Unterstützung von In-App-Updates (Kotlin oder Java)

In diesem Leitfaden wird beschrieben, wie Sie In-App- Updates in deiner App mit Kotlin oder Java Es gibt separate Anleitungen für Fälle, in denen bei der Implementierung nativer Code verwendet wird. (C/C++) und in Fällen, in denen Ihre für die Implementierung Unity.

Entwicklungsumgebung einrichten

Die Play In-App Update Library ist Teil der Google Play Core-Bibliotheken. Gib die folgende Gradle-Abhängigkeit an, um die Play In-App-Inhalte zu integrieren Mediathek aktualisieren.

Cool

// 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 den Verfügbarkeitsstatus des Updates enthält. Je nach Status des aktualisiert wird, enthält die Instanz auch Folgendes:

  • Wenn ein Update verfügbar und das Update zulässig ist, enthält einen Intent zum Starten des Updates.
  • Wenn ein In-App-Update bereits läuft, meldet die Instanz außerdem den Status des laufenden Updates.

Veraltete Updates prüfen

Neben der Prüfung, ob ein Update verfügbar ist, Prüfen, wie viel Zeit seit der letzten Benachrichtigung des Nutzers über ein Update vergangen ist über den Play Store. So können Sie besser entscheiden, ob Sie ein flexibles Update oder ein sofortiges Update. Warten Sie z. B. einige Tage bevor der Nutzer mit einem flexiblen Update benachrichtigt wird, und einige Tage später bevor eine sofortige Aktualisierung erforderlich ist.

Verwenden Sie clientVersionStalenessDays() So überprüfen Sie, wie viele Tage seit dem Update im Play Store verfügbar sind:

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.
    }
});

Updatepriorität prüfen

Mit der Google Play Developer API können Sie die Priorität jedes Updates festlegen. So kann Ihre App entscheiden, wie dringend ein Update dem Nutzer empfohlen wird. Betrachten Sie beispielsweise die folgende Strategie zum Festlegen der Aktualisierungspriorität:

  • Kleinere Verbesserungen der Benutzeroberfläche: Aktualisierung mit niedriger Priorität. weder eine flexible noch ein sofortiges Update. Nur aktualisieren, wenn der Nutzer nicht interagiert mit Ihrer App.
  • Leistungsverbesserungen: Update mit mittlerer Priorität flexibles aktualisieren.
  • Kritisches Sicherheitsupdate: Update mit hoher Priorität Sofortige Anforderung aktualisieren.

Zur Bestimmung der Priorität verwendet Google Play einen ganzzahligen Wert zwischen 0 und 5 mit 0 Standardeinstellung und 5 die höchste Priorität. Zum Festlegen der Priorität für eine aktualisieren Sie das Feld inAppUpdatePriority unter Edits.tracks.releases in der Google Play Developer API Alle neu hinzugefügten Versionen im Release dieselbe Priorität wie die Veröffentlichung haben. Die Priorität kann nur festgelegt werden, wenn wenn ein neuer Release eingeführt wird, der später nicht mehr geändert werden kann.

Legen Sie die Priorität mithilfe der Google Play Developer API fest, wie in der Google Play Developer API Entwickler-API Dokumentation. Die Priorität für In-App-Updates sollte in der Edit.tracks im Feld Edit.tracks: update . Das folgende Beispiel zeigt die Veröffentlichung einer App mit dem Versionscode 88. und inAppUpdatePriority 5:

{
  "releases": [{
      "versionCodes": ["88"],
      "inAppUpdatePriority": 5,
      "status": "completed"
  }]
}

Im Code Ihrer App können Sie die Prioritätsstufe für ein bestimmtes Update mit updatePriority() Bei der zurückgegebenen Priorität wird der inAppUpdatePriority für alle Apps berücksichtigt. Versionscodes zwischen der installierten und der letzten verfügbaren Version, unabhängig vom Release-Track. Stellen Sie sich beispielsweise das folgende Szenario vor:

  • Du veröffentlichst Version 1 in einem Produktions-Track ohne Priorität.
  • Sie veröffentlichen Version 2 in einem internen Test-Track mit Priorität 5.
  • Du veröffentlichst Version 3 in einem Produktions-Track ohne Priorität.

Wenn Nutzer in der Produktionsphase ein Update von Version 1 auf Version 3 durchführen, 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 es mit 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());

Jede AppUpdateInfo-Instanz kann nur einmal verwendet werden, um ein Update zu starten. Wiederholen Falls das Update fehlschlägt, fordern Sie ein neues AppUpdateInfo an und prüfen Sie es noch einmal dass das Update verfügbar und zulässig ist.

Sie können einen Launcher für Aktivitätsergebnisse über die integrierte ActivityResultContracts.StartIntentSenderForResult Vertrag. Sehen Sie sich den Abschnitt zur Callback zum Updatestatus

Die nächsten Schritte hängen davon ab, ob Sie eine flexible Update oder ein sofortiges Update.

Aktualisierung mit AppUpdateOptions konfigurieren

