Как настроить обновления в приложении (Unity)

В этом руководстве рассказывается, как реализовать поддержку обновлений в приложении с помощью Unity. Существуют отдельные руководства для случаев, когда в вашей реализации используется язык программирования Kotlin или Java, и случаев, когда в вашей реализации используется нативный код (C/C++).

Обзор Unity SDK

Play In-App Update API входит в семейство Play Core SDK. Плагин Unity предлагает класс AppUpdateManager для обработки взаимодействия между вашим приложением и Google Play API. Чтобы управлять обновлениями в приложении, создайте экземпляр этого класса:

AppUpdateManager appUpdateManager = new AppUpdateManager();

Как настроить среду разработки

OpenUPM-CLI

Если у вас установлен OpenUPM CLI, вы можете установить реестр OpenUPM с помощью следующей команды:

openupm add com.google.play.appupdate

OpenUPM

  1. Откройте настройки менеджера пакетов, выбрав в меню Unity Edit (Редактировать) > Project Settings (Настройки проекта) > Package Manager (Менеджер пакетов).

  2. Добавьте OpenUPM в качестве реестра с ограниченной областью действия в окне Package Manager (Менеджер пакетов):

    Name: package.openupm.com
    URL: https://package.openupm.com
    Scopes: com.google.external-dependency-manager
      com.google.play.common
      com.google.play.core
      com.google.play.appupdate
    
  3. Откройте меню менеджера пакетов, выбрав в меню Unity Window (Окно) > Package Manager (Менеджер пакетов).

  4. В раскрывающемся списке "Область действия менеджера" выберите Мои реестры.

  5. Выберите пакет Google Play Integrity plugin for Unity из списка и нажмите Install (Установить).

Импортировать из GitHub

  1. Скачайте последнюю версию .unitypackage с сайта GitHub.

  2. Импортируйте файл .unitypackage, выбрав в меню Unity Assets (Объекты) > Import package (Импортировать пакет) > Custom Package (Пользовательский пакет), и импортируйте все элементы.

Проверьте наличие обновлений

Прежде чем запрашивать обновление, проверьте, доступно ли оно для вашего приложения. Чтобы проверить наличие обновления в сопрограмме, используйте AppUpdateManager.

IEnumerator CheckForUpdate()
{
  PlayAsyncOperation<AppUpdateInfo, AppUpdateErrorCode> appUpdateInfoOperation =
    appUpdateManager.GetAppUpdateInfo();

  // Wait until the asynchronous operation completes.
  yield return appUpdateInfoOperation;

  if (appUpdateInfoOperation.IsSuccessful)
  {
    var appUpdateInfoResult = appUpdateInfoOperation.GetResult();
    // Check AppUpdateInfo's UpdateAvailability, UpdatePriority,
    // IsUpdateTypeAllowed(), ... and decide whether to ask the user
    // to start an in-app update.
  }
  else
  {
    // Log appUpdateInfoOperation.Error.
  }
}

Возвращенный экземпляр AppUpdateInfo содержит статус доступности обновления. Если обновление приложения уже выполняется, экземпляр также сообщает о статусе выполняющегося обновления.

Проверка актуальности обновления

Помимо проверки наличия обновления, вы также можете проверить, сколько времени прошло с момента последнего уведомления пользователя об обновлении через Google Play. Это поможет вам решить, какое обновление запустить: гибкое или немедленное. Например, вы можете подождать несколько дней, прежде чем уведомить пользователя о гибком обновлении, и ещё несколько дней, прежде чем потребовать немедленного обновления.

Используйте ClientVersionStalenessDays, чтобы узнать, сколько дней прошло с момента, когда обновление стало доступно в Google Play.

var stalenessDays = appUpdateInfoOperation.ClientVersionStalenessDays;

Проверить приоритет обновления

Google Play Developer API позволяет задавать приоритет для каждого обновления. Это позволяет приложению решить, насколько настойчиво рекомендовать пользователю обновление. Например, можно использовать следующую стратегию:

  • Незначительные улучшения интерфейса. Низкий приоритет. Не запрашивайте ни гибкое, ни немедленное обновление.
  • Улучшение производительности. Средний приоритет. Запросите гибкое обновление.
  • Критическое обновление системы безопасности – высокий приоритет, требуется немедленное обновление.

Для определения приоритета Google Play использует целое число от 0 до 5, где 0 – значение по умолчанию, а 5 – наивысший приоритет. Чтобы задать приоритет обновления, используйте поле inAppUpdatePriority в разделе Edits.tracks.releases в Google Play Developer API. Все новые версии в выпуске имеют тот же приоритет, что и сам выпуск. Приоритет можно задать только при выпуске новой версии, и его нельзя изменить позже.

Задайте приоритет с помощью Google Play Developer API, как описано в документации по Play Developer API. Приоритет обновления в приложении должен быть указан в ресурсе Edit.tracks, который передается в методе Edit.tracks: update. В примере ниже показан выпуск приложения с кодом версии 88 и inAppUpdatePriority 5:

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

В коде приложения можно проверить уровень приоритета для определенного обновления с помощью UpdatePriority:

var priority = appUpdateInfoOperation.UpdatePriority;

