پشتیبانی از به‌روزرسانی‌های درون‌برنامه (بومی)

این راهنما نحوه پشتیبانی از به‌روزرسانی‌های درون‌برنامه را در برنامه‌تان بااستفاده از کد بومی (C یا C++) شرح می‌دهد. راهنماهای جداگانه‌ای برای مواردی که پیاده‌سازی شما از زبان برنامه‌نویسی Kotlin یا زبان برنامه‌نویسی Java استفاده می‌کند و مواردی که پیاده‌سازی شما از Unity یا Unreal Engine استفاده می‌کند وجود دارد.

نمای کلی کیت توسعه نرم‌افزار بومی

«کیت توسعه نرم‌افزار Play Core Native» بخشی از خانواده کیت توسعه نرم‌افزار Play Core است. کیت توسعه نرم‌افزار Native حاوی فایل سرایند C، app_update.h، است که AppUpdateManager را از «کتابخانه به‌روزرسانی درون‌برنامه Java Play» می‌پوشاند. این فایل سرایند به برنامه شما اجازه می‌دهد میانای برنامه‌سازی کاربردی را برای به‌روزرسانی‌های درون‌برنامه مستقیماً از کد بومی‌تان فراخوانی کند.

راه‌اندازی محیط توسعه نرم‌افزار

دانلود کنید Play Core Native SDK

قبل از دانلود، باید با شرایط و ضوابط زیر موافقت کنید.

شرایط و ضوابط

Last modified: September 24, 2020
  1. By using the Play Core Software Development Kit, you agree to these terms in addition to the Google APIs Terms of Service ("API ToS"). If these terms are ever in conflict, these terms will take precedence over the API ToS. Please read these terms and the API ToS carefully.
  2. For purposes of these terms, "APIs" means Google's APIs, other developer services, and associated software, including any Redistributable Code.
  3. “Redistributable Code” means Google-provided object code or header files that call the APIs.
  4. Subject to these terms and the terms of the API ToS, you may copy and distribute Redistributable Code solely for inclusion as part of your API Client. Google and its licensors own all right, title and interest, including any and all intellectual property and other proprietary rights, in and to Redistributable Code. You will not modify, translate, or create derivative works of Redistributable Code.
  5. Google may make changes to these terms at any time with notice and the opportunity to decline further use of the Play Core Software Development Kit. Google will post notice of modifications to the terms at https://developer.android.com/guide/playcore/license. Changes will not be retroactive.
دانلود کنید Play Core Native SDK

