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

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

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

«کیت توسعه نرم‌افزار بومی Play Core» بخشی از خانواده کیت توسعه نرم‌افزار Play Core است. «کیت توسعه نرم‌افزار بومی» شامل فایل سرصفحه 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 SDK Platform نسخه ۱۰.۰ (سطح میانای برنامه کاربردی ۲۹) استفاده کنید.
    • ابزارهای خط فرمان کیت توسعه نرم‌افزار Android را نصب کنید و از sdkmanager برای نصب نسخه پلاتفرم کیت توسعه نرم‌افزار Android 10.0 (سطح میانای برنامه کاربردی ۲۹) استفاده کنید.
  2. بااستفاده از مدیر کیت توسعه نرم‌افزار برای نصب جدیدترین CMake و Android Native Development Kit (NDK)، «استودیو Android» را برای توسعه بومی آماده کنید. برای اطلاعات بیشتر درباره ایجاد یا وارد کردن پروژه‌های بومی، به شروع به کار با 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» ممکن است داده‌های مربوط به نسخه را جمع‌آوری کند تا به Google اجازه دهد محصول را بهبود دهد، ازجمله:

  • نام بسته برنامه
  • نسخه بسته برنامه
  • نسخه «کیت توسعه نرم‌افزار بومی Play Core»

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

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

پس‌از ادغام کردن «کیت توسعه نرم‌افزار بومی Play Core» در پروژه‌تان، خط زیر را در فایل‌هایی که حاوی فراخوانی‌های میانای برنامه‌سازی کاربردی هستند اضافه کنید:

#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» 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.
    }
}

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

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

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

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

مراحل بعدی

برای تأیید اینکه یکپارچه‌سازی شما به‌درستی کار می‌کند، به‌روزرسانی‌های درون‌برنامه برنامه‌تان را آزمایش کنید.