AppUpdateOptions enthält ein AllowAssetPackDeletion-Feld, das definiert, ob das Update dürfen Asset-Packs löschen, falls beschränkter Gerätespeicher. Dieses Feld ist standardmäßig auf false festgelegt. Sie können aber Folgendes verwenden: Das setAllowAssetPackDeletion() , um sie stattdessen auf true festzulegen:

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 Updatestatus erhalten

Nach dem Start eines Updates erhält der Callback für den Launcher des registrierten Aktivitätsergebnisses Folgendes: 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.
            }
        }
    });

Die onActivityResult() kann verschiedene Werte erhalten. Callback:

  • RESULT_OK: Der Nutzer hat hat das Update akzeptiert. Für sofortige Updates ist dies möglicherweise nicht der Fall. da das Update bereits abgeschlossen sein sollte, an Ihre App zurückgegeben.
  • RESULT_CANCELED: Der Nutzer hat das Update abgelehnt oder abgebrochen.
  • ActivityResult.RESULT_IN_APP_UPDATE_FAILED: Aufgrund eines anderen Fehlers konnte der Nutzer seine Einwilligung nicht erteilen oder nicht fortfahren.

Flexible Aktualisierung verarbeiten

Wenn Sie ein flexibles Update starten, wird dem Nutzer zuerst ein Dialogfeld angezeigt, über das Sie ihn anfordern können. Einwilligung geben. Wenn der Nutzer einwilligt, wird der Download im Hintergrund gestartet und sodass der Nutzer weiterhin mit Ihrer App interagieren kann. In diesem Abschnitt wird beschrieben, wie Sie flexibles In-App-Update zu überwachen und durchzuführen.

Status der flexiblen Aktualisierung überwachen

Nach Beginn des Downloads für ein flexibles Update muss Ihre App die um zu erfahren, wann das Update installiert werden kann, und um die auf der Benutzeroberfläche Ihrer App.

Sie können den Status einer laufenden Aktualisierung überwachen, indem Sie einen Listener für und installieren Sie Statusupdates. Sie können auch eine Fortschrittsanzeige Nutzer über den Fortschritt des Downloads 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 den um das Update zu installieren.

Anders als bei sofortigen Updates löst Google Play eine App nicht automatisch aus. für ein flexibles Update neu starten. Das liegt daran, dass während eines flexiblen Updates Die Nutzenden erwarten, so lange mit der App zu interagieren, bis sie sich entscheiden, dass sie das Update installieren möchten.

Es wird empfohlen, eine Benachrichtigung (oder andere Hinweise auf der Benutzeroberfläche) bereitzustellen. um den Nutzer zu informieren, dass das Update installiert werden kann, und um Bestätigung anzufordern bevor Sie die App neu starten.

Das folgende Beispiel zeigt, wie ein Material Design über eine Snackbar Bestätigung des Nutzers, um 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 du anrufst appUpdateManager.completeUpdate() im Vordergrund zeigt die Plattform eine Benutzeroberfläche im Vollbildmodus an, über die die App neu gestartet wird. im Hintergrund. Nachdem die Plattform das Update installiert hat, startet deine App neu die Hauptaktivität.

Wenn du stattdessen completeUpdate() aufrufst, wenn sich deine App im Hintergrund, wird das Update im Hintergrund installiert ohne die Benutzeroberfläche des Geräts zu verdecken.

Immer wenn der Nutzer Ihre App in den Vordergrund bringt, sollten Sie prüfen, ob Ihre App ein Update zur Installation bereit. Wenn es für deine App ein Update in der DOWNLOADED gibt Status angezeigt wird, fordern Sie den Nutzer auf, das Update zu installieren. Andernfalls werden die aktualisierten Daten weiterhin den Gerätespeicher des Nutzers belegt.

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();
              }
          });
}

Sofortige Aktualisierung verarbeiten

Wenn du ein sofortiges Update startest und der Nutzer zustimmt, Google Play zeigt den Updatefortschritt während der gesamten die gesamte Dauer des Updates ab. Wenn der Nutzer Ihre App während Das Update sollte weiterhin im Hintergrund heruntergeladen und installiert werden. ohne zusätzliche Bestätigung durch den Nutzer.

Wenn Ihre App jedoch in den Vordergrund zurückkehrt, sollten Sie sich vergewissern, Update nicht im UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS Bundesstaat. Wenn das Update in diesem Status angehalten wurde, setze 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(). Ihre App sollte insbesondere in der Lage sein, Fälle zu handhaben, in denen ein Nutzer das Angebot ablehnt. aktualisieren oder den Download abbrechen. Wenn Nutzende eine dieser Aktionen ausführen, wird die Google Play-Benutzeroberfläche geschlossen. Ihre App sollte die beste Vorgehensweise bestimmen.

Wenn möglich, sollte der Nutzer ohne das Update fortfahren und ihn noch einmal auffordern . Wenn Ihre App ohne das Update nicht funktioniert, sollten Sie eine bevor Sie den Aktualisierungsvorgang neu starten oder den Nutzer dazu auffordern, schließen Sie die App. Auf diese Weise weiß der Nutzer, dass er Ihre App neu starten kann. wenn sie bereit sind, das erforderliche Update zu installieren.

Nächste Schritte

Teste die In-App-Updates, um dies zu prüfen ob Ihre Integration ordnungsgemäß funktioniert.