این راهنما توضیح میدهد که چگونه بااستفاده از Kotlin یا Java از بهروزرسانیهای درونبرنامه در برنامهتان پشتیبانی کنید. راهنماهای جداگانهای برای مواردی که پیادهسازی شما از کد بومی (C/C++) استفاده میکند و مواردی که پیادهسازی شما از Unity یا Unreal Engine استفاده میکند وجود دارد.
راهاندازی محیط توسعه نرمافزار
«کتابخانه بهروزرسانی درونبرنامه Play» بخشی از کتابخانههای هسته Google Play است. برای ادغام «کتابخانه بهروزرسانی درونبرنامه Play»، وابستگی Gradle زیر را اضافه کنید.
شیک
// 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' ... }
کاتلین
// 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") ... }
بررسی دردسترس بودن بهروزرسانی
قبلاز درخواست بهروزرسانی، بررسی کنید که آیا بهروزرسانیای برای برنامهتان دردسترس است یا نه.
از AppUpdateManager برای بررسی وجود بهروزرسانی استفاده کنید:
کاتلین
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. } }
جاوا
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. } });
نمونه AppUpdateInfo برگرداندهشده حاوی وضعیت دردسترس بودن بهروزرسانی است. بسته به وضعیت بهروزرسانی، نمونه حاوی موارد زیر نیز هست:
- اگر بهروزرسانی دردسترس باشد و بهروزرسانی مجاز باشد، نمونه همچنین حاوی قصدی برای شروع بهروزرسانی است.
- اگر بهروزرسانی درونبرنامهای ازقبل درحال انجام باشد، نمونه همچنین وضعیت بهروزرسانی درحال انجام را گزارش میکند.
بررسی قدیمی بودن بهروزرسانی
علاوهبر بررسی اینکه آیا بهروزرسانی دردسترس است یا نه، ممکن است بخواهید بررسی کنید که از آخرین باری که کاربر ازطریق «فروشگاه Play» از بهروزرسانی مطلع شده است، چقدر زمان گذشته است. این کار میتواند به شما کمک کند تصمیم بگیرید که آیا باید بهروزرسانی انعطافپذیر را شروع کنید یا بهروزرسانی فوری. برای مثال، ممکن است چند روز صبر کنید و سپس با بهروزرسانی انعطافپذیر به کاربر اطلاع دهید، و چند روز بعداز آن بهروزرسانی فوری را الزامی کنید.
از clientVersionStalenessDays() برای بررسی تعداد روزهایی که از دردسترس قرار گرفتن بهروزرسانی در «فروشگاه Play» میگذرد استفاده کنید:
کاتلین
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. } }
جاوا
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. } });
بررسی اولویت بهروزرسانی
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" }] }
در کد برنامهتان، میتوانید سطح اولویت بهروزرسانی موردنظر را بااستفاده از
updatePriority() بررسی کنید. اولویت برگرداندهشده
inAppUpdatePriority را برای همه کدهای نسخه برنامه بین نسخه نصبشده
و جدیدترین نسخه دردسترس، صرفنظر از دسته هدف انتشار، درنظر میگیرد. برای مثال،
سناریو زیر را درنظر بگیرید:
- نسخه ۱ را بدون اولویت در دسته هدف تولید منتشر میکنید.
- نسخه ۲ را با اولویت ۵ در دسته هدف آزمایشی داخلی منتشر میکنید.
- نسخه ۳ را بدون اولویت در دسته هدف تولید منتشر میکنید.
وقتی کاربران تولید از نسخه ۱ به نسخه ۳ بهروزرسانی میکنند، اولویت ۵ را دریافت خواهند کرد، هرچند نسخه ۲ در دسته هدف دیگری منتشر شده است.
کاتلین
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. } }
جاوا
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. } });
شروع بهروزرسانی
پساز تأیید اینکه بهروزرسانی دردسترس است، میتوانید بااستفاده از
AppUpdateManager.startUpdateFlowForResult() درخواست بهروزرسانی کنید:
کاتلین
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())
جاوا
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());
از هر نمونه AppUpdateInfo فقط یکبار میتوان برای شروع بهروزرسانی استفاده کرد. برای امتحان مجدد
بهروزرسانی درصورت ناموفق بودن، AppUpdateInfo جدیدی درخواست کنید و دوباره بررسی کنید
که بهروزرسانی دردسترس و مجاز باشد.
میتوانید بااستفاده از قرارداد داخلی ActivityResultContracts.StartIntentSenderForResult، راهانداز نتیجه فعالیت را ثبت کنید. بخش
دریافت تماس برگشتی برای وضعیت بهروزرسانی را بررسی کنید.
مراحل بعدی به این بستگی دارد که درخواست بهروزرسانی انعطافپذیر دارید یا بهروزرسانی فوری.
پیکربندی بهروزرسانی با AppUpdateOptions
AppUpdateOptions حاوی فیلد AllowAssetPackDeletion است که تعیین میکند
آیا بهروزرسانی میتواند درصورت محدود بودن فضای ذخیرهسازی دستگاه،
بستههای دارایی را پاک کند یا نه. این فیلد بهطور پیشفرض روی false تنظیم شده است، اما میتوانید از روش
setAllowAssetPackDeletion() برای تنظیم آن روی true استفاده کنید:
کاتلین
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())
جاوا
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());
دریافت تماس برگشتی برای بهروزرسانی وضعیت
پساز شروع بهروزرسانی، فراخوان راهانداز نتیجه فعالیت ثبتشده نتیجه کادر گفتگوی تأیید را دریافت میکند:
کاتلین
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. } }
جاوا
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. } } });
چندین مقدار وجود دارد که ممکن است از فراخوانی برگشتی onActivityResult()
دریافت کنید:
RESULT_OK: کاربر بهروزرسانی را پذیرفته است. برای بهروزرسانیهای فوری، ممکن است این فراخوانی برگشتی را دریافت نکنید زیرا بهروزرسانی باید تا زمانی که کنترل به برنامهتان برگردانده میشود بهپایان رسیده باشد.RESULT_CANCELED: کاربر بهروزرسانی را رد یا لغو کرده است.ActivityResult.RESULT_IN_APP_UPDATE_FAILED: خطای دیگری مانع از ارائه رضایت کاربر یا ادامه بهروزرسانی شده است.
مدیریت بهروزرسانی انعطافپذیر
وقتی بهروزرسانی انعطافپذیر را شروع میکنید، ابتدا کادر گفتگویی برای درخواست رضایت کاربر ظاهر میشود. اگر کاربر موافقت کند، بارگیری در پسزمینه شروع میشود و کاربر میتواند به تعامل با برنامه شما ادامه دهد. این بخش نحوه نظارت و تکمیل بهروزرسانی انعطافپذیر درونبرنامه را شرح میدهد.
نظارت بر وضعیت بهروزرسانی انعطافپذیر
پساز شروع بارگیری برای بهروزرسانی انعطافپذیر، برنامهتان باید وضعیت بهروزرسانی را پایش کند تا بداند چه زمانی بهروزرسانی میتواند نصب شود و پیشرفت را در واسط کاربر برنامهتان نمایش دهد.
میتوانید با ثبت شنونده برای بهروزرسانیهای وضعیت نصب، وضعیت بهروزرسانی درحال انجام را پایش کنید. همچنین میتوانید نوار پیشرفتی در واسط کاربر برنامه ارائه دهید تا کاربران را از پیشرفت بارگیری مطلع کنید.
کاتلین
// 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)
جاوا
// 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);
نصب بهروزرسانی انعطافپذیر
وقتی وضعیت InstallStatus.DOWNLOADED را شناسایی میکنید، باید برنامه را بازراهاندازی کنید تا بهروزرسانی نصب شود.
برخلاف بهروزرسانیهای فوری، Google Play بهطور خودکار برنامه را برای بهروزرسانی انعطافپذیر بازراهاندازی نمیکند. دلیلش این است که درطول بهروزرسانی انعطافپذیر، کاربر انتظار دارد تا زمانی که تصمیم به نصب بهروزرسانی بگیرد، بتواند به تعامل با برنامه ادامه دهد.
توصیه میشود اعلانی (یا نشانگر میانای کاربری دیگری) ارائه دهید تا به کاربر اطلاع دهد که بهروزرسانی آماده نصب است و قبلاز بازراهاندازی برنامه، تأییدیه درخواست کند.
مثال زیر پیادهسازی نوار میانوعده «طراحی مواد» را نشان میدهد که از کاربر میخواهد راهاندازی مجدد برنامه را تأیید کند:
کاتلین
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() } }
جاوا
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(); }
وقتی appUpdateManager.completeUpdate() را در پیشزمینه فراخوانی میکنید،
پلاتفرم واسط کاربر تمامصفحهای را نمایش میدهد که برنامه را در پسزمینه بازراهاندازی میکند.
پساز اینکه پلاتفرم بهروزرسانی را نصب کرد، برنامه شما در فعالیت اصلیاش
بازراهاندازی میشود.
اگر درعوض وقتی برنامهتان در پسزمینه است completeUpdate() را فراخوانی کنید،
بهروزرسانی بدون پنهان کردن واسط کاربر دستگاه بهصورت بیصدا نصب میشود.
هرزمان کاربر برنامهتان را به پیشزمینه میآورد، بررسی کنید آیا برنامهتان بهروزرسانیای دارد که منتظر نصب باشد. اگر برنامهتان بهروزرسانیای در وضعیت DOWNLOADED دارد، از کاربر بخواهید بهروزرسانی را نصب کند. درغیراینصورت، دادههای بهروزرسانی
همچنان فضای ذخیرهسازی دستگاه کاربر را اشغال میکند.
کاتلین
// 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() } } }
جاوا
// 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(); } }); }
مدیریت بهروزرسانی فوری
وقتی بهروزرسانی فوری را شروع میکنید و کاربر با شروع بهروزرسانی موافقت میکند، Google Play پیشرفت بهروزرسانی را در بالای میانای کاربر برنامهتان درطول کل مدت بهروزرسانی نمایش میدهد. اگر کاربر درطول بهروزرسانی، برنامه شما را ببندد یا متوقف کند، بهروزرسانی باید بدون تأیید بیشتر کاربر، در پسزمینه بارگیری و نصب شود.
بااینحال، وقتی برنامهتان به پیشزمینه برمیگردد، باید تأیید کنید که بهروزرسانی در وضعیت UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS متوقف نشده باشد. اگر
بهروزرسانی در این وضعیت متوقف شده است، بهروزرسانی را ازسر بگیرید:
کاتلین
// 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()) } } }
جاوا
// 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()); } }); }
جریان بهروزرسانی نتیجهای را برمیگرداند که در سند مرجع برای
startUpdateFlowForResult() شرح داده شده است. بهطور مشخص، برنامهتان باید بتواند
مواردی را که کاربر بهروزرسانی را رد میکند یا بارگیری را لغو میکند مدیریت کند. وقتی
کاربر یکی از این کنشها را انجام میدهد، میانای کاربری Google Play بسته میشود. برنامه شما
باید بهترین روش را برای ادامه دادن تعیین کند.
درصورت امکان، به کاربر اجازه دهید بدون بهروزرسانی ادامه دهد و بعداً دوباره از او درخواست کنید. اگر برنامهتان بدون بهروزرسانی نمیتواند کار کند، قبلاز راهاندازی مجدد جریان بهروزرسانی یا درخواست از کاربر برای بستن برنامه، پیام اطلاعرسانی نمایش دهید. به این ترتیب، کاربر متوجه میشود که وقتی برای نصب بهروزرسانی الزامی آماده شد، میتواند برنامهتان را دوباره راهاندازی کند.
مراحل بعدی
بهروزرسانیهای درونبرنامه برنامهتان را آزمایش کنید تا مطمئن شوید ادغام بهدرستی کار میکند.