Как начать обновление

Убедившись, что обновление доступно, вы можете запросить его с помощью метода AppUpdateManager.StartUpdate(). Прежде чем запрашивать обновление, убедитесь, что у вас есть актуальный объект AppUpdateInfo. Вам также нужно создать объект AppUpdateOptions, чтобы настроить процесс обновления.

В примере ниже создается объект AppUpdateOptions для немедленного обновления.

// Creates an AppUpdateOptions defining an immediate in-app
// update flow and its parameters.
var appUpdateOptions = AppUpdateOptions.ImmediateAppUpdateOptions();

В примере ниже создается объект AppUpdateOptions для гибкого обновления:

// Creates an AppUpdateOptions defining a flexible in-app
// update flow and its parameters.
var appUpdateOptions = AppUpdateOptions.FlexibleAppUpdateOptions();

Объект AppUpdateOptions также содержит поле AllowAssetPackDeletion, которое определяет, разрешено ли обновлению удалять пакеты объектов, если на хранилище устройства недостаточно места. По умолчанию в этом поле задано значение false, но вы можете передать необязательный аргумент allowAssetPackDeletion в ImmediateAppUpdateOptions() или FlexibleAppUpdateOptions(), чтобы задать значение true:

// Creates an AppUpdateOptions for an immediate flow that allows
// asset pack deletion.
var appUpdateOptions =
  AppUpdateOptions.ImmediateAppUpdateOptions(allowAssetPackDeletion: true);

// Creates an AppUpdateOptions for a flexible flow that allows asset
// pack deletion.
var appUpdateOptions =
  AppUpdateOptions.FlexibleAppUpdateOptions(allowAssetPackDeletion: true);

Дальнейшие действия зависят от того, какое обновление вы запрашиваете: гибкое или немедленное.

Как обработать гибкое обновление

После того как вы создадите актуальный объект AppUpdateInfo и правильно настроите объект AppUpdateOptions, вызовите метод AppUpdateManager.StartUpdate(), чтобы асинхронно запросить процесс обновления.

IEnumerator StartFlexibleUpdate()
{
  // Creates an AppUpdateRequest that can be used to monitor the
  // requested in-app update flow.
  var startUpdateRequest = appUpdateManager.StartUpdate(
    // The result returned by PlayAsyncOperation.GetResult().
    appUpdateInfoResult,
    // The AppUpdateOptions created defining the requested in-app update
    // and its parameters.
    appUpdateOptions);

  while (!startUpdateRequest.IsDone)
  {
  // For flexible flow,the user can continue to use the app while
  // the update downloads in the background. You can implement a
  // progress bar showing the download status during this time.
  yield return null;
  }

}

При гибком обновлении вы должны запустить установку обновления приложения после успешного завершения скачивания. Для этого вызовите AppUpdateManager.CompleteUpdate(), как показано в примере ниже.

IEnumerator CompleteFlexibleUpdate()
{
  var result = appUpdateManager.CompleteUpdate();
  yield return result;

  // If the update completes successfully, then the app restarts and this line
  // is never reached. If this line is reached, then handle the failure (e.g. by
  // logging result.Error or by displaying a message to the user).
}

Как обработать немедленное обновление

После того как вы создадите актуальный объект AppUpdateInfo и правильно настроите объект AppUpdateOptions, вызовите метод AppUpdateManager.StartUpdate(), чтобы асинхронно запросить процесс обновления.

IEnumerator StartImmediateUpdate()
{
  // Creates an AppUpdateRequest that can be used to monitor the
  // requested in-app update flow.
  var startUpdateRequest = appUpdateManager.StartUpdate(
    // The result returned by PlayAsyncOperation.GetResult().
    appUpdateInfoResult,
    // The AppUpdateOptions created defining the requested in-app update
    // and its parameters.
    appUpdateOptions);
  yield return startUpdateRequest;

  // If the update completes successfully, then the app restarts and this line
  // is never reached. If this line is reached, then handle the failure (for
  // example, by logging result.Error or by displaying a message to the user).
}

При немедленном обновлении Google Play показывает диалоговое окно с запросом подтверждения. Если пользователь соглашается, Google Play автоматически скачивает и устанавливает обновление, а затем перезапускает приложение.

Обработка ошибок

В этом разделе описаны решения распространенных проблем.

  • Если StartUpdate() выдает ArgumentNullException, это означает, что AppUpdateInfo имеет значение null. Прежде чем запускать процесс обновления, убедитесь, что объект AppUpdateInfo, возвращенный из GetAppUpdateInfo(), не равен null.
  • Если PlayAsyncOperation возвращает код ошибки ErrorUpdateUnavailable, убедитесь, что доступна обновленная версия приложения с тем же идентификатором приложения и ключом подписи.
  • Если метод PlayAsyncOperation возвращает код ошибки ErrorUpdateNotAllowed, это означает, что объект AppUpdateOptions указывает на тип обновления, который не разрешен для доступного обновления. Прежде чем запускать процесс обновления, проверьте, разрешен ли выбранный тип обновления в объекте AppUpdateInfo.

Дальнейшие действия

Протестируйте обновления в приложении, чтобы убедиться, что интеграция работает правильно.