يوضِّح هذا الدليل كيفية إتاحة التحديثات داخل التطبيق في تطبيقك باستخدام الرموز البرمجية الأصلية (C أو C++ ). وتتوفّر أدلة منفصلة للحالات التي يستخدم فيها التنفيذ لغة برمجة Kotlin أو لغة برمجة Java، والحالات التي يستخدم فيها التنفيذ Unity.
نظرة عامة على حزمة تطوير البرامج (SDK) المدمجة مع المحتوى
تعتبر حزمة تطوير البرامج (SDK) الأصلية لـ Play Core جزءًا من مجموعة Play Core
SDK. تحتوي حزمة تطوير البرامج (SDK) الأصلية على ملف رأس C، app_update.h
، الذي يلتف
AppUpdateManager
من مكتبة التحديثات داخل التطبيق في Java Play. يسمح ملف الرأس هذا لتطبيقك باستدعاء واجهة برمجة التطبيقات
للحصول على تحديثات داخل التطبيق مباشرةً من الرمز الأصلي.
إعداد بيئة التطوير
تنزيل Play Core Native SDK
قبل التنزيل، يجب الموافقة على الأحكام والشروط التالية.
الأحكام والشروط
Last modified: September 24, 2020- 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.
- For purposes of these terms, "APIs" means Google's APIs, other developer services, and associated software, including any Redistributable Code.
- “Redistributable Code” means Google-provided object code or header files that call the APIs.
- 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.
- 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.
عليك القيام بأي مما يلي:
- ثبِّت الإصدار 4.0 من استوديو Android أو إصدارًا أحدث. استخدِم واجهة مستخدم SDK Manager لتثبيت الإصدار 10.0 من Android SDK Platform (المستوى 29 من واجهة برمجة التطبيقات).
- ثبِّت أدوات سطر أوامر Android SDK واستخدِم
sdkmanager
لتثبيت Android SDK Platform الإصدار 10.0 (المستوى 29 من واجهة برمجة التطبيقات).
يمكنك إعداد Android Studio لتطوير البرامج الأصلية باستخدام SDK Manager لتثبيت أحدث إصدار من CMake وAndroid Native Development Kit. لمزيد من المعلومات حول إنشاء أو استيراد مشاريع النصوص البرمجية الأصلية، يمكنك الاطّلاع على بدء استخدام NDK.
قم بتنزيل ملف ZIP واستخرجه إلى جانب مشروعك.
رابط التنزيل حجم الملف المجموع الاختباري لخوارزمية SHA-256 36 ميبيبايت 782a8522d937848c83a715c9a258b95a3ff2879a7cd71855d137b41c00786a5e حدِّث ملف
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.0.0' implementation 'com.google.android.play:asset-delivery:2.0.0' implementation 'com.google.android.play:integrity:1.0.1' implementation 'com.google.android.play:review:2.0.0' // Import these common dependencies. implementation 'com.google.android.gms:play-services-tasks:18.0.2' implementation files("$playcoreDir/playcore-native-metadata.jar") ... }
Kotlin
// 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.0.0") implementation("com.google.android.play:asset-delivery:2.0.0") implementation("com.google.android.play:integrity:1.0.1") implementation("com.google.android.play:review:2.0.0") // Import these common dependencies. implementation("com.google.android.gms:play-services-tasks:18.0.2") implementation(files("$playcoreDir/playcore-native-metadata.jar")) ... }
حدِّث ملفات
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 SDK البيانات المتعلّقة بالإصدار للسماح لشركة Google بتحسين المنتج، بما في ذلك:
- اسم حزمة التطبيق
- إصدار حزمة التطبيق
- إصدار Play Core Native SDK
سيتم جمع هذه البيانات عند تحميل حزمة تطبيقك
على Play Console. لإيقاف عملية جمع البيانات هذه، عليك إزالة
استيراد "$playcoreDir/playcore-native-metadata.jar
" في ملف Build.gradle.
تجدُر الإشارة إلى أنّ عملية جمع البيانات هذه المتعلّقة باستخدامك لحزمة Play Core Native SDK واستخدام Google للبيانات التي يتم جمعها هي عملية منفصلة ومستقلة عن مجموعة Google من تبعيات المكتبة التي تم تعريفها في Gradle عند تحميل حزمة تطبيقك إلى Play Console.
بعد دمج Play Core Native SDK في مشروعك، يمكنك تضمين السطر التالي في الملفات التي تحتوي على طلبات بيانات من واجهة برمجة التطبيقات:
#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 قيمة عدد صحيح تتراوح بين 0 و5، ويكون الرقم 0 هو القيمة التلقائية و5 يشير إلى الأولوية القصوى. لضبط أولوية أحد التحديثات، استخدِم الحقل inAppUpdatePriority
ضمن
Edits.tracks.releases
في واجهة برمجة التطبيقات Google Play Developer API. تُعد جميع الإصدارات المضافة حديثًا في
الإصدار نفس أولوية الإصدار. لا يمكن ضبط الأولوية إلا عند
طرح إصدار جديد ولا يمكن تغييرها لاحقًا.
حدِّد الأولوية باستخدام واجهة برمجة التطبيقات Google Play Developer API، كما هو موضَّح في مستندات
Play Developer API.
حدِّد أولوية التحديث داخل التطبيق في المرجع
Edit.tracks
الذي تم تمريره في طريقة
Edit.tracks: update
. يوضّح المثال التالي إطلاق تطبيق برمز الإصدار 88 و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()
لطلب عملية التحديث بشكل غير متزامن، مع إدخال نشاط 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.
}
}
يمكنك إخلاء الموارد من خلال استدعاء وظيفة
AppUpdateManager_destroy()
بعد انتهاء تطبيقك من استخدام واجهة برمجة التطبيقات.
خطأ أثناء المعالجة
يوضِّح هذا القسم حلولاً للأخطاء الشائعة المُشار إليها بقيم محدّدة في AppUpdateErrorCode
:
- يشير رمز الخطأ
-110, APP_UPDATE_INITIALIZATION_NEEDED
إلى أنّه لم يتم إعداد واجهة برمجة التطبيقات بنجاح. استدعِAppUpdateManager_init()
لإعداد واجهة برمجة التطبيقات. - يشير رمز الخطأ
-4, APP_UPDATE_INVALID_REQUEST
إلى أن بعض معلَمات طلب تدفق التعديل قد تمت كتابتها بشكل غير صحيح. تأكَّد من أنّ العنصرَينAppUpdateInfo
وAppUpdateOptions
ليسا فارغَين ومن أنّهما منسقان بشكل صحيح. - يشير رمز الخطأ
-5, APP_UPDATE_UNAVAILABLE
إلى عدم توفّر تحديث. تأكَّد من أنّ الإصدار المستهدَف يتضمّن نفس اسم الحزمة ورقم تعريف التطبيق ومفتاح التوقيع. في حال توفُّر تحديث، امحُ ذاكرة التخزين المؤقت للتطبيق واطلبAppUpdateManager_requestAppUpdateInfo()
مرة أخرى لإعادة تحميلAppUpdateInfo
. - يشير رمز الخطأ
-6, APP_UPDATE_NOT_ALLOWED
إلى أنّ نوع التعديل المُشار إليه من خلال الكائنAppUpdateOption
غير مسموح به. قبل بدء عملية التحديث، تأكَّد مما إذا كان العنصرAppUpdateInfo
يشير إلى أنّ نوع التحديث مسموح به.
الخطوات التالية
اختبِر تحديثات تطبيقك داخل التطبيق للتأكّد من أنّ عملية الدمج تعمل بشكل صحيح.