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

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

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

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] を選択して、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 ファイルをインポートします。

Unity SDK の概要

Play In-app Update API は、Play Core SDK ファミリーの一部です。Unity プラグインには、アプリと Play API 間の通信を処理するための AppUpdateManager クラスが用意されています。アプリ内アップデートの管理に使用するには、まずこのクラスをインスタンス化する必要があります。

AppUpdateManager appUpdateManager = new AppUpdateManager();

入手可能なアップデートの有無を確認する

アップデートをリクエストする前に、アプリに適用できるアップデートが存在するかどうかを確認します。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(), etc. 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 では、各アップデートの優先度を設定できます。 これにより、アプリはユーザーにアップデートを推奨する度合いを決定できるようになります。たとえば、アップデートの優先度を設定するための次のような戦略を考えてみます。

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

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

Google Play Developer API を使用した優先度の設定については、Play Developer 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 と署名鍵を持つアプリの更新バージョンが存在することを確認してください。
  • PlayAsyncOperationErrorUpdateNotAllowed エラーコードを返す場合は、AppUpdateOptions オブジェクトが入手可能なアップデートで許可されていないアップデート タイプを示していることを表しています。アップデート フローを開始する前に、選択したアップデート タイプが許可されていることを AppUpdateInfo オブジェクトが示しているかどうかを確認してください。

次のステップ

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