คู่มือนี้อธิบายวิธีรองรับการอัปเดตในแอปในแอปโดยใช้โค้ดแบบเนทีฟ (C หรือ C++) โดยมีคู่มือแยกต่างหากสำหรับกรณีที่การติดตั้งใช้งานใช้ภาษาโปรแกรม Kotlin หรือภาษาโปรแกรม Java และกรณีที่การติดตั้งใช้งานใช้ Unity หรือ Unreal Engine
ภาพรวมของ SDK แบบเนทีฟ
Play Core Native SDK เป็นส่วนหนึ่งของตระกูล Play Core SDK SDK แบบเนทีฟมีไฟล์ส่วนหัว C app_update.h ซึ่งรวม AppUpdateManager จากไลบรารีการอัปเดตแอปในแอปของ Google Play สำหรับ Java ไฟล์ส่วนหัวนี้ช่วยให้แอปเรียกใช้ API สำหรับการอัปเดตในแอปได้โดยตรงจากโค้ดแบบเนทีฟ
ตั้งค่าสภาพแวดล้อมในการพัฒนาซอฟต์แวร์
ดาวน์โหลด 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.
เลือกดำเนินการอย่างหนึ่งดังต่อไปนี้
- ติดตั้ง Android Studio เวอร์ชัน 4.0 ขึ้นไป ใช้ UI ของเครื่องมือจัดการ SDK เพื่อติดตั้ง Android SDK Platform เวอร์ชัน 10.0 (ระดับ API 29)
- ติดตั้งเครื่องมือบรรทัดคำสั่ง Android SDK และใช้
sdkmanagerเพื่อติดตั้งแพลตฟอร์ม Android SDK เวอร์ชัน 10.0 (ระดับ API 29)
เตรียม Android Studio สำหรับการพัฒนาแบบเนทีฟโดยใช้เครื่องมือจัดการ SDK เพื่อติดตั้ง CMake และ Android Native Development Kit (NDK) เวอร์ชันล่าสุด ดูข้อมูลเพิ่มเติมเกี่ยวกับการสร้างหรือนำเข้าโปรเจ็กต์เนทีฟได้ที่เริ่มต้นใช้งาน NDK
ดาวน์โหลดไฟล์ ZIP และแตกไฟล์ไว้ข้างโปรเจ็กต์
ลิงก์ดาวน์โหลด ขนาด การตรวจสอบข้อผิดพลาดด้วย SHA-256 54.8 MiB 008b8fedc6179a6dc6ccc21af75591afc7036f78f3d5559d844f1b923934fef0 อัปเดตไฟล์
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") ... }
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.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")) ... }
อัปเดตไฟล์
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 นั้นแยกต่างหากและไม่เกี่ยวข้องกับการเก็บรวบรวมทรัพยากร Dependency ของไลบรารีที่ประกาศใน Gradle ของ Google เมื่อคุณอัปโหลดแพ็กเกจแอปไปยัง Play Console
หลังจากผสานรวม Play Core Native SDK เข้ากับโปรเจ็กต์แล้ว ให้ใส่บรรทัดต่อไปนี้ในไฟล์ที่มีการเรียก API
#include "play/app_update.h"
เริ่มต้น API การอัปเดตแอป
เมื่อใดก็ตามที่คุณใช้ 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 ซึ่งคุณสามารถใช้เพื่อดึงข้อมูลเกี่ยวกับคำขออัปเดตได้ ตัวอย่างเช่น คุณอาจต้องการเรียกใช้ฟังก์ชันนี้ใน Game Loop ทุกครั้งจนกว่าจะแสดงผลลัพธ์ที่ไม่ใช่ค่า Null สำหรับ 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 Store ซึ่งจะช่วยให้คุณตัดสินใจได้ว่าควรเริ่มการอัปเดตแบบยืดหยุ่นหรือการอัปเดตทันที ตัวอย่างเช่น คุณอาจรอ 2-3 วันก่อนแจ้งให้ผู้ใช้ทราบด้วยการอัปเดตแบบยืดหยุ่น และรออีก 2-3 วันหลังจากนั้นก่อนที่จะกำหนดให้ต้องอัปเดตทันที
ใช้ AppUpdateInfo_getClientVersionStalenessDays() เพื่อตรวจสอบจำนวนวันนับตั้งแต่การอัปเดตพร้อมใช้งานผ่าน Play Store ดังนี้
int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);
ตรวจสอบลำดับความสำคัญของการอัปเดต
Google Play Developer API ช่วยให้คุณกำหนดลำดับความสำคัญของการอัปเดตแต่ละรายการได้ ซึ่งจะช่วยให้แอปตัดสินใจได้ว่าจะแนะนำการอัปเดตให้ผู้ใช้มากน้อยเพียงใด ตัวอย่างเช่น ลองพิจารณากลยุทธ์ต่อไปนี้สำหรับการตั้งค่าลำดับความสำคัญของการอัปเดต
- การปรับปรุง UI เล็กน้อย: การอัปเดตลำดับความสำคัญต่ำ ไม่ต้องขอการอัปเดตแบบยืดหยุ่นหรือการอัปเดตทันที อัปเดตเฉพาะเมื่อผู้ใช้ไม่ได้โต้ตอบกับแอปเท่านั้น
- การปรับปรุงประสิทธิภาพ: การอัปเดตลำดับความสำคัญปานกลาง ขอการอัปเดตที่ยืดหยุ่น
- การอัปเดตความปลอดภัยที่สำคัญ: การอัปเดตที่มีลำดับความสำคัญสูง ขอให้อัปเดตทันที
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 ที่กำหนดว่าการอัปเดตได้รับอนุญาตให้ล้างAsset Packหรือไม่ในกรณีที่พื้นที่เก็บข้อมูลของอุปกรณ์มีจำกัด ระบบจะตั้งค่าช่องนี้เป็น 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()เพื่อเริ่มต้น API - รหัสข้อผิดพลาด
-4, APP_UPDATE_INVALID_REQUESTบ่งชี้ว่าพารามิเตอร์บางรายการของคำขอขั้นตอนการอัปเดตมีรูปแบบไม่ถูกต้อง ตรวจสอบว่าออบเจ็กต์AppUpdateInfoและAppUpdateOptionsไม่เป็นค่า Null และมีรูปแบบที่ถูกต้อง - รหัสข้อผิดพลาด
-5, APP_UPDATE_UNAVAILABLEบ่งชี้ว่าไม่มีการอัปเดตที่เกี่ยวข้องพร้อมใช้งาน ตรวจสอบว่าเวอร์ชันเป้าหมายมีชื่อแพ็กเกจ รหัสแอปพลิเคชัน และคีย์ Signing เดียวกัน หากมีอัปเดตพร้อมใช้งาน ให้ล้างแคชของแอปแล้วโทรหาAppUpdateManager_requestAppUpdateInfo()อีกครั้งเพื่อรีเฟรชAppUpdateInfo - รหัสข้อผิดพลาด
-6, APP_UPDATE_NOT_ALLOWEDบ่งชี้ว่าไม่อนุญาตให้ใช้ประเภทการอัปเดตที่ระบุโดยออบเจ็กต์AppUpdateOptionตรวจสอบว่าออบเจ็กต์AppUpdateInfoระบุว่าอนุญาตให้อัปเดตประเภทนี้หรือไม่ก่อนเริ่มขั้นตอนการอัปเดต
ขั้นตอนถัดไป
ทดสอบการอัปเดตในแอปของแอปเพื่อยืนยันว่าการผสานรวมทำงานอย่างถูกต้อง