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

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

مرور کلی SDK بومی

کیت توسعه نرم‌افزار بومی Play Core بخشی از خانواده کیت توسعه نرم‌افزار بومی Play Core است. کیت توسعه نرم‌افزار بومی شامل یک فایل هدر C app_update.h است که AppUpdateManager از کتابخانه به‌روزرسانی درون‌برنامه‌ای Java Play در بر می‌گیرد. این فایل هدر به برنامه شما اجازه می‌دهد تا API را برای به‌روزرسانی‌های درون‌برنامه‌ای مستقیماً از کد بومی خود فراخوانی کند.

محیط توسعه خود را تنظیم کنید

دانلود کنید 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.15.4.zip

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

  2. با استفاده از SDK Manager و نصب آخرین نسخه CMake و Android Native Development Kit (NDK)، اندروید استودیو را برای توسعه بومی آماده کنید. برای اطلاعات بیشتر در مورد ایجاد یا وارد کردن پروژه‌های بومی، به بخش «شروع کار با NDK» مراجعه کنید.

  3. فایل زیپ را دانلود کنید و آن را در کنار پروژه خود استخراج کنید.

    لینک دانلود اندازه بررسی SHA-256
    ۳۹.۶ مگابایت 92b43246860d4ce4772a3a0786212d9b4781920e112d81b93ca1c5ebd8da89cb
  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.5.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.5.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 ممکن است داده‌های مربوط به نسخه را جمع‌آوری کند تا به گوگل امکان بهبود محصول را بدهد، از جمله:

  • نام بسته برنامه
  • نسخه بسته برنامه
  • نسخه Core Native SDK را اجرا کنید

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

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

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

#include "play/app_update.h"

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

هر زمان که از API به‌روزرسانی درون‌برنامه‌ای استفاده می‌کنید، ابتدا آن را با فراخوانی تابع 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);

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

رابط برنامه‌نویسی کاربردی توسعه‌دهندگان گوگل پلی به شما امکان می‌دهد اولویت هر به‌روزرسانی را تعیین کنید. این به برنامه شما اجازه می‌دهد تا تصمیم بگیرد که با چه شدتی یک به‌روزرسانی را به کاربر توصیه کند. برای مثال، استراتژی زیر را برای تنظیم اولویت به‌روزرسانی در نظر بگیرید:

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

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

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

{
  "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() برای درخواست ناهمگام یک جریان به‌روزرسانی فراخوانی کنید و یک jobject jobActivity اندروید را برای پارامتر نهایی ارسال کنید.

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

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

AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);

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

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

مراحل بعدی

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