アプリ内アップデートをサポートする(Unreal Engine)

このガイドでは、Unreal Engine を使用してアプリ内でアプリ内アップデートをサポートする方法について説明します。実装に Kotlin プログラミング言語または Java プログラミング言語を使用するケースと、ネイティブ コード(C/C++)または Unity を使用するケースについては、個別のガイドが用意されています。

Unreal Engine SDK の概要

Play In-App Updates API は Play Core SDK ファミリーの一部です。Unreal Engine の API には、アプリと Play API 間の通信を処理する UInAppUpdatesManager クラスが用意されています。リクエストの実行後、アプリは EAppUpdateErrorCode を使用してリクエストのステータスを確認できます。

サポートされている Unreal Engine のバージョン

このプラグインは、Unreal Engine 5.0 以降のすべてのバージョンをサポートしています。

開発環境をセットアップする

  1. GitHub リポジトリから Play Unreal Engine Plugin をダウンロードします。

  2. Unreal Engine プロジェクトの Plugins フォルダ内に GooglePlay フォルダをコピーします。

  3. Unreal Engine プロジェクトを開き、[編集 → プラグイン] をクリックします。

  4. [Google Play] を検索し、[有効] チェックボックスをオンにします。

  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 インスタンスには、アップデートの有無を示すステータスが含まれます。アプリ内アップデートがすでに進行中の場合、インスタンスは進行中のアップデートのステータスも報告します。

アップデートの新しさの確認

アップデートが適用可能であるかどうかを確認するだけでなく、ユーザーが Google Play ストアからアップデートの通知を受信してから経過した期間を確認することもできます。これは、フレキシブル アップデートと即時アップデートのどちらを開始したらよいかを判断する際に有用です。たとえば、ユーザーにフレキシブル アップデートを通知するまで数日待ち、その後、即時アップデートを要求するまでさらに数日待つこともできます。

UAppUpdateInfo:GetClientVersionStalenessDays を使用して、Google Play ストアからのアップデートの入手が可能になった時点から経過した日数を確認します。

int32 ClientVersionStalenessDays = UpdateInfo->GetClientVersionStalenessDays();

アップデートの優先度の確認

Google Play Developer API を使用すると、各アップデートの優先度を設定できます。これにより、アプリはユーザーへの更新の推奨度を決定できます。たとえば、アップデートの優先度を設定するための次のような戦略を考えてみます。

  • UI の小さな改善: 優先度が低いアップデート。フレキシブル アップデート、即時アップデートのいずれもリクエストしません。
  • パフォーマンスの改善: 優先度が中程度のアップデート。フレキシブル アップデートをリクエストします。
  • 重要なセキュリティ アップデート: 優先度が高いアップデート。即時アップデートをリクエストします。

優先度を決定するにあたり、Google Play は 0~5 の整数値を使用します。0 はデフォルトの値、5 は優先度が最も高い値です。アップデートの優先度を設定するには、Google Play Developer API の Edits.tracks.releases の下にある inAppUpdatePriority フィールドを使用します。リリースで新たに追加されたすべてのバージョンの優先度は、リリースと同じとみなされます。優先度は新しいリリースの公開時にのみ設定できます。後から変更することはできません。

Google 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::StartUpdateAppUpdate_INVALID_REQUEST エラーを返した場合、UAppUpdateInfo が無効であることを意味します。アップデート フローを開始する前に、UInAppUpdatesManager::RequestInfo から返された UAppUpdateInfo オブジェクトが null でないことを確認してください。
  • UInAppUpdatesManager::StartUpdateAppUpdate_NOT_ALLOWED エラーを返した場合、UAppUpdateOptions オブジェクトが、利用可能なアップデートで許可されていない更新タイプを示していることを意味します。アップデート フローを開始する前に、選択したアップデート タイプが許可されていることを UAppUpdateInfo オブジェクトが示しているかどうかを確認してください。

次のステップ

アプリのアプリ内アップデートをテストして、統合が正しく機能していることを確認します。