このガイドでは、Unity を使用してアプリ内でアプリ内アップデートをサポートする方法について説明します。実装に Kotlin プログラミング言語または Java プログラミング言語を使用するケースと、ネイティブ コード(C/C++)を使用するケースについては、個別のガイドが用意されています。
Unity SDK の概要
Play アプリ内アップデート API は Play Core SDK ファミリーの一部です。Unity プラグインには、アプリと Google Play API 間の通信を処理する AppUpdateManager クラスが用意されています。このクラスを使用してアプリ内アップデートを管理するには、このクラスをインスタンス化する必要があります。
AppUpdateManager appUpdateManager = new AppUpdateManager();
開発環境をセットアップする
OpenUPM-CLI
OpenUPM CLI がインストールされている場合は、次のコマンドを使用して OpenUPM レジストリをインストールできます。
openupm add com.google.play.appupdateOpenUPM
Unity のメニュー オプション [Edit] > [Project Settings] > [Package Manager] を選択して、パッケージ マネージャーの設定を開きます。
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.appupdateUnity メニュー オプションの [Window] > [Package Manager] を選択して、Package Manager メニューを開きます。
マネージャー スコープのプルダウンで [My Registries] を選択します。
パッケージ リストから Google Play Integrity plugin for Unity パッケージを選択し、[Install] を押します。
GitHub からインポートする
GitHub から最新の
.unitypackageリリースをダウンロードします。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 インスタンスには、アップデートの有無を示すステータスが含まれます。アプリ内アップデートがすでに進行中の場合は、進行中のアップデートのステータスも報告されます。
アップデートの新しさの確認
アップデートが適用可能であるかどうかを確認するだけでなく、ユーザーが 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 を使用した優先度の設定については、Google 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 と署名鍵を持つアプリの更新バージョンが存在することを確認してください。PlayAsyncOperationからErrorUpdateNotAllowedエラーコードが返された場合、AppUpdateOptionsオブジェクトが、利用可能なアップデートで許可されていない更新タイプを示していることを意味します。アップデート フローを開始する前に、選択したアップデート タイプが許可されていることをAppUpdateInfoオブジェクトが示しているかどうかを確認してください。
次のステップ
アプリのアプリ内アップデートをテストして、統合が正しく機能していることを確認します。