アプリ内アップデートをサポートする(ネイティブ)

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

ネイティブ SDK の概要

Play Core Native SDK は Play Core SDK ファミリーに含まれています。Native SDK には、Java Play Core SDK からの AppUpdateManager をラップする C ヘッダー ファイル app_update.h が含まれています。このヘッダー ファイルを使用すると、ネイティブ コードから直接アプリ内アップデート用の API を呼び出すことができます。

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

開発環境を設定するには、Play Core Library ガイドのネイティブのセクションに記載されているセットアップ手順を実施します。

Play Core Native SDK をプロジェクトに統合したら、API 呼び出しを含むファイルに次の行を含めます。

#include "play/app_update.h"

アプリ内アップデートの API を初期化する

アプリ内アップデートの API を使用するときは、まず AppUpdateManager_init() を呼び出して初期化する必要があります。android_native_app_glue.h を使用してビルドされた次の例をご覧ください。

void android_main(android_app* app) {
  app->onInputEvent = HandleInputEvent;

  AppUpdateErrorCode error_code =
    AppUpdateManager_init(app->activity->vm, app->activity->clazz);
  if (error_code == APP_UPDATE_NO_ERROR) {
    // You can use the API.
  }
}

アップデートの有無の確認

アップデートをリクエストする前に、アプリに利用できるアップデートがあるかどうかを確認します。AppUpdateManager_requestInfo() により、後でアプリ内レビューフローを起動するために必要な情報を収集する非同期リクエストが開始されます。リクエストが正常に開始すると、関数は APP_UPDATE_NO_ERROR を返します。

AppUpdateErrorCode error_code = AppUpdateManager_requestInfo()

if (error_code == APP_UPDATE_NO_ERROR) {
    // The request has successfully started, check the result using
    // AppUpdateManager_getInfo.
}

AppUpdateManager_getInfo() を使用すると、リクエストの継続的なプロセスと結果を追跡できます。エラーコードに加えて、この関数は AppUpdateInfo 不透明構造体を返します。これを使用して、更新リクエストに関する情報を取得できます。たとえば、info に対して null 以外の結果が返されるまで、すべてのゲームループでこの関数を呼び出すことができます。

AppUpdateInfo* info;
GameUpdate() {

   // Keep calling this in every game loop until info != nullptr
   AppUpdateErrorCode error_code = AppUpdateManager_getInfo(&info);

   if (error_code == APP_UPDATE_NO_ERROR && info != nullptr) {
       // Successfully started, check the result in the following functions
   }
...
}

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

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

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

int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);

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

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"
  }]
}

アプリのコードで、AppUpdateInfo_getPriority() を使用して特定のアップデートの優先度を確認できます。

int32_t priority = AppUpdateInfo_getPriority(info);

アップデートの開始

アップデートが利用可能であることを確認したら、AppUpdateManager_requestStartUpdate() を使用してアップデートをリクエストできます。アップデートをリクエストする前に、最新の AppUpdateInfo オブジェクトを取得し、AppUpdateOptions オブジェクトを作成して、アップデート フローを構成します。AppUpdateOptions オブジェクトでは、アプリ内アップデート フローのオプション(アップデートをフレキシブルと即時のどちらにするかを含む)を定義します。

次の例では、フレキシブル アップデート フロー用の AppUpdateOptions オブジェクトを作成します。

// Creates an AppUpdateOptions configuring a flexible in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_FLEXIBLE, &options);

次の例では、即時アップデート フロー用の AppUpdateOptions オブジェクトを作成します。

// Creates an AppUpdateOptions configuring an immediate in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_IMMEDIATE, &options);

また、AppUpdateOptions オブジェクトには AllowAssetPackDeletion フィールドも含まれており、デバイスのストレージが限られている場合に、アップデートでアセットパックの消去を許可するかどうかを定義します。このフィールドはデフォルトでは false に設定されていますが、代わりに AppUpdateOptions_setAssetPackDeletionAllowed() メソッドを使用して true に設定することもできます。

bool allow = true;
AppUpdateErrorCode error_code = AppUpdateOptions_setAssetPackDeletionAllowed(options, allow);

最新の AppUpdateInfo オブジェクトと、適切に構成された AppUpdateOptions オブジェクトを取得後、AppUpdateManager_requestStartUpdate() を呼び出してアップデート フローを非同期リクエストし、最後のパラメータの Android のアクティビティ jobject で渡します。

AppUpdateErrorCode request_error_code =
AppUpdateManager_requestStartUpdate(info, options, app->activity->clazz);

リソースを解放するには、不要になった AppUpdateInfoAppUpdateOptions のインスタンスを、AppUpdateInfo_destroy()AppUpdateOptions_destroy() をそれぞれ呼び出すことでリリースします。

AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);

即時アップデート フローの場合、Google Play にはユーザーの確認ページが表示されます。ユーザーがリクエストを承認すると、Google Play はフォアグラウンドでアップデートのダウンロードとインストールを自動的に行い、インストールが成功するとアプリを再起動して更新したバージョンにします。

フレキシブル アップデート フローでは、ユーザーがアプリの使用を続けながら、最新の AppUpdateInfo オブジェクトのリクエストを継続し、現在の更新ステータスを追跡できます。ダウンロードが正常に完了したら、次の例に示すように、AppUpdateManager_requestCompleteUpdate() を呼び出してアップデートの完了をトリガーする必要があります。

AppUpdateStatus status = AppUpdateInfo_getStatus(info);
if (status == APP_UPDATE_DOWNLOADED) {
    AppUpdateErrorCode error_code = AppUpdateManager_requestCompleteUpdate();
    if (error_code != APP_UPDATE_NO_ERROR)
    {
      // There was an error while completing the update flow.
    }
}

アプリで API の使用が終了したら、AppUpdateManager_destroy() 関数を呼び出してリソースを解放します。

エラー処理

このセクションでは、特定の AppUpdateErrorCode 値で示される一般的なエラーの解決策について説明します。

  • エラーコード -110, APP_UPDATE_INITIALIZATION_NEEDED は、API が正常に初期化されていないことを示します。AppUpdateManager_init() を呼び出して API を初期化します。
  • エラーコード -4, APP_UPDATE_INVALID_REQUEST は、アップデート フロー リクエストの一部のパラメータの形式が正しくないことを示します。AppUpdateInfo オブジェクトと AppUpdateOptions オブジェクトが null ではなく、正しくフォーマットされていることを確認してください。
  • エラーコード -5, APP_UPDATE_UNAVAILABLE は、適用可能なアップデートがないことを示します。対象のバージョンに同じパッケージ名アプリケーション ID署名鍵があることを確認します。アップデートが利用できる場合は、アプリのキャッシュをクリアし、もう一度 AppUpdateManager_requestAppUpdateInfo() を呼び出して AppUpdateInfo を更新します。
  • エラーコード -6, APP_UPDATE_NOT_ALLOWED は、AppUpdateOption オブジェクトによって指定されたアップデート タイプが許可されていないことを示します。アップデート フローを開始する前に、AppUpdateInfo オブジェクトでアップデート タイプが許可されているかどうかを確認してください。

次のステップ

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