In diesem Leitfaden 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 die 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") ... }
Prüfen, ob ein Update verfügbar ist
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 Absicht, das Update zu starten.
- Wenn ein In-App-Update bereits ausgeführt wird, meldet die Instanz auch den Status des laufenden Updates.
Aktualität von Updates prüfen
Sie sollten 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 Play Store vergangen ist. So können Sie besser entscheiden, ob Sie ein flexibles oder ein sofortiges Update starten sollten. Sie können beispielsweise einige Tage warten, bevor Sie den Nutzer mit einem flexiblen Update benachrichtigen, und einige Tage danach, bevor Sie ein sofortiges Update verlangen.
Mit clientVersionStalenessDays()
können Sie die Anzahl der Tage seit der Verfügbarkeit des Updates im Play Store 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 von Updates prüfen
Mit der Google Play Developer API können Sie die Priorität jeder Aktualisierung festlegen. So kann Ihre App entscheiden, wie dringend sie dem Nutzer ein Update empfiehlt. Betrachten Sie beispielsweise die folgende Strategie zum Festlegen der Updatepriorität:
- Kleinere Verbesserungen an der Benutzeroberfläche: Update mit niedriger Priorität; es ist weder ein flexibles noch ein sofortiges Update erforderlich. Aktualisieren Sie nur, wenn der Nutzer nicht mit Ihrer App interagiert.
- Leistungsverbesserungen: Aktualisierung mit mittlerer Priorität; flexible Aktualisierung anfordern.
- Kritisches Sicherheitsupdate: Update mit hoher Priorität; sofortiges Update erforderlich.
Google Play verwendet zur Bestimmung der Priorität einen ganzzahligen Wert zwischen 0 und 5. Der Standardwert ist 0 und 5 ist die höchste Priorität. Wenn Sie die Priorität für ein Update festlegen möchten, verwenden Sie das Feld inAppUpdatePriority
unter Edits.tracks.releases
in der Google Play Developer API. Alle neu hinzugefügten Versionen im Release haben dieselbe Priorität wie das Release. Die Priorität kann nur beim Einführen einer neuen Version festgelegt und 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-Dokumentation beschrieben. Die Priorität für In-App-Updates sollte in der Edit.tracks
-Ressource angegeben werden, die in der Methode Edit.tracks: update
übergeben wird. Im folgenden Beispiel wird gezeigt, wie eine App mit dem Versionscode 88 und inAppUpdatePriority
5 veröffentlicht wird:
{ "releases": [{ "versionCodes": ["88"], "inAppUpdatePriority": 5, "status": "completed" }] }
Im Code Ihrer App können Sie die Prioritätsstufe für ein bestimmtes Update mit updatePriority()
prüfen. Bei der zurückgegebenen Priorität wird der inAppUpdatePriority
für alle App-Versionscodes zwischen der installierten Version und der neuesten verfügbaren Version berücksichtigt, unabhängig vom Release-Track. Betrachten Sie beispielsweise das folgende Szenario:
- Sie veröffentlichen 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 die Priorität 5, obwohl Version 2 auf 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
Wenn Sie bestätigt haben, dass ein Update verfügbar ist, können Sie es mit AppUpdateManager.startUpdateFlowForResult()
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 zum Starten einer Aktualisierung verwendet werden. Wenn das Update fehlschlägt, können Sie es noch einmal versuchen. Fordern Sie dazu 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 Callback für Aktualisierungsstatus erhalten.
Die nächsten Schritte hängen davon ab, ob Sie eine flexible Aktualisierung oder eine sofortige Aktualisierung anfordern.
Update mit AppUpdateOptions konfigurieren
AppUpdateOptions
enthält ein AllowAssetPackDeletion
-Feld, das definiert, ob beim Update Asset-Packs gelöscht werden dürfen, wenn der Gerätespeicher begrenzt ist. Dieses Feld ist standardmäßig auf false
gesetzt. Sie können es jedoch mit der Methode setAllowAssetPackDeletion()
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());
Rückruf zum Aktualisierungsstatus erhalten
Nach dem Starten eines Updates erhält der registrierte Aktivitätsergebnis-Launcher-Callback 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. } } });
Sie können verschiedene Werte vom onActivityResult()
-Callback erhalten:
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 die Aktualisierung abgelehnt oder abgebrochen.ActivityResult.RESULT_IN_APP_UPDATE_FAILED
: Ein anderer Fehler hat entweder verhindert, dass der Nutzer die Einwilligung erteilt hat, oder dass das Update fortgesetzt wurde.
Flexible Aktualisierung 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 zustimmt, 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 der flexiblen Aktualisierung ü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 Benutzeroberfläche Ihrer App anzuzeigen.
Sie können den Status einer laufenden Aktualisierung überwachen, indem Sie einen Listener für Aktualisierungen des Installationsstatus registrieren. Sie können auch eine Fortschrittsanzeige in der Benutzeroberfläche der App einblenden, 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.
Im Gegensatz zu sofortigen Updates wird bei flexiblen Updates kein automatischer Neustart der App durch Google Play ausgelöst. Das liegt daran, dass der Nutzer bei einem flexiblen Update erwartet, dass er weiterhin mit der App interagieren kann, bis er sich für die Installation des Updates entscheidet.
Es wird empfohlen, den Nutzer über eine Benachrichtigung oder eine andere UI-Anzeige darüber zu informieren, dass das Update installiert werden kann, und ihn vor dem Neustart der App um Bestätigung zu bitten.
Im folgenden Beispiel wird die Implementierung einer Material Design-Snackbar veranschaulicht, in der der Nutzer um Bestätigung zum Neustarten der App gebeten wird:
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-Benutzeroberfläche an, die die App im Hintergrund neu startet.
Nachdem die Plattform das Update installiert hat, wird Ihre App in ihrer Hauptaktivität neu gestartet.
Wenn Sie stattdessen completeUpdate()
aufrufen, während Ihre App im Hintergrund ausgeführt wird, wird das Update automatisch installiert, ohne die Geräte-UI zu verdecken.
Prüfen Sie jedes Mal, wenn der Nutzer Ihre App in den Vordergrund holt, ob ein Update für Ihre App zur Installation bereitsteht. Wenn für Ihre App ein Update im Status DOWNLOADED
verfügbar ist, fordern Sie den Nutzer auf, das Update zu installieren. Andernfalls belegen die Aktualisierungsdaten 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 durchführen
Wenn Sie ein sofortiges Update starten und der Nutzer der Aktualisierung zustimmt, zeigt Google Play den Fortschritt des Updates während der gesamten Dauer des Updates oben in der Benutzeroberfläche Ihrer App an. Wenn der Nutzer Ihre App während des Updates schließt oder beendet, sollte das Update im Hintergrund ohne zusätzliche Bestätigung des Nutzers heruntergeladen und installiert werden.
Wenn Ihre App jedoch wieder in den Vordergrund wechselt, sollten Sie prüfen, ob das Update im Status UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS
hängen geblieben ist. Wenn das Update in diesem Status hängen bleibt, setzen Sie es 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 Aktualisierungsablauf gibt ein Ergebnis zurück, wie in der Referenzdokumentation für startUpdateFlowForResult()
beschrieben. Ihre App sollte insbesondere Fälle abfangen 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-Benutzeroberfläche geschlossen. Ihre App sollte den besten Weg für die weitere Vorgehensweise ermitteln.
Lassen Sie den Nutzer nach Möglichkeit ohne das Update fortfahren und erinnern Sie ihn später noch einmal daran. Wenn Ihre App ohne das Update nicht funktioniert, sollten Sie eine informative Meldung anzeigen, bevor Sie den Updatevorgang 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 Ihre Integration ordnungsgemäß funktioniert.