play-core-native-sdk-1.16.0.zip

  1. یکی از کارهای زیر را انجام دهید:

    • Android Studio نسخه ۴.۰ یا بالاتر را نصب کنید. از میانای کاربر «مدیر کیت توسعه نرم‌افزار» برای نصب نسخه ۱۰.۰ پلاتفرم کیت توسعه نرم‌افزار Android (سطح میانای برنامه‌سازی کاربردی ۲۹) استفاده کنید.
    • ابزارهای خط فرمان کیت توسعه نرم‌افزار Android را نصب کنید و از sdkmanager برای نصب نسخه ۱۰.۰ پلاتفرم کیت توسعه نرم‌افزار Android (سطح میانای برنامه‌سازی کاربردی ۲۹) استفاده کنید.
  2. بااستفاده از مدیر SDK، «استودیو Android» را برای توسعه بومی آماده کنید تا جدیدترین نسخه‌های CMake و «کیت توسعه بومی Android»‏ (NDK) را نصب کنید. برای اطلاعات بیشتر درباره ایجاد یا وارد کردن پروژه‌های بومی، به شروع به کار با NDK مراجعه کنید.

  3. فایل zip را بارگیری کنید و آن را در کنار پروژه‌تان از حالت فشرده خارج کنید.

    بارگیری پیوند اندازه جمع‌آزمای SHA-256
    ‫۵۴٫۸ مبی‌بایت 008b8fedc6179a6dc6ccc21af75591afc7036f78f3d5559d844f1b923934fef0
  4. فایل build.gradle برنامه‌تان را به‌صورت زیر به‌روز کنید:

    شیک

        // App build.gradle
    
        plugins {
          id 'com.android.application'
        }
    
        // Define a path to the extracted Play Core SDK files.
        // If using a relative path, wrap it with file() since CMake requires absolute paths.
        def playcoreDir = file('../path/to/playcore-native-sdk')
    
        android {
            defaultConfig {
                ...
                externalNativeBuild {
                    cmake {
                        // Define the PLAYCORE_LOCATION directive.
                        arguments "-DANDROID_STL=c++_static",
                                  "-DPLAYCORE_LOCATION=$playcoreDir"
                    }
                }
                ndk {
                    // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                    abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                }
            }
            buildTypes {
                release {
                    // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                    proguardFile '$playcoreDir/proguard/common.pgcfg'
                    proguardFile '$playcoreDir/proguard/gms_task.pgcfg'
                    proguardFile '$playcoreDir/proguard/per-feature-proguard-files'
                    ...
                }
                debug {
                    ...
                }
            }
            externalNativeBuild {
                cmake {
                    path 'src/main/CMakeLists.txt'
                }
            }
        }
    
        dependencies {
            // Import these feature-specific AARs for each Google Play Core library.
            implementation 'com.google.android.play:app-update:2.1.0'
            implementation 'com.google.android.play:asset-delivery:2.3.0'
            implementation 'com.google.android.play:integrity:1.6.0'
            implementation 'com.google.android.play:review:2.0.2'
    
            // Import these common dependencies.
            implementation 'com.google.android.gms:play-services-tasks:18.0.2'
            implementation files("$playcoreDir/playcore-native-metadata.jar")
            ...
        }
        

    کاتلین

    // App build.gradle
    
    plugins {
        id("com.android.application")
    }
    
    // Define a path to the extracted Play Core SDK files.
    // If using a relative path, wrap it with file() since CMake requires absolute paths.
    val playcoreDir = file("../path/to/playcore-native-sdk")
    
    android {
        defaultConfig {
            ...
            externalNativeBuild {
                cmake {
                    // Define the PLAYCORE_LOCATION directive.
                    arguments += listOf("-DANDROID_STL=c++_static", "-DPLAYCORE_LOCATION=$playcoreDir")
                }
            }
            ndk {
                // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                abiFilters.clear()
                abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
            }
        }
        buildTypes {
            release {
                // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                proguardFile("$playcoreDir/proguard/common.pgcfg")
                proguardFile("$playcoreDir/proguard/gms_task.pgcfg")
                proguardFile("$playcoreDir/proguard/per-feature-proguard-files")
                ...
            }
            debug {
                ...
            }
        }
        externalNativeBuild {
            cmake {
                path = "src/main/CMakeLists.txt"
            }
        }
    }
    
    dependencies {
        // Import these feature-specific AARs for each Google Play Core library.
        implementation("com.google.android.play:app-update:2.1.0")
        implementation("com.google.android.play:asset-delivery:2.3.0")
        implementation("com.google.android.play:integrity:1.6.0")
        implementation("com.google.android.play:review:2.0.2")
    
        // Import these common dependencies.
        implementation("com.google.android.gms:play-services-tasks:18.0.2")
        implementation(files("$playcoreDir/playcore-native-metadata.jar"))
        ...
    }
  5. فایل‌های CMakeLists.txt برنامه‌تان را همان‌طور که در زیر نشان داده شده است به‌روز کنید:

    cmake_minimum_required(VERSION 3.6)
    
    ...
    
    # Add a static library called “playcore” built with the c++_static STL.
    include(${PLAYCORE_LOCATION}/playcore.cmake)
    add_playcore_static_library()
    
    // In this example “main” is your native code library, i.e. libmain.so.
    add_library(main SHARED
            ...)
    
    target_include_directories(main PRIVATE
            ${PLAYCORE_LOCATION}/include
            ...)
    
    target_link_libraries(main
            android
            playcore
            ...)
    

گردآوری داده‌ها

«کیت توسعه نرم‌افزار Play Core Native» ممکن است داده‌های مربوط به نسخه را جمع‌آوری کند تا به Google اجازه دهد محصول را بهبود بخشد، ازجمله:

  • نام بسته برنامه
  • نسخه بسته برنامه
  • نسخه Play Core Native SDK

این داده‌ها هنگام بارگذاری بسته برنامه‌تان در «کنسول Play» جمع‌آوری می‌شود. برای انصراف از این فرایند جمع‌آوری داده، $playcoreDir/playcore-native-metadata.jar را از فایل build.gradle بردارید.

توجه داشته باشید که این جمع‌آوری داده مربوط به استفاده شما از Play Core Native SDK و استفاده Google از داده‌های جمع‌آوری‌شده جدا و مستقل از جمع‌آوری وابستگی‌های کتابخانه توسط Google است که در Gradle هنگام بارگذاری بسته برنامه‌تان در «کنسول Play» اعلام شده است.

پس‌از ادغام Play Core Native SDK در پروژه‌تان، خط زیر را در فایل‌هایی که حاوی فراخوانی‌های API هستند اضافه کنید:

#include "play/app_update.h"

مقداردهی اولیه میانای برنامه‌سازی کاربردی به‌روزرسانی درون‌برنامه

هرگاه از میانای برنامه‌سازی کاربردی به‌روزرسانی درون‌برنامه استفاده می‌کنید، ابتدا آن را با فراخوانی تابع AppUpdateManager_init() مقداردهی اولیه کنید، همان‌طور که در مثال زیر که با android_native_app_glue.h ساخته شده است نشان داده شده است:

void android_main(android_app* app) {
  app->onInputEvent = HandleInputEvent;

  AppUpdateErrorCode error_code =
    AppUpdateManager_init(app->activity->vm, app->activity->clazz);
  if (error_code == APP_UPDATE_NO_ERROR) {
    // You can use the API.
  }
}

بررسی دردسترس بودن به‌روزرسانی

قبل‌از درخواست به‌روزرسانی، بررسی کنید که آیا به‌روزرسانی برای برنامه‌تان دردسترس است یا نه. AppUpdateManager_requestInfo() درخواست ناهمگامی را شروع می‌کند که اطلاعات لازم را برای راه‌اندازی جریان به‌روزرسانی درون‌برنامه در آینده جمع‌آوری می‌کند. اگر درخواست باموفقیت شروع شود، تابع APP_UPDATE_NO_ERROR را برمی‌گرداند.

AppUpdateErrorCode error_code = AppUpdateManager_requestInfo()

if (error_code == APP_UPDATE_NO_ERROR) {
    // The request has successfully started, check the result using
    // AppUpdateManager_getInfo.
}

می‌توانید فرایند جاری و نتیجه درخواست را بااستفاده از AppUpdateManager_getInfo() پیگیری کنید. علاوه‌بر کد خطا، این تابع یک ساختار مات AppUpdateInfo را برمی‌گرداند که می‌توانید از آن برای بازیابی اطلاعات مربوط به درخواست به‌روزرسانی استفاده کنید. برای مثال، ممکن است بخواهید این تابع را در هر حلقه بازی فراخوانی کنید تا زمانی که نتیجه غیرتهی برای info برگرداند:

AppUpdateInfo* info;
GameUpdate() {

   // Keep calling this in every game loop until info != nullptr
   AppUpdateErrorCode error_code = AppUpdateManager_getInfo(&info);

   if (error_code == APP_UPDATE_NO_ERROR && info != nullptr) {
       // Successfully started, check the result in the following functions
   }
...
}

بررسی قدیمی بودن به‌روزرسانی

علاوه‌بر بررسی اینکه آیا به‌روزرسانی دردسترس است یا نه، ممکن است بخواهید بررسی کنید که از آخرین باری که کاربر ازطریق «فروشگاه Play» از به‌روزرسانی مطلع شده است، چقدر زمان گذشته است. این کار می‌تواند به شما کمک کند تصمیم بگیرید که آیا باید به‌روزرسانی انعطاف‌پذیر را شروع کنید یا به‌روزرسانی فوری. برای مثال، ممکن است چند روز صبر کنید و سپس با به‌روزرسانی انعطاف‌پذیر به کاربر اطلاع دهید، و چند روز بعداز آن به‌روزرسانی فوری را الزامی کنید.

از AppUpdateInfo_getClientVersionStalenessDays() برای بررسی تعداد روزهایی که از دردسترس قرار گرفتن به‌روزرسانی ازطریق «فروشگاه Play» گذشته است استفاده کنید:

int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);

