支持应用内更新 (Unreal Engine)

本指南介绍了如何使用 Unreal Engine 在您的应用中支持应用内更新。我们针对使用 Kotlin 编程语言或 Java 编程语言以及原生代码 (C/C++)Unity 完成实现的情况分别提供了指南。

Unreal Engine SDK 概览

Play 应用内更新 API 是 Play Core SDK 系列的一部分。Unreal Engine 的 API 提供了 UInAppUpdatesManager 类,用于处理应用与 Play API 之间的通信。发出请求后,您的应用可以使用 EAppUpdateErrorCode 检查请求的状态。

支持的 Unreal Engine 版本

该插件支持 Unreal Engine 5.0 及所有后续版本。

设置您的开发环境

  1. 从 GitHub 代码库下载 Play Unreal Engine 插件

  2. GooglePlay 文件夹复制到 Unreal Engine 项目的 Plugins 文件夹中。

  3. 打开您的 Unreal Engine 项目,然后依次点击 Edit(修改)→ Plugins(插件)

  4. 搜索 Google Play,然后选中 Enabled(已启用)复选框。

  5. 重新启动游戏项目并触发构建。

  6. 打开项目的 Build.cs 文件,然后将 PlayInAppUpdates 模块添加到 PublicDependencyModuleNames

    using UnrealBuildTool;
    
    public class MyGame : ModuleRules
    {
      public MyGame(ReadOnlyTargetRules Target) : base(Target)
      {
        // ...
    
        PublicDependencyModuleNames.Add("PlayInAppUpdates");
    
        // ...
      }
    }
    

检查是否有可用更新

在请求更新之前,请检查您的应用是否有可用更新。使用 UInAppUpdatesManager::RequestInfo 检查是否有更新:

MyClass.h

void MyClass::OnRequestInfoOperationCompleted(
  EAppUpdateErrorCode ErrorCode,
  UAppUpdateInfo* UpdateInfo)
{
  // Check the resulting error code.
  if (ErrorCode == EAppUpdateErrorCode::AppUpdate_NO_ERROR)
  {
    // Check AppUpdateInfo's UpdateAvailability, UpdatePriority,
    // IsUpdateTypeAllowed(), ... and decide whether to ask the user
    // to start an in-app update.
  }
}

MyClass.cpp

void MyClass::CheckForUpdateAvailability()
{
  // Create a delegate to bind the callback function.
  FRequestInfoOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnRequestInfoOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnRequestInfoOperationCompleted);

  // Initiate the request info operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->RequestInfo(Delegate);
}

返回的 UAppUpdateInfo 实例包含更新可用性状态。如果应用内更新已在进行中,实例还会报告正在进行的更新的状态。

检查更新是否已过时

除了检查是否有可用更新之外,您可能还需要确定自您通过 Play 商店通知用户有更新以来已经过了多长时间。您可以根据这一信息来决定是允许用户灵活更新,还是立即发起更新。例如,您可以等待几天后再通知用户进行灵活更新,再等待几天后要求用户立即更新。

您可以使用 UAppUpdateInfo:GetClientVersionStalenessDays 检查更新在 Play 商店中发布后的天数:

int32 ClientVersionStalenessDays = UpdateInfo->GetClientVersionStalenessDays();

检查更新优先级

借助 Google Play Developer API,您可以设置每次更新的优先级。这样,您的应用就可以决定向用户推荐更新的强度。例如,我们来考虑以下关于如何设置更新优先级的策略:

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

Google Play 使用 0 到 5 之间的整数值来确定优先级,其中 0 是默认值,5 代表最高优先级。如需设置更新的优先级,请使用 Google Play Developer API 中 Edits.tracks.releases 下的 inAppUpdatePriority 字段。发布版本中的所有新增版本都被视为与发布版本具有相同的优先级。只有在发布新版本时才能设置优先级,且以后无法更改。

Play Developer API 文档中所述使用 Google Play Developer API 设置优先级。应用内更新优先级应在以 Edit.tracks: update 方法传递的 Edit.tracks 资源中指定。以下示例演示了发布版本代码为 88 且 inAppUpdatePriority 为 5 的应用:

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

