Panduan ini menjelaskan cara mendukung update dalam aplikasi di aplikasi Anda menggunakan Kotlin atau Java. Ada panduan terpisah untuk kasus saat implementasi Anda menggunakan kode native (C/C++) dan kasus saat implementasi Anda menggunakan Unity atau Unreal Engine.
Menyiapkan lingkungan pengembangan
Library Play In-App Update adalah bagian dari library Google Play Core. Sertakan dependensi Gradle berikut untuk mengintegrasikan Library Play In-App Update.
Groovy
// In your app's build.gradle file: ... dependencies { // This dependency is downloaded from the Google's Maven repository. // So, make sure you also include that repository in your project's build.gradle file. implementation 'com.google.android.play:app-update:2.1.0' // For Kotlin users also add the Kotlin extensions library for Play In-App Update: implementation 'com.google.android.play:app-update-ktx:2.1.0' ... }
Kotlin
// In your app's build.gradle.kts file: ... dependencies { // This dependency is downloaded from the Google's Maven repository. // So, make sure you also include that repository in your project's build.gradle file. implementation("com.google.android.play:app-update:2.1.0") // For Kotlin users also import the Kotlin extensions library for Play In-App Update: implementation("com.google.android.play:app-update-ktx:2.1.0") ... }
Memeriksa ketersediaan update
Sebelum meminta update, periksa apakah ada update yang tersedia untuk aplikasi Anda.
Gunakan AppUpdateManager
untuk memeriksa update:
Kotlin
val appUpdateManager = AppUpdateManagerFactory.create(context) // Returns an intent object that you use to check for an update. val appUpdateInfoTask = appUpdateManager.appUpdateInfo // Checks that the platform will allow the specified type of update. appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE // This example applies an immediate update. To apply a flexible update // instead, pass in AppUpdateType.FLEXIBLE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE) ) { // Request the update. } }
Java
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context); // Returns an intent object that you use to check for an update. Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo(); // Checks that the platform will allow the specified type of update. appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> { if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE // This example applies an immediate update. To apply a flexible update // instead, pass in AppUpdateType.FLEXIBLE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) { // Request the update. } });
Instance AppUpdateInfo
yang ditampilkan berisi status ketersediaan update. Bergantung pada status update, instance juga berisi
hal berikut:
- Jika update tersedia dan diizinkan, instance juga berisi intent untuk memulai update.
- Jika update dalam aplikasi sedang berjalan, instance juga melaporkan status update yang sedang berjalan.
Memeriksa penghentian update
Selain memeriksa apakah update tersedia, Anda juga perlu memeriksa jumlah waktu yang telah berlalu sejak pengguna terakhir kali diberi tahu tentang update melalui Play Store. Hal ini dapat membantu Anda menentukan apakah harus melakukan inisialisasi update fleksibel atau update langsung. Misalnya, Anda mungkin menunggu beberapa hari sebelum memberi tahu pengguna dengan update fleksibel, dan beberapa hari setelahnya sebelum meminta update langsung.
Gunakan clientVersionStalenessDays()
untuk memeriksa jumlah hari sejak update tersedia di Play Store:
Kotlin
val appUpdateManager = AppUpdateManagerFactory.create(context) // Returns an intent object that you use to check for an update. val appUpdateInfoTask = appUpdateManager.appUpdateInfo // Checks whether the platform allows the specified type of update, // and current version staleness. appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && (appUpdateInfo.clientVersionStalenessDays() ?: -1) >= DAYS_FOR_FLEXIBLE_UPDATE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) { // Request the update. } }
Java
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context); // Returns an intent object that you use to check for an update. Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo(); // Checks whether the platform allows the specified type of update, // and current version staleness. appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> { if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.clientVersionStalenessDays() != null && appUpdateInfo.clientVersionStalenessDays() >= DAYS_FOR_FLEXIBLE_UPDATE && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.FLEXIBLE)) { // Request the update. } });
Memeriksa prioritas update
Google Play Developer API memungkinkan Anda menetapkan prioritas setiap update. Hal ini memungkinkan aplikasi Anda menentukan seberapa kuat rekomendasi update kepada pengguna. Misalnya, pertimbangkan strategi berikut untuk menetapkan prioritas update:
- Peningkatan kecil pada UI: Update prioritas rendah; tidak meminta update fleksibel atau update langsung. Mengupdate hanya saat pengguna tidak berinteraksi dengan aplikasi Anda.
- Peningkatan performa: Update prioritas sedang; meminta update fleksibel.
- Update keamanan penting: Update prioritas tinggi; meminta update langsung.
Untuk menentukan prioritas, Google Play menggunakan nilai bilangan bulat antara 0 dan 5, dengan 0
adalah nilai default dan 5 adalah prioritas tertinggi. Guna menyetel prioritas untuk
update, gunakan kolom inAppUpdatePriority
di bawah Edits.tracks.releases
di
Google Play Developer API. Semua versi yang baru ditambahkan dalam rilis
dianggap sebagai prioritas yang sama dengan rilis tersebut. Prioritas hanya dapat disetel saat
meluncurkan rilis baru, dan tidak dapat diubah setelahnya.
Tetapkan prioritas menggunakan Google Play Developer API seperti yang dijelaskan dalam dokumentasi
Play Developer API. Prioritas update dalam aplikasi harus ditentukan di
resource Edit.tracks
yang diteruskan dalam metode
Edit.tracks: update
. Contoh berikut menunjukkan perilisan aplikasi dengan kode versi 88
dan inAppUpdatePriority
5:
{ "releases": [{ "versionCodes": ["88"], "inAppUpdatePriority": 5, "status": "completed" }] }
Dalam kode aplikasi, Anda dapat memeriksa tingkat prioritas untuk update tertentu menggunakan
updatePriority()
. Prioritas yang ditampilkan mempertimbangkan
inAppUpdatePriority
untuk semua kode versi aplikasi antara versi terinstal
dan versi terbaru yang tersedia, terlepas dari jalur rilis. Misalnya,
pertimbangkan skenario berikut:
- Anda merilis versi 1 ke jalur produksi tanpa prioritas.
- Anda merilis versi 2 ke jalur pengujian internal dengan prioritas 5.
- Anda merilis versi 3 ke jalur produksi tanpa prioritas.
Saat pengguna produksi mengupdate dari versi 1 ke versi 3, mereka akan mendapatkan prioritas 5, meskipun versi 2 dipublikasikan di jalur yang berbeda.
Kotlin
val appUpdateManager = AppUpdateManagerFactory.create(context) // Returns an intent object that you use to check for an update. val appUpdateInfoTask = appUpdateManager.appUpdateInfo // Checks whether the platform allows the specified type of update, // and checks the update priority. appUpdateInfoTask.addOnSuccessListener { appUpdateInfo -> if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.updatePriority() >= 4 /* high priority */ && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) { // Request an immediate update. } }
Java
AppUpdateManager appUpdateManager = AppUpdateManagerFactory.create(context); // Returns an intent object that you use to check for an update. Task<AppUpdateInfo> appUpdateInfoTask = appUpdateManager.getAppUpdateInfo(); // Checks whether the platform allows the specified type of update, // and checks the update priority. appUpdateInfoTask.addOnSuccessListener(appUpdateInfo -> { if (appUpdateInfo.updateAvailability() == UpdateAvailability.UPDATE_AVAILABLE && appUpdateInfo.updatePriority() >= 4 /* high priority */ && appUpdateInfo.isUpdateTypeAllowed(AppUpdateType.IMMEDIATE)) { // Request an immediate update. } });
Memulai update
Setelah memastikan bahwa update tersedia, Anda dapat meminta update menggunakan
AppUpdateManager.startUpdateFlowForResult()
:
Kotlin
appUpdateManager.startUpdateFlowForResult( // Pass the intent that is returned by 'getAppUpdateInfo()'. appUpdateInfo, // an activity result launcher registered via registerForActivityResult activityResultLauncher, // Or pass 'AppUpdateType.FLEXIBLE' to newBuilder() for // flexible updates. AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build())
Java
appUpdateManager.startUpdateFlowForResult( // Pass the intent that is returned by 'getAppUpdateInfo()'. appUpdateInfo, // an activity result launcher registered via registerForActivityResult activityResultLauncher, // Or pass 'AppUpdateType.FLEXIBLE' to newBuilder() for // flexible updates. AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build());
Setiap instance AppUpdateInfo
hanya dapat digunakan untuk memulai update sekali saja. Untuk mencoba kembali
update jika gagal, minta AppUpdateInfo
baru dan periksa kembali
apakah update tersedia dan diizinkan.
Anda dapat mendaftarkan peluncur hasil aktivitas menggunakan
kontrak ActivityResultContracts.StartIntentSenderForResult
bawaan. Periksa
bagian tentang mendapatkan callback untuk status update.
Langkah selanjutnya bergantung pada apakah Anda meminta update fleksibel atau update langsung.
Mengonfigurasi update dengan AppUpdateOptions
AppUpdateOptions
berisi kolom AllowAssetPackDeletion
yang menentukan
apakah update diizinkan untuk menghapus paket aset jika penyimpanan
perangkat terbatas. Kolom ini ditetapkan ke false
secara default, tetapi Anda dapat menggunakan
metode setAllowAssetPackDeletion()
untuk menetapkannya ke true
:
Kotlin
appUpdateManager.startUpdateFlowForResult( // Pass the intent that is returned by 'getAppUpdateInfo()'. appUpdateInfo, // an activity result launcher registered via registerForActivityResult activityResultLauncher, // Or pass 'AppUpdateType.FLEXIBLE' to newBuilder() for // flexible updates. AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE) .setAllowAssetPackDeletion(true) .build())
Java
appUpdateManager.startUpdateFlowForResult( // Pass the intent that is returned by 'getAppUpdateInfo()'. appUpdateInfo, // an activity result launcher registered via registerForActivityResult activityResultLauncher, // Or pass 'AppUpdateType.FLEXIBLE' to newBuilder() for // flexible updates. AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE) .setAllowAssetPackDeletion(true) .build());
Mendapatkan callback untuk status update
Setelah memulai update, callback peluncur hasil aktivitas yang terdaftar akan mendapatkan hasil dialog konfirmasi:
Kotlin
registerForActivityResult(StartIntentSenderForResult()) { result: ActivityResult -> // handle callback if (result.resultCode != RESULT_OK) { log("Update flow failed! Result code: " + result.resultCode); // If the update is canceled or fails, // you can request to start the update again. } }
Java
registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { // handle callback if (result.getResultCode() != RESULT_OK) { log("Update flow failed! Result code: " + result.getResultCode()); // If the update is canceled or fails, // you can request to start the update again. } } });
Ada beberapa nilai yang mungkin Anda terima dari callback
onActivityResult()
:
RESULT_OK
: Pengguna telah menyetujui update. Untuk update langsung, Anda mungkin tidak menerima callback ini karena update seharusnya sudah selesai saat kontrol dikembalikan ke aplikasi Anda.RESULT_CANCELED
: Pengguna telah menolak atau membatalkan update.ActivityResult.RESULT_IN_APP_UPDATE_FAILED
: Beberapa error lain mencegah pengguna memberikan izin atau update dilanjutkan.
Menangani update fleksibel
Saat Anda memulai update fleksibel, dialog terlebih dahulu akan muncul kepada pengguna untuk meminta izin. Jika pengguna mengizinkan, maka download akan dimulai di latar belakang, dan pengguna dapat melanjutkan berinteraksi dengan aplikasi. Bagian ini menjelaskan cara memantau dan menyelesaikan update dalam aplikasi fleksibel.
Memantau status update aplikasi
Setelah download dimulai untuk update fleksibel, aplikasi Anda harus memantau status update untuk mengetahui kapan update dapat diinstal dan menampilkan progresnya di UI aplikasi.
Anda dapat memantau status update yang sedang berlangsung dengan mendaftarkan pemroses untuk menginstal update status. Anda juga dapat memberikan status progres di UI aplikasi untuk memberi tahu pengguna tentang progres download.
Kotlin
// Create a listener to track request state updates. val listener = InstallStateUpdatedListener { state -> // (Optional) Provide a download progress bar. if (state.installStatus() == InstallStatus.DOWNLOADING) { val bytesDownloaded = state.bytesDownloaded() val totalBytesToDownload = state.totalBytesToDownload() // Show update progress bar. } // Log state or install the update. } // Before starting an update, register a listener for updates. appUpdateManager.registerListener(listener) // Start an update. // When status updates are no longer needed, unregister the listener. appUpdateManager.unregisterListener(listener)
Java
// Create a listener to track request state updates. InstallStateUpdatedListener listener = state -> { // (Optional) Provide a download progress bar. if (state.installStatus() == InstallStatus.DOWNLOADING) { long bytesDownloaded = state.bytesDownloaded(); long totalBytesToDownload = state.totalBytesToDownload(); // Implement progress bar. } // Log state or install the update. }; // Before starting an update, register a listener for updates. appUpdateManager.registerListener(listener); // Start an update. // When status updates are no longer needed, unregister the listener. appUpdateManager.unregisterListener(listener);
Menginstal update fleksibel
Saat Anda mendeteksi status InstallStatus.DOWNLOADED
, Anda harus memulai ulang
aplikasi untuk menginstal update.
Tidak seperti update langsung, Google Play tidak otomatis memicu mulai ulang aplikasi untuk update fleksibel. Hal ini karena selama proses update fleksibel, pengguna berharap untuk terus berinteraksi dengan aplikasi hingga memutuskan bahwa mereka ingin menginstal update.
Sebaiknya Anda memberi notifikasi (atau indikasi UI lain) untuk memberi tahu pengguna bahwa update siap untuk diinstal dan meminta konfirmasi sebelum memulai ulang aplikasi.
Contoh berikut mendemonstrasikan penerapan snackbar Desain Material yang meminta konfirmasi dari pengguna untuk memulai ulang aplikasi:
Kotlin
val listener = { state -> if (state.installStatus() == InstallStatus.DOWNLOADED) { // After the update is downloaded, show a notification // and request user confirmation to restart the app. popupSnackbarForCompleteUpdate() } ... } // Displays the snackbar notification and call to action. fun popupSnackbarForCompleteUpdate() { Snackbar.make( findViewById(R.id.activity_main_layout), "An update has just been downloaded.", Snackbar.LENGTH_INDEFINITE ).apply { setAction("RESTART") { appUpdateManager.completeUpdate() } setActionTextColor(resources.getColor(R.color.snackbar_action_text_color)) show() } }
Java
InstallStateUpdatedListener listener = state -> { if (state.installStatus() == InstallStatus.DOWNLOADED) { // After the update is downloaded, show a notification // and request user confirmation to restart the app. popupSnackbarForCompleteUpdate(); } ... }; // Displays the snackbar notification and call to action. private void popupSnackbarForCompleteUpdate() { Snackbar snackbar = Snackbar.make( findViewById(R.id.activity_main_layout), "An update has just been downloaded.", Snackbar.LENGTH_INDEFINITE); snackbar.setAction("RESTART", view -> appUpdateManager.completeUpdate()); snackbar.setActionTextColor( getResources().getColor(R.color.snackbar_action_text_color)); snackbar.show(); }
Saat Anda memanggil appUpdateManager.completeUpdate()
di latar depan, platform akan menampilkan UI layar penuh yang memulai ulang aplikasi di latar belakang.
Setelah platform menginstal update, aplikasi Anda akan dimulai ulang ke aktivitas
utama.
Jika Anda memanggil completeUpdate()
saat aplikasi berada di latar belakang,
update akan diinstal secara otomatis tanpa menghalangi UI perangkat.
Kapan pun pengguna membawa aplikasi Anda ke latar belakang, periksa apakah aplikasi memiliki
update yang menunggu untuk diinstal. Jika aplikasi Anda memiliki update di status
DOWNLOADED
, minta pengguna untuk menginstal update. Jika tidak, data update
akan terus mengisi penyimpanan perangkat pengguna.
Kotlin
// Checks that the update is not stalled during 'onResume()'. // However, you should execute this check at all app entry points. override fun onResume() { super.onResume() appUpdateManager .appUpdateInfo .addOnSuccessListener { appUpdateInfo -> ... // If the update is downloaded but not installed, // notify the user to complete the update. if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) { popupSnackbarForCompleteUpdate() } } }
Java
// Checks that the update is not stalled during 'onResume()'. // However, you should execute this check at all app entry points. @Override protected void onResume() { super.onResume(); appUpdateManager .getAppUpdateInfo() .addOnSuccessListener(appUpdateInfo -> { ... // If the update is downloaded but not installed, // notify the user to complete the update. if (appUpdateInfo.installStatus() == InstallStatus.DOWNLOADED) { popupSnackbarForCompleteUpdate(); } }); }
Menangani update langsung
Jika Anda memulai update langsung dan pengguna setuju untuk memulai update, Google Play akan menampilkan progres update di bagian atas UI aplikasi selama durasi update. Jika pengguna menutup atau menghentikan aplikasi Anda selama update, update tersebut harus terus mendownload dan menginstal di latar belakang tanpa konfirmasi tambahan dari pengguna.
Namun, jika aplikasi kembali ke latar depan, Anda harus memastikan bahwa
update tidak terhenti di
status
UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS
. Jika update terhenti dalam status ini, lanjutkan update:
Kotlin
// Checks that the update is not stalled during 'onResume()'. // However, you should execute this check at all entry points into the app. override fun onResume() { super.onResume() appUpdateManager .appUpdateInfo .addOnSuccessListener { appUpdateInfo -> ... if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS ) { // If an in-app update is already running, resume the update. appUpdateManager.startUpdateFlowForResult( appUpdateInfo, activityResultLauncher, AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()) } } }
Java
// Checks that the update is not stalled during 'onResume()'. // However, you should execute this check at all entry points into the app. @Override protected void onResume() { super.onResume(); appUpdateManager .getAppUpdateInfo() .addOnSuccessListener( appUpdateInfo -> { ... if (appUpdateInfo.updateAvailability() == UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS) { // If an in-app update is already running, resume the update. appUpdateManager.startUpdateFlowForResult( appUpdateInfo, activityResultLauncher, AppUpdateOptions.newBuilder(AppUpdateType.IMMEDIATE).build()); } }); }
Alur update menampilkan hasil seperti yang dijelaskan dalam dokumentasi referensi untuk
startUpdateFlowForResult()
. Secara khusus, aplikasi Anda harus dapat
menangani kasus saat pengguna menolak update atau membatalkan download. Saat
pengguna melakukan salah satu tindakan ini, UI Google Play akan menutup. Aplikasi Anda
harus menentukan cara terbaik untuk melanjutkan.
Jika memungkinkan, biarkan pengguna meneruskan tanpa update dan minta mereka lagi nanti. Jika aplikasi Anda tidak dapat berfungsi tanpa update, pertimbangkan untuk menampilkan pesan informatif sebelum memulai ulang alur update atau meminta pengguna untuk menutup aplikasi. Dengan begitu, pengguna memahami bahwa mereka dapat meluncurkan kembali aplikasi Anda saat mereka siap untuk menginstal update yang diperlukan.
Langkah berikutnya
Uji update dalam aplikasi pada aplikasi Anda untuk memverifikasi bahwa integrasi berfungsi dengan benar.