بررسی اولویت به‌روزرسانی

Google Play Developer API به شما امکان می‌دهد اولویت هر به‌روزرسانی را تنظیم کنید. این به برنامه شما اجازه می‌دهد تصمیم بگیرد که با چه شدتی به‌روزرسانی را به کاربر توصیه کند. برای مثال، استراتژی زیر را برای تنظیم اولویت به‌روزرسانی درنظر بگیرید:

  • بهبودهای جزئی در واسط کاربر: به‌روزرسانی با اولویت پایین؛ نه به‌روزرسانی انعطاف‌پذیر درخواست کنید و نه به‌روزرسانی فوری. فقط زمانی به‌روزرسانی کنید که کاربر با برنامه‌تان تعامل ندارد.
  • بهبود عملکرد: به‌روزرسانی اولویت متوسط؛ درخواست به‌روزرسانی انعطاف‌پذیر.
  • به‌روزرسانی امنیتی مهم: به‌روزرسانی اولویت بالا؛ درخواست به‌روزرسانی فوری.

برای تعیین اولویت، Google Play از یک مقدار عدد صحیح بین ۰ و ۵ استفاده می‌کند که ۰ پیش‌فرض و ۵ بالاترین اولویت است. برای تنظیم اولویت به‌روزرسانی، از فیلد inAppUpdatePriority در بخش Edits.tracks.releases در Google Play Developer API استفاده کنید. همه نسخه‌های جدید اضافه‌شده در نسخه پخش دارای اولویت یکسان با نسخه پخش درنظر گرفته می‌شوند. اولویت را فقط هنگام عرضه نسخه جدید می‌توان تنظیم کرد و بعداً نمی‌توان آن را تغییر داد.

