Obsługa aktualizacji w aplikacji (Kotlin lub Java)

W tym przewodniku opisujemy, jak obsługiwać reklamy w aplikacjach aktualizacje w aplikacji przy użyciu Kotlin lub Java. Istnieją osobne przewodniki dla przypadków, gdy implementacja korzysta z kodu natywnego (C/C++) i przypadki, w których implementacja korzysta z Unity.

Konfigurowanie środowiska programistycznego

Biblioteka aktualizacji Google Play w aplikacji jest częścią podstawowych bibliotek Google Play. Aby zintegrować Google Play w aplikacji, uwzględnij tę zależność Gradle Zaktualizuj bibliotekę.

Odlotowe

// 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")
    ...
}

Sprawdź dostępność aktualizacji

Zanim poprosisz o aktualizację, sprawdź, czy jest dostępna aktualizacja Twojej aplikacji. Używaj AppUpdateManager aby sprawdzić dostępność aktualizacji:

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

Zwrócone wartości AppUpdateInfo instancji zawiera stan dostępności aktualizacji. W zależności od stanu update, instancja zawiera też te elementy:

  • Jeśli aktualizacja jest dostępna i aktualizacja jest dozwolona, instancja również zawiera intencję rozpoczęcia aktualizacji.
  • Jeśli aktualizacja w aplikacji jest już w toku, instancja zgłasza też błąd stanu trwającej aktualizacji.

Sprawdź aktualność aktualizacji

Oprócz sprawdzenia, czy jest dostępna aktualizacja, możesz też sprawdzanie, ile czasu upłynęło od ostatniego powiadomienia użytkownika o aktualizacji; w Sklepie Play. Pomoże Ci to podjąć decyzję o zainicjowaniu lub natychmiastową aktualizację. Na przykład możesz odczekać kilka dni, przed powiadomieniem użytkownika o elastycznej aktualizacji i kilka dni później bez natychmiastowej aktualizacji.

Używaj clientVersionStalenessDays() aby sprawdzić, ile dni minęło od udostępnienia aktualizacji w Sklepie Play:

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

Sprawdź priorytet aktualizacji

Interfejs Google Play Developer API pozwala określić priorytet każdej aktualizacji. Dzięki temu aplikacja może zdecydować, jak zdecydowanie zalecić aktualizację użytkownikowi. Rozważ na przykład tę strategię ustalania priorytetu aktualizacji:

  • Drobne ulepszenia interfejsu: aktualizacja Niskiego priorytetu. nie żądają też elastycznego ani natychmiastowej aktualizacji. Aktualizuj tylko wtedy, gdy użytkownik nie wchodzi w interakcję z Twoją aplikacją.
  • Ulepszenia wydajności: aktualizacja o średnim priorytecie; poproś o elastyczną formę płatności .
  • Krytyczna aktualizacja zabezpieczeń: aktualizacja o wysokim priorytecie; poproś o natychmiastową prośbę .

Aby określić priorytet, Google Play używa liczby całkowitej z zakresu od 0 do 5, przy czym 0 to wartość domyślna, a 5 to najwyższy priorytet. Aby ustawić priorytet aktualizacji, użyj pola inAppUpdatePriority w kolumnie Edits.tracks.releases Google Play Developer API. Wszystkie nowo dodane wersje są uważane za takie samo jak wydanie. Priorytet można ustawić tylko wtedy, gdy podczas publikowania nowej wersji, której nie można później zmienić.

Ustaw priorytet przy użyciu interfejsu Google Play Developer API w sposób opisany w artykule na temat Google Play. Interfejs API dla programistów dokumentacji. Priorytet aktualizacji w aplikacji należy określić w Edit.tracks zasób przekazany w Edit.tracks: update . Ten przykład pokazuje publikowanie aplikacji z kodem wersji 88 i inAppUpdatePriority 5:

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

W kodzie aplikacji możesz sprawdzić priorytet danej aktualizacji, updatePriority() Zwracany priorytet uwzględnia inAppUpdatePriority dla wszystkich aplikacji między wersją zainstalowaną a najnowszą dostępną niezależnie od ścieżki wersji. Przeanalizujmy ten scenariusz:

  • Publikujesz wersję 1 na ścieżce produkcyjnej bez priorytetu.
  • Publikujesz wersję 2 na ścieżce testu wewnętrznego o priorytecie 5.
  • Publikujesz wersję 3 na ścieżce produkcyjnej bez priorytetu.

Gdy użytkownicy wersji produkcyjnej zaktualizują aplikację z wersji 1 do wersji 3, uzyskają priorytet 5, mimo że wersja 2 została opublikowana w innej ścieżce.

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

Rozpocznij aktualizację

Po potwierdzeniu, że aktualizacja jest dostępna, możesz poprosić o jej przywrócenie przy użyciu: 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());

Każdej instancji AppUpdateInfo można użyć do rozpoczęcia aktualizacji tylko raz. Aby spróbować ponownie, aktualizację w przypadku niepowodzenia, poproś o nowy AppUpdateInfo i sprawdź ponownie że aktualizacja jest dostępna i może być dozwolona.

Możesz zarejestrować program uruchamiający wyniki aktywności, używając wbudowanego ActivityResultContracts.StartIntentSenderForResult umowy. Zapoznaj się z sekcją na temat powiadomienie o stanie aktualizacji.

Kolejne kroki zależą od tego, czy zależy Ci na elastycznym aktualizację lub natychmiastową aktualizację.

Konfigurowanie aktualizacji przy użyciu AppUpdateOptions

AppUpdateOptions zawiera pole AllowAssetPackDeletion, które określa, czy aktualizacja jest mogą czyścić pakiety zasobów w przypadku ograniczona ilość miejsca na urządzeniu. Domyślna wartość w tym polu to false, ale możesz użyć setAllowAssetPackDeletion() ustaw ją na 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());

