支持应用内更新(Unity)

本指南介绍了如何使用 Unity 在应用中支持应用内更新。另有单独的指南,分别介绍了您的实现使用Kotlin 编程语言或 Java 编程语言的情况,以及您的实现使用原生代码 (C/C++) 的情况。

Unity SDK 概览

Play 应用内更新 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 作为范围注册表添加到包管理器窗口

    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. 将管理器范围下拉菜单设为选择 My Registries

  5. 从包列表中选择 Google Play Integrity plugin for Unity 包,然后按 Install

从 GitHub 导入

  1. 从 GitHub 下载最新版 .unitypackage

  2. 选择 Unity 菜单选项 Assets > Import package > Custom Package 并导入所有项,以导入 .unitypackage 文件。

检查更新是否可用

在请求更新之前,请检查您的应用是否有可用更新。使用 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 实例包含更新可用性状态。如果应用内更新已在进行中,该实例还会报告正在进行的更新的状态。

检查更新过时情况

除了检查更新是否可用外,您可能还需要检查自上次通过 Play 商店通知用户更新以来过了多长时间。这可以帮助您决定是启动灵活更新还是立即更新。例如,您可能会等待几天再通过灵活更新通知用户,再过几天后再要求立即更新。

使用 ClientVersionStalenessDays 检查更新通过 Play 商店发布以来经过的天数

var stalenessDays = appUpdateInfoOperation.ClientVersionStalenessDays;

检查更新优先级

通过 Google Play 开发者 API,您可以设置每次更新的优先级。这样一来,您的应用就可以决定向用户推荐更新的强度。例如,可以考虑以下设置更新优先级的策略:

  • 次要界面改进:低优先级更新;既不请求灵活更新,也不请求立即更新。
  • 性能改进:中优先级更新;请求灵活更新。
  • 关键安全更新:高优先级更新;请求立即更新。

为了确定优先级,Google Play 使用一个介于 0 到 5 之间的整数值,其中 0 为默认值,5 为最高优先级。要为更新设置优先级,请使用 Google Play 开发者 API 中 Edits.tracks.releases 下的 inAppUpdatePriority 字段。发布版本中的所有新添加版本都将被视为与该发布版本具有相同的优先级。优先级只能在新发布版本推出时设置,以后无法更改。

按照Play 开发者 API 文档中的说明,使用 Google Play 开发者 API 设置优先级。应用内更新优先级应在 Edit.tracks: update 方法中传递的 Edit.tracks 资源中指定。以下示例展示了如何发布版本代码为 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。在开始更新流程之前,请确保从 GetAppUpdateInfo() 返回的 AppUpdateInfo 对象不为 null。
  • 如果 PlayAsyncOperation 返回 ErrorUpdateUnavailable 错误代码,请确保有可用的更新应用版本,并且该版本具有相同的应用 ID 和签名密钥。
  • 如果 PlayAsyncOperation 返回 ErrorUpdateNotAllowed 错误代码,则表示 AppUpdateOptions 对象指示的更新类型不允许进行可用更新。在开始更新流程之前,请检查 AppUpdateInfo 对象是否指示所选更新类型允许。

后续步骤

测试您应用的应用内更新,以验证您的集成是否正常工作。