اولویت را بااستفاده از Google Play Developer API تنظیم کنید، همان‌طور که در سند Play Developer API شرح داده شده است. اولویت به‌روزرسانی درون‌برنامه را در منبع Edit.tracks که در روش Edit.tracks: update ارسال شده است مشخص کنید. مثال زیر انتشار برنامه‌ای با کد نسخه ۸۸ و inAppUpdatePriority ۵ را نشان می‌دهد:

{
  "releases": [{
      "versionCodes": ["88"],
      "inAppUpdatePriority": 5,
      "status": "completed"
  }]
}

در کد برنامه‌تان، می‌توانید سطح اولویت را برای به‌روزرسانی داده‌شده بااستفاده از AppUpdateInfo_getPriority() بررسی کنید:

int32_t priority = AppUpdateInfo_getPriority(info);

شروع به‌روزرسانی

پس‌از اینکه تأیید کردید به‌روزرسانی دردسترس است، می‌توانید بااستفاده از AppUpdateManager_requestStartUpdate() درخواست به‌روزرسانی کنید. قبل‌از درخواست به‌روزرسانی، شیء AppUpdateInfo به‌روز را دریافت کنید و شیء AppUpdateOptions را برای پیکربندی جریان به‌روزرسانی ایجاد کنید. شیء AppUpdateOptions گزینه‌هایی را برای جریان به‌روزرسانی درون‌برنامه تعریف می‌کند، ازجمله اینکه به‌روزرسانی باید انعطاف‌پذیر باشد یا فوری.

مثال زیر یک شیء AppUpdateOptions برای جریان به‌روزرسانی انعطاف‌پذیر ایجاد می‌کند:

// Creates an AppUpdateOptions configuring a flexible in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_FLEXIBLE, &options);

مثال زیر یک شیء AppUpdateOptions برای جریان به‌روزرسانی فوری ایجاد می‌کند:

// Creates an AppUpdateOptions configuring an immediate in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_IMMEDIATE, &options);

شیء AppUpdateOptions همچنین حاوی فیلد AllowAssetPackDeletion است که تعیین می‌کند آیا به‌روزرسانی مجاز است بسته‌های دارایی را درصورت محدود بودن فضای ذخیره‌سازی دستگاه پاک کند یا نه. این فیلد به‌طور پیش‌فرض روی false تنظیم شده است، اما می‌توانید از روش AppUpdateOptions_setAssetPackDeletionAllowed() برای تنظیم آن روی true استفاده کنید:

bool allow = true;
AppUpdateErrorCode error_code = AppUpdateOptions_setAssetPackDeletionAllowed(options, allow);