Poproś o oddzwonienie, aby sprawdzić stan aktualizacji

Po rozpoczęciu aktualizacji wywołanie zwrotne launchera zarejestrowanej aktywności otrzymuje wynik w oknie potwierdzenia:

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

Metoda onActivityResult() może zawierać kilka wartości, wywołanie zwrotne:

  • RESULT_OK: użytkownik ma zaakceptowała aktualizację. W przypadku natychmiastowych aktualizacji możesz nie otrzymać wywołanie zwrotne, ponieważ aktualizacja powinna już być zakończona, zanim element sterujący czasu to do aplikacji.
  • RESULT_CANCELED: użytkownik odrzuciła lub anulowała aktualizację.
  • ActivityResult.RESULT_IN_APP_UPDATE_FAILED: Jakiś inny błąd uniemożliwił użytkownikowi udzielenie zgody lub nie można kontynuować.

Elastyczna aktualizacja

Po rozpoczęciu elastycznej aktualizacji użytkownik zobaczy najpierw okno, w którym może poprosić zgody na wykorzystanie danych. Jeśli użytkownik wyrazi zgodę, pobieranie rozpocznie się w tle. użytkownik może nadal korzystać z aplikacji. Ta sekcja zawiera informacje na temat monitorować i dokonywać elastycznej aktualizacji w aplikacji.

Monitorowanie stanu elastycznej aktualizacji

Po rozpoczęciu pobierania elastycznej aktualizacji aplikacja musi monitorować stan aktualizacji, aby wiedzieć, kiedy można zainstalować aktualizację, i wyświetlić postęp w interfejsie aplikacji.

Możesz monitorować stan trwającej aktualizacji, rejestrując detektor aktualizacje stanu instalacji. W interfejsie aplikacji możesz też dodać pasek postępu, informowania użytkowników o postępach pobierania.

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

Instalowanie elastycznej aktualizacji

Po wykryciu stanu InstallStatus.DOWNLOADED musisz ponownie uruchomić aplikację by zainstalować aktualizację.

W przeciwieństwie do natychmiastowych aktualizacji Google Play nie aktywuje aplikacji automatycznie. Uruchom ponownie, aby uzyskać elastyczną aktualizację. Dzieje się tak, ponieważ podczas elastycznej aktualizacji użytkownik oczekuje, że będzie kontynuować interakcję z aplikacją, dopóki nie zdecyduje, że chcą ją zainstalować.

Zalecamy podanie powiadomienia (lub innego elementu interfejsu) aby poinformować użytkownika, że aktualizacja jest gotowa do instalacji, i poprosić o potwierdzenie. przed ponownym uruchomieniem aplikacji.

Poniższy przykład pokazuje implementację stylu Material Design pasek powiadomień, który wysyła żądanie potwierdzenie ponownego uruchomienia aplikacji przez użytkownika:

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

Gdy dzwonisz appUpdateManager.completeUpdate() na pierwszym planie platforma wyświetla pełnoekranowy interfejs użytkownika, który uruchamia aplikację ponownie. w tle. Gdy platforma zainstaluje aktualizację, aplikacja zostanie zrestartowana jako jego głównej działalności.

Jeśli zamiast tego wywołujesz completeUpdate(), gdy aplikacja jest w w tle, aktualizacja zostanie zainstalowana dyskretnie nie zasłaniając interfejsu urządzenia.

Za każdym razem, gdy użytkownik przenosi Twoją aplikację na pierwszy plan, sprawdź, czy aktualizacja oczekuje na zainstalowanie. Jeśli DOWNLOADED zawiera aktualizację Twojej aplikacji , poproś użytkownika o zainstalowanie aktualizacji. W przeciwnym razie dane nadal zajmują pamięć urządzenia użytkownika.

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

Natychmiastowa aktualizacja

Gdy rozpoczniesz natychmiastową aktualizację, a użytkownik wyrazi na nią zgodę, Google Play wyświetla postęp aktualizacji nad interfejsem aplikacji przez cały przez cały czas trwania aktualizacji. Jeśli użytkownik zamknie aplikację w trakcie Aktualizacja powinna być nadal pobierana i instalowana w tle bez dodatkowego potwierdzenia ze strony użytkownika.

Gdy jednak aplikacja wróci na pierwszy plan, upewnij się, że tag aktualizacja nie jest wstrzymywana UpdateAvailability.DEVELOPER_TRIGGERED_UPDATE_IN_PROGRESS stanu. Jeśli aktualizacja utknęła w tym stanie, wznów ją:

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

Proces aktualizacji zwraca wynik zgodny z opisem w dokumentacji dotyczącej startUpdateFlowForResult(), Aplikacja powinna być w szczególności w stanie obsługiwać przypadki, gdy użytkownik odrzuci zaktualizuje albo anuluje pobieranie. Gdy użytkownik wykona jedną z tych czynności, interfejs Google Play zostanie zamknięty. Aplikacja powinna określić najlepszy sposób postępowania.

Jeśli to możliwe, pozwól użytkownikowi kontynuować bez aktualizacji i ponownie poproś go o aktualizację. później. Jeśli aplikacja bez aktualizacji nie będzie mogła działać, warto wyświetlić komunikat informacyjny przed ponownym rozpoczęciem aktualizacji lub prośbą o Zamknij aplikację. Dzięki temu użytkownik będzie wiedział, że może ponownie uruchomić aplikację. gdy będą gotowi do zainstalowania wymaganej aktualizacji.

Dalsze kroki

Testowanie aktualizacji aplikacji. czy integracja działa poprawnie.