In dieser Anleitung wird beschrieben, wie Sie In-App-Updates in Ihrer App mit Kotlin oder Java unterstützen. Es gibt separate Anleitungen für Fälle, in denen Ihre Implementierung nativen Code (C/C++) verwendet, und für Fälle, in denen Ihre Implementierung Unity oder Unreal Engine verwendet.
Entwicklungsumgebung einrichten
Die Play In-App Update Library ist Teil der Google Play Core-Bibliotheken. Fügen Sie die folgende Gradle-Abhängigkeit ein, um die Play In-App Update Library einzubinden.
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") ... }
Verfügbarkeit von Updates prüfen
Bevor Sie ein Update anfordern, prüfen Sie, ob ein Update für Ihre App verfügbar ist.
Verwenden Sie AppUpdateManager, um nach einem Update zu suchen:
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. } });
Die zurückgegebene AppUpdateInfo-Instanz enthält den Status der Updateverfügbarkeit. Je nach Status des Updates enthält die Instanz auch Folgendes:
- Wenn ein Update verfügbar ist und das Update zulässig ist, enthält die Instanz auch eine Intent-Nachricht, um das Update zu starten.
- Wenn ein In-App-Update bereits ausgeführt wird, meldet die Instanz auch den Status des laufenden Updates.
Alter des Updates prüfen
Sie können nicht nur prüfen, ob ein Update verfügbar ist, sondern auch, wie viel Zeit seit der letzten Benachrichtigung des Nutzers über ein Update im Google Play Store vergangen ist. So können Sie entscheiden, ob Sie ein flexibles oder ein sofortiges Update initiieren sollten. Sie können beispielsweise einige Tage warten, bevor Sie den Nutzer mit einem flexiblen Update benachrichtigen, und einige Tage danach ein sofortiges Update anfordern.
Verwenden Sie clientVersionStalenessDays(), um die Anzahl der Tage seit der
Verfügbarkeit des Updates im Google Play Store zu prüfen:
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. } });
Priorität des Updates prüfen
Mit der Google Play Developer API können Sie die Priorität jedes Updates festlegen. So kann Ihre App entscheiden, wie stark sie dem Nutzer ein Update empfehlen soll. Betrachten Sie beispielsweise die folgende Strategie zum Festlegen der Updatepriorität:
- Kleinere UI-Verbesserungen: Update mit niedriger Priorität. Fordern Sie weder ein flexibles noch ein sofortiges Update an. Aktualisieren Sie nur, wenn der Nutzer nicht mit Ihrer App interagiert.
- Leistungsverbesserungen: Update mit mittlerer Priorität. Fordern Sie ein flexibles Update an.
- Kritisches Sicherheitsupdate: Update mit hoher Priorität. Fordern Sie ein sofortiges Update an.
Google Play verwendet einen ganzzahligen Wert zwischen 0 und 5, wobei 0 die Standardeinstellung und 5 die höchste Priorität ist. Verwenden Sie das Feld inAppUpdatePriority unter Edits.tracks.releases in der Google Play Developer API, um die Priorität für ein Update festzulegen. Alle neu hinzugefügten Versionen im Release haben dieselbe Priorität wie das Release. Die Priorität kann nur beim Roll-out einer Neuveröffentlichung festgelegt werden und kann später nicht mehr geändert werden.
Legen Sie die Priorität mit der Google Play Developer API fest, wie in der Play
Developer API documentation beschrieben. Die Priorität für In-App-Updates muss in
der Edit.tracks Ressource angegeben werden, die in der Edit.tracks: update
Methode übergeben wird. Im folgenden Beispiel wird eine App mit dem Versionscode 88 und inAppUpdatePriority 5 veröffentlicht:
{ "releases": [{ "versionCodes": ["88"], "inAppUpdatePriority": 5, "status": "completed" }] }
Im Code Ihrer App können Sie die Priorität für ein bestimmtes Update mit
updatePriority() prüfen. Die zurückgegebene Priorität berücksichtigt inAppUpdatePriority für alle App-Versionscodes zwischen der installierten Version und der neuesten verfügbaren Version, unabhängig vom Release-Track. Betrachten Sie beispielsweise das folgende Szenario:
- Sie veröffentlichen Release-Version 1 in einem Produktions-Track ohne Priorität.
- Sie veröffentlichen Version 2 in einem internen Test-Track mit Priorität 5.
- Sie veröffentlichen Version 3 in einem Produktions-Track ohne Priorität.
Wenn Produktionsnutzer von Version 1 auf Version 3 aktualisieren, erhalten sie Priorität 5, obwohl Version 2 in einem anderen Track veröffentlicht wurde.
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. } });
Update starten
Nachdem Sie bestätigt haben, dass ein Update verfügbar ist, können Sie mit
AppUpdateManager.startUpdateFlowForResult() ein Update anfordern:
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());
Jede AppUpdateInfo-Instanz kann nur einmal verwendet werden, um ein Update zu starten. Wenn das Update fehlschlägt, fordern Sie eine neue AppUpdateInfo an und prüfen Sie noch einmal, ob das Update verfügbar und zulässig ist.
Sie können einen Launcher für Aktivitätsergebnisse mit dem integrierten
ActivityResultContracts.StartIntentSenderForResult Vertrag registrieren. Weitere Informationen finden Sie im
Abschnitt zum Abrufen eines Callbacks für den Updatestatus.
Die nächsten Schritte hängen davon ab, ob Sie ein flexibles Update oder ein sofortiges Update anfordern.
Update mit AppUpdateOptions konfigurieren
AppUpdateOptions enthält ein Feld AllowAssetPackDeletion, das definiert
, ob das Update Asset-Packs löschen darf, wenn der Gerätespeicher begrenzt ist. Dieses Feld ist standardmäßig auf false gesetzt. Sie können es jedoch mit der
setAllowAssetPackDeletion() Methode auf true setzen:
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());
Callback für Updatestatus abrufen
Nachdem ein Update gestartet wurde, erhält der Callback des registrierten Launchers für Aktivitätsergebnisse das Ergebnis des Bestätigungsdialogfelds:
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. } } });
Es gibt mehrere Werte, die Sie vom onActivityResult()-Callback erhalten können:
RESULT_OK: Der Nutzer hat das Update akzeptiert. Bei sofortigen Updates erhalten Sie diesen Callback möglicherweise nicht, da das Update bereits abgeschlossen sein sollte, wenn die Steuerung an Ihre App zurückgegeben wird.RESULT_CANCELED: Der Nutzer hat das Update abgelehnt oder abgebrochen.ActivityResult.RESULT_IN_APP_UPDATE_FAILED: Ein anderer Fehler hat verhindert, dass der Nutzer die Einwilligung erteilt oder das Update fortgesetzt werden konnte.
Flexibles Update verarbeiten
Wenn Sie ein flexibles Update starten, wird dem Nutzer zuerst ein Dialogfeld angezeigt, in dem er um seine Einwilligung gebeten wird. Wenn der Nutzer einwilligt, beginnt der Download im Hintergrund und der Nutzer kann weiterhin mit Ihrer App interagieren. In diesem Abschnitt wird beschrieben, wie Sie ein flexibles In-App-Update überwachen und abschließen.
Status des flexiblen Updates überwachen
Nachdem der Download für ein flexibles Update begonnen hat, muss Ihre App den Updatestatus überwachen, um zu wissen, wann das Update installiert werden kann, und um den Fortschritt in der UI Ihrer App anzuzeigen.
Sie können den Status eines laufenden Updates überwachen, indem Sie einen Listener für Statusupdates zur Installation registrieren. Sie können auch eine Fortschrittsleiste in der UI der App bereitstellen, um Nutzer über den Fortschritt des Downloads zu informieren.
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);
Flexibles Update installieren
Wenn Sie den Status InstallStatus.DOWNLOADED erkennen, müssen Sie die App neu starten, um das Update zu installieren.
Anders als bei sofortigen Updates löst Google Play bei einem flexiblen Update nicht automatisch einen Neustart der App aus. Das liegt daran, dass der Nutzer bei einem flexiblen Update erwartet, weiterhin mit der App interagieren zu können, bis er sich entscheidet, das Update zu installieren.
Wir empfehlen, eine Benachrichtigung (oder eine andere UI-Anzeige) bereitzustellen, um den Nutzer darüber zu informieren, dass das Update zur Installation bereit ist, und um eine Bestätigung anzufordern, bevor Sie die App neu starten.
Im folgenden Beispiel wird eine Material Design-Snackbar implementiert, in der der Nutzer um Bestätigung gebeten wird, die App neu zu starten:
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(); }
Wenn Sie appUpdateManager.completeUpdate() im Vordergrund aufrufen, zeigt die
Plattform eine Vollbild-UI an, die die App im Hintergrund neu startet.
Nachdem die Plattform das Update installiert hat, wird Ihre App in der Hauptaktivität neu gestartet.
Wenn Sie completeUpdate() stattdessen aufrufen, wenn sich Ihre App im Hintergrund befindet,
wird das Update im Hintergrund installiert, ohne die Geräte-UI zu verdecken.
Prüfen Sie immer, wenn der Nutzer Ihre App in den Vordergrund holt, ob ein Update zur Installation bereitsteht. Wenn sich ein Update im Status DOWNLOADED befindet, fordern Sie den Nutzer auf, das Update zu installieren. Andernfalls belegen die Updatedaten weiterhin den Gerätespeicher des Nutzers.
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(); } }); }
Sofortiges Update verarbeiten
Wenn Sie ein sofortiges Update starten und der Nutzer einwilligt, das Update zu starten, zeigt Google Play den Fortschritt des Updates während der gesamten Dauer des Updates über der UI Ihrer App an. Wenn der Nutzer Ihre App während des Updates schließt oder beendet, sollte das Update im Hintergrund heruntergeladen und installiert werden, ohne dass eine zusätzliche Bestätigung des Nutzers erforderlich ist.
Wenn Ihre App jedoch in den Vordergrund zurückkehrt, sollten Sie prüfen, ob das
Update nicht im
UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS Status hängen geblieben ist. Wenn das Update in diesem Status hängen geblieben ist, setzen Sie das Update fort:
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()); } }); }
Der Updateablauf gibt ein Ergebnis zurück, wie in der Referenzdokumentation für
startUpdateFlowForResult() beschrieben. Ihre App sollte insbesondere Fälle verarbeiten können, in denen ein Nutzer das Update ablehnt oder den Download abbricht. Wenn der Nutzer eine dieser Aktionen ausführt, wird die Google Play-UI geschlossen. Ihre App sollte den besten Weg finden, um fortzufahren.
Wenn möglich, lassen Sie den Nutzer ohne das Update fortfahren und fordern Sie ihn später noch einmal auf. Wenn Ihre App ohne das Update nicht funktioniert, zeigen Sie eine informative Meldung an, bevor Sie den Updateablauf neu starten oder den Nutzer auffordern, die App zu schließen. So weiß der Nutzer, dass er Ihre App neu starten kann, wenn er bereit ist, das erforderliche Update zu installieren.
Nächste Schritte
Testen Sie die In-App-Updates Ihrer App, um zu prüfen, ob die Einbindung ordnungsgemäß funktioniert.