在应用的代码中,您可以使用 UAppUpdateInfo::UpdatePriority 来检查给定更新的优先级:

int32 Priority = UpdateInfo->GetPriority();

启动更新

在确认有可用更新后,您可以使用 UInAppUpdatesManager::StartUpdate 请求更新。在请求更新之前,请确保您拥有最新的 UAppUpdateInfo 对象。您还必须创建 UAppUpdateOptions 对象以配置更新流程。

以下示例针对立即更新流程创建了 UAppUpdateOptions 对象:

// Creates an UAppUpdateOptions defining an immediate in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_IMMEDIATE);

以下示例针对灵活更新流程创建了 UAppUpdateOptions 对象:

// Creates an UAppUpdateOptions defining a flexible in-app
// update flow and its parameters.
UAppUpdateOptions* Options = NewObject<UAppUpdateOptions>();
Options->CreateOptions(EAppUpdateType::AppUpdate_TYPE_FLEXIBLE);

UAppUpdateOptions 对象还包含一个 IsAssetPackDeletionAllowed 函数,用于返回是否允许更新在设备存储空间有限的情况下清除资源包。此字段默认设置为 false,但您可以使用 UAppUpdateOptions::SetAssetPackDeletionAllowed 将其设置为 true

// Sets the AssetPackDeletionAllowed field to true.
Options->SetAssetPackDeletionAllowed(true);

后续步骤取决于您是请求灵活更新还是立即更新

处理灵活更新

在获取最新的 UAppUpdateInfo 对象且正确配置 UAppUpdateOptions 对象后,您可以调用 UInAppUpdatesManager::StartUpdate 来请求更新流程。

MyClass.h

void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

// .cpp
void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);

  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}

针对灵活更新流程,在下载成功完成后,您必须触发安装应用更新。为此,请调用 InAppUpdatesManager::CompleteUpdate,如以下示例所示:

MyClass.h

void MyClass::OnCompleteUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

void MyClass::CompleteFlexibleUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnCompleteUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnCompleteUpdateOperationCompleted);

  // Initiate the complete update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->CompleteUpdate(UpdateInfo, UpdateOptions, Delegate);
}

处理立即更新

在获取最新的 UAppUpdateInfo 对象且正确配置 UAppUpdateOptions 对象后,您可以调用 InAppUpdatesManager::StartUpdate 来请求更新流程。

MyClass.h

void MyClass::OnStartUpdateOperationCompleted(EAppUpdateErrorCode ErrorCode)
{
  // ...
}

MyClass.cpp

void MyClass::StartUpdate()
{
  // Create a delegate to bind the callback function.
  FUpdateOperationCompletedDelegate Delegate;

  // Bind the completion handler (OnStartUpdateOperationCompleted) to the delegate.
  Delegate.BindDynamic(this, &MyClass::OnStartUpdateOperationCompleted);

  // Initiate the start update operation, passing the delegate to handle the result.
  GetGameInstance()
    ->GetSubsystem<UInAppUpdatesManager>()
    ->StartUpdate(UpdateInfo, UpdateOptions, Delegate);
}

对于立即更新流程,Google Play 会显示一个用户确认对话框。 用户接受请求后,Google Play 会自动下载并安装更新,然后在安装成功后重启应用以使用更新后的版本。

错误处理

本部分将介绍一些常见错误的解决方案。

  • 如果 UInAppUpdatesManager::StartUpdate 返回 AppUpdate_INVALID_REQUEST 错误,则表示 UAppUpdateInfo 无效。在启动更新流程之前,请确保从 UInAppUpdatesManager::RequestInfo 返回的 UAppUpdateInfo 对象不为 null。
  • 如果 UInAppUpdatesManager::StartUpdate 返回 AppUpdate_NOT_ALLOWED 错误,则表示 UAppUpdateOptions 对象指明的更新类型不允许用于可用更新。在启动更新流程之前,请检查 UAppUpdateInfo 对象是否指明允许所选的更新类型。

后续步骤

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