پس‌از اینکه شیء AppUpdateInfo به‌روز و شیء AppUpdateOptions به‌درستی پیکربندی‌شده را داشتید، AppUpdateManager_requestStartUpdate() را فراخوانی کنید تا به‌طور ناهمگام جریان به‌روزرسانی را درخواست کنید و Android Activity jobject را برای پارامتر نهایی ارسال کنید.

AppUpdateErrorCode request_error_code =
AppUpdateManager_requestStartUpdate(info, options, app->activity->clazz);

برای آزاد کردن منابع، نمونه‌های AppUpdateInfo و AppUpdateOptions را که دیگر نیاز ندارید با فراخوانی AppUpdateInfo_destroy() و AppUpdateOptions_destroy() به‌ترتیب منتشر کنید.

AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);

برای جریان به‌روزرسانی فوری، Google Play صفحه تأیید کاربر را نمایش می‌دهد. وقتی کاربر درخواست را می‌پذیرد، Google Play به‌طور خودکار به‌روزرسانی را در پیش‌زمینه بارگیری و نصب می‌کند، سپس اگر نصب موفقیت‌آمیز باشد، برنامه را با نسخه به‌روزشده بازراه‌اندازی می‌کند.

برای جریان به‌روزرسانی انعطاف‌پذیر، می‌توانید همچنان درخواست اشیاء به‌روز AppUpdateInfo را بدهید تا وضعیت به‌روزرسانی فعلی را درحین تعامل کاربر با برنامه پیگیری کنید. پس‌از تکمیل موفقیت‌آمیز بارگیری، باید با فراخوانی AppUpdateManager_requestCompleteUpdate()، تکمیل به‌روزرسانی را راه‌اندازی کنید، همان‌طور که در مثال زیر نشان داده شده است:

AppUpdateStatus status = AppUpdateInfo_getStatus(info);
if (status == APP_UPDATE_DOWNLOADED) {
    AppUpdateErrorCode error_code = AppUpdateManager_requestCompleteUpdate();
    if (error_code != APP_UPDATE_NO_ERROR)
    {
      // There was an error while completing the update flow.
    }
}

با فراخوانی تابع AppUpdateManager_destroy() پس‌از اتمام استفاده برنامه‌تان از API، منابع را آزاد کنید.

مدیریت کردن خطا

این بخش راه‌حل‌هایی برای خطاهای رایج نشان‌داده‌شده با مقادیر خاص AppUpdateErrorCode را شرح می‌دهد:

  • کد خطای -110, APP_UPDATE_INITIALIZATION_NEEDED نشان می‌دهد که API با موفقیت مقداردهی اولیه نشده است. برای مقداردهی اولیه میانای برنامه‌سازی کاربردی، AppUpdateManager_init() را فراخوانی کنید.
  • کد خطای -4, APP_UPDATE_INVALID_REQUEST نشان می‌دهد که برخی از پارامترهای درخواست جریان به‌روزرسانی بدشکل است. بررسی کنید تا مطمئن شوید که اشیاء AppUpdateInfo و AppUpdateOptions تهی نیستند و به‌درستی قالب‌بندی شده‌اند.
  • کد خطای -5, APP_UPDATE_UNAVAILABLE نشان می‌دهد که هیچ به‌روزرسانی قابل‌اجرایی دردسترس نیست. مطمئن شوید که نسخه هدف دارای همان نام بسته، شناسه برنامه، و کلید امضا باشد. اگر به‌روزرسانی دردسترس است، حافظه نهان برنامه را پاک کنید و دوباره با AppUpdateManager_requestAppUpdateInfo() تماس بگیرید تا AppUpdateInfo بازآوری شود.
  • کد خطای -6, APP_UPDATE_NOT_ALLOWED نشان می‌دهد که نوع به‌روزرسانی نشان‌داده‌شده توسط شیء AppUpdateOption مجاز نیست. قبل‌از شروع جریان به‌روزرسانی، بررسی کنید که آیا شیء AppUpdateInfo نشان می‌دهد که نوع به‌روزرسانی مجاز است یا نه.

مراحل بعدی

به‌روزرسانی‌های درون‌برنامه برنامه‌تان را آزمایش کنید تا مطمئن شوید ادغام به‌درستی کار می‌کند.