デバイス階層ターゲティング

デバイス階層ターゲティングとは

デバイス階層ターゲティング(DTT)を使用すると、デバイスのハードウェアに基づいて、同じアセットの異なるバージョン(解像度など)をデバイスに配信できます。たとえば、ローエンド デバイスには低解像度のアセットを配信してパフォーマンスを向上させ、ハイエンド デバイスには高解像度のアセットを配信してグラフィックの品質を向上させることができます。いずれの場合も必要なアセットのみをユーザーのデバイスに配信するため、ゲーム全体のサイズが大きくなることはありません。これは、Play Asset Delivery のアセットパックのコンセプトに基づいています。以下で説明するように、階層の条件を(現時点では RAM、特定のデバイスモデル、または使用可能なシステム機能に基づいて)定義し、最大 5 つの階層を使用できます。

Play Asset Delivery と同様に、デバイス階層ターゲティングは API 16(Jelly Bean 4.1)以降をサポートしていますが、API 19(KitKat 4.4.X)以前の場合、デバイスビルドにかかわらずデフォルトの階層が配信されます。

デベロッパーが実施する手順

DTT を既存のゲームに統合するには、概要として次の手順が必要になります。

  1. デバイス階層ターゲティングを(さらには Play Asset Delivery を)ゲームに統合します。
    • Play Asset Delivery をゲームに統合します(まだ統合していない場合)。
    • アセットをアセットパックに分割します。
    • Play にアップロードする最終的な Android App Bundle アーティファクト用に、コードとアセットをまとめてパッケージ化します。
  2. デバイス階層ターゲティング設定を作成し、ユーザーのデバイスにアセットを配信する方法を Play が認識できるようにします。
    • Google Play Developer API を設定します(まだ完了していない場合)。この API を使用して DTT 設定を Play に送信します。
    • 手順に沿って DTT 設定を作成します。
  3. AAB を Play にアップロードし、すべてが正しく設定されているかどうかをテストします。

最初のセクションで、使用するビルドシステムに応じてガイドにフォークが示されます。選択するシステムは、使用しているエンジンと既存の設定によって異なります。

  • Gradle(Java とネイティブのゲームに推奨): Gradle を使用してビルドしたゲームの場合、次の手順に沿って、DTT をサポートする AAB をビルドするように、ビルドシステムを設定します。
    • ゲームを Gradle にエクスポートし、Gradle でビルドを完了する場合、以下の手順を行うことをおすすめします(例: Gradle にエクスポートされた Unity ゲーム)
  • Unity プラグイン: Unity プロジェクトにインポートする Unity パッケージが提供されます。これにより、DTT をサポートする AAB を設定およびビルドできます。

アプリ内でデバイス階層ターゲティングを設定する

Play Asset Delivery をゲームに統合する(まだ完了していない場合)

Play Asset Delivery(PAD)を使用すると、インストール時または実行時にゲームのアセットを動的に配信できます。詳しくは、Play Asset Delivery をご覧ください。デバイス階層ターゲティングにより、Play はデバイスのさまざまな階層に対して指定したデバイス階層設定に基づいて、アセットパックを配信します。以下のガイダンスに沿って PAD をゲームに統合し(つまり、ゲームでのアセットパックの作成、取得の実装を行い)、プロジェクト コードを変更してデバイス階層ターゲティングを有効にすることをおすすめします。

Gradle

Gradle でビルドされたゲームの場合は、次の手順で Gradle を使用してアセットパックをビルドしてから、手順に沿って次のアセットパックの取得をゲームに統合します。

Unity

Unity でビルドされたゲームの場合は、こちらの手順で概説されているように、AssetPackConfig クラスを使用してアセットパックを設定します。

デバイス階層固有のディレクトリを作成する

Gradle を使用する場合

後で定義する N 層(最大 5 層)にアセットを分割します。前のステップで作成した既存のアセット バンドル ディレクトリを取得し、適切なフォルダ(下記の説明を参照)に #tier_0、#tier_1、#tier_2 などの接尾辞を付けて、DTT ディレクトリを作成します。ゲームでアセットパックを使用する場合、接尾辞でフォルダを扱う必要はありません(接尾辞はビルドプロセス中に自動的に削除されます)。

前のステップを実施すると、次のようになります。

...
.../level1/src/main/assets/character-textures#tier_2/
.../level1/src/main/assets/character-textures#tier_1/
.../level1/src/main/assets/character-textures#tier_0/
...

フォルダの下のファイルにアクセスする場合、接尾辞なしで同じパスを使用できます(この例では、接尾辞なしで level1/assets/character-textures/ として参照します)。

Unity を使用している場合

DTT を使用するアセットパックを追加するには、次の AssetPackConfig メソッドを使用します。

/// Package the specified raw assets in the specified folders,
/// keyed by DeviceTier, in an AssetPack with the specified delivery mode.
public void AddAssetsFolders(
    string assetPackName,
    IDictionary<DeviceTier, string> deviceTierToAssetPackDirectoryPath,
    AssetPackDeliveryMode deliveryMode)

/// Package the specified AssetBundle files, which vary only by DeviceTier,
/// in an AssetPack with the specified delivery mode.
public void AddAssetBundles(
    IDictionary<DeviceTier, string> deviceTierToAssetBundleFilePath,
    AssetPackDeliveryMode deliveryMode)

たとえば、キャラクターに 3 つの AssetBundles を異なる詳細の程度で設定しているとします。

これらの AssetBundles を対応するデバイス階層にマッピングするには、次のスニペットを使用します。

var assetPackConfig = new AssetPackConfig();
var tiers = new Dictionary<DeviceTier, string>
{
    {0, "Assets/LowPoly/Character"},
    {1, "Assets/Mid/Character"},
    {2, "Assets/Detailed/Character"}
};
assetPackConfig.AddAssetBundles(tiers, AssetPackDeliveryMode.OnDemand);

Android App Bundle をビルドする

Gradle

プロジェクトの build.gradle ファイルで、次の(またはそれ以上の)バージョンの Android Gradle プラグインbundletool を持つように依存関係を設定します。

buildscript {
  dependencies {
    classpath 'com.android.tools.build:gradle:4.2.0'
    classpath "com.android.tools.build:bundletool:1.7.1"
    ...
  }
  ...
}

また、Gradle のバージョンを 6.7.1 以上にアップデートする必要もあります。これは、プロジェクト内の gradle/wrapper/gradle-wrapper.properties でアップデートできます。

distributionUrl=https://services.gradle.org/distributions/gradle-6.7.1-all.zip

最後に、Play Asset Delivery Library を使用する必要があります。モノリシックな Play Core Library を使用している場合は、1.8.3 以上にアップデートします。可能であれば、Play Asset Delivery Library に切り替えて、最新バージョンにアップデートすることをおすすめします。

dependencies {
  implementation 'com.google.android.play:asset-delivery:2.0.1'
  ...
}

メインアプリ モジュールの build.gradle ファイルで、DTT 分割を有効にします。

android {
  bundle {
    deviceTier {
      enableSplit true
    }
    ...
  }
  ...
}

最後に、Android App Bundle(AAB)をビルドします。

bundletool

bundletool を使用してバンドルを作成します。また、AAB をカスタマイズするステップで、BundleConfig.pb ファイルに以下を追加します。

{
  ...
  "optimizations": {
    "splitsConfig": {
      "splitDimension": [
      ...
      {
        "value": "DEVICE_TIER",
        "negate": false,
        "suffixStripping": {
          "enabled": true,
        }
      }],
    }
  }
}

Unity

DTT パックを含めるように AssetPackConfig を設定したら、その設定を次のいずれかのメソッドに渡して AAB をビルドできます。

// Configures the build system to use the newly created assetPackConfig when
// calling Google > Build and Run or Google > Build Android App
Bundle.AssetPackConfigSerializer.SaveConfig(assetPackConfig);
// Alternatively, use BundleTool.BuildBundle to build an App Bundle from script
BuildBundle(new buildPlayerOptions(), assetPackConfig)

ローカルテスト

先に進む前に、App Bundle をローカルでテストして、すべてが正しく設定されているか確認することをおすすめします。bundletool(1.8.0 以上)を使用して、ローカルでアプリのビルドとテストを行い、正しいデバイス階層を明示的に指定します。最初に build-apks を使用して一連の .apks ファイルを生成してから、install-apks を使用して接続されたデバイスにアプリをデプロイします。 インストールする階層をデバイス階層フラグで指定することもできます。ローカルテストの方法について詳しくは、こちらをご覧ください(このページは DTT については更新されていないため、device-tier フラグに関する情報は記載されていません)。

bundletool build-apks --bundle=/path/to/app.aab --output=/path/to/app.apks --local-testing
bundletool install-apks --apks=/path/to/app.apks --device-tier=1

別の方法: extract-apks を使用して、特定のデバイス用に APK のセットを抽出することもできます。ただし、このデバイスの階層を指定した状態で get-device-spec を使用した場合、--local-testing フラグと連携して動作しないため、fast-follow アセットパックや on-demand アセットパックはテストできません。

bundletool get-device-spec --output=/path/to/device-spec.json --device-tier=1
bundletool extract-apks --apks=/path/to/existing_APK_set.apks --output-dir=/path/to/device_specific_APK_set.apks --device-spec=/path/to/device-spec.json

Unity

[Google] -> [Build and Run] メニュー オプションを使用すると、--local-testing フラグを有効にしてゲームをビルドおよび実行できます。ただし、install-apks コマンドに渡されるデバイス階層を指定することはできません。

0 以外のデバイス階層を指定する場合は、次のようにします。

  1. [Google] -> [Build Android App Bundle] メニュー オプションを使用して AAB をビルドします。
  2. 前のセクションの手順に沿って、ビルドした AAB で bundletoolbuild-apksinstall-apks を実行します。

Google Play Developer API でデバイス階層設定を作成する

Google Play Developer API のスタートガイド(まだ完了していない場合)

デバイス階層ターゲティングの設定(例: 各階層の要件の定義)を行うには、Android Publisher API を使用して設定を Google Play にアップロードする必要があります。API の詳細については上記のリンクをご覧ください。使用を開始するための手順がいくつか用意されています。

  1. 必要に応じて、API プロジェクトを作成して Google Play Console にリンクします
  2. API アクセス クライアントを設定します

API リファレンスはこちらで確認できます。後で API 経由でビルドをアップロードする場合は、Edits メソッドを使用します。 また、API を使用する前に、こちらのページを確認することをおすすめします。

Device Tier Configuration API を使用する

デバイス階層設定を作成するには、次の API 呼び出しを使用します。

デバイス階層設定の作成

HTTP リクエスト POST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs
パスパラメータ なし
リクエストの本文 デバイス階層設定
レスポンスの本文 デバイス階層設定
デバイス階層設定オブジェクト

デバイス階層の定義は、次の 2 つの手順で構成されます。

  1. 一連のデバイス グループを定義します。
  2. デバイス グループにレベルを割り当てて、デバイス階層セットを定義します。

デバイス グループとは、設定で定義したセレクタに一致するデバイスのセットです。

セレクタでは、デバイスの RAM とデバイスモデルに関する要件を定義できます。

グループは選択した名前で識別されます。また、重複しても構いません。

次に、グループをランク付けして、デバイス階層セットを定義します。各デバイス階層は、それぞれのレベルとデバイス グループによって定義されます。

複数の階層に一致するデバイスには、最も一致する階層のコンテンツが配信されます。

  {
    device_groups: [
      {
        name: string,
        device_selectors: [
          {
            device_ram: {
              min_bytes: integer
              max_bytes: integer
            },
            included_device_ids: [
              {
                build_brand: string,
                build_device: string
              }
            ],
            excluded_device_ids: [
              {
                build_brand: string,
                build_device: string
              }
            ],
            required_system_features: [
              {
                name: string
              }
            ],
            forbidden_system_features: [
              {
                name: string
              }
            ]
          }
        ]
      }
    ],
    device_tier_set: {
      device_tiers: [
        {
          level: int,
          device_group_names: [string]
        }
      ]
    }
  }

フィールド:

  • device_confid_id(整数): このデバイス階層設定に対応する ID。
  • device_groups(オブジェクト): グループの定義。

    • name(文字列): デバイス グループの名前(自分で定義した文字列 ID)。
    • device_selectors(オブジェクト): このグループに属するデバイスの要件。
    • device_ram(オブジェクト): デバイスの RAM の要件。
      • min_bytes(整数、包含的): 必要な最小 RAM(バイト単位)。
      • max_bytes(整数、排他的): 必要な最大 RAM(バイト単位)。
    • included_device_ids(オブジェクト): このセレクタに含めるデバイスモデル(グループあたり最大 10,000 個の device_ids)。デバイスがセレクタに一致するには、このリストに含まれている必要があります。これはセレクタ全体に一致するための必要条件であり、十分条件ではありません(セレクタ内の要件を組み合わせる方法については上記の注をご覧ください)。
      • build_brand(文字列): デバイスのメーカー。
      • build_device(文字列): デバイスのモデルコード。
    • excluded_device_ids(オブジェクト): このセレクタで除外するデバイスモデル(グループあたり最大 10,000 個の device_ids)。このリストにあるデバイスは、セレクタ内の他のすべての要件に一致したとしても、セレクタに一致しません。
      • build_brand(文字列): デバイスのメーカー。
      • build_device(文字列): デバイスのモデルコード。
    • required_system_features(オブジェクト): デバイスがこのセレクタに含まれるために搭載している必要がある機能(グループあたり最大 100 個の機能)。 デバイスがセレクタに一致するには、このリストにあるすべてのシステム機能を搭載している必要があります。これはセレクタ全体に一致するための必要条件であり、十分条件ではありません(セレクタ内の要件を組み合わせる方法については上記の注をご覧ください)。

      システム機能リファレンス

      • name(文字列): システム機能
    • forbidden_system_features(オブジェクト): このセレクタに含まれるために、デバイスが搭載してはいけない機能(グループあたり最大 100 個の機能)。デバイスがこのリスト内にあるシステム機能を搭載している場合、セレクタの他のすべての要件に一致しても、セレクタに一致しません。

      システム機能リファレンス

      • name(文字列): システム機能
  • device_tiers(オブジェクト): 階層の定義

    • level(int): 階層のレベル
    • group_name(文字列配列): この階層に属するデバイス グループの名前

デバイスのメーカーとモデルコードの正しい形式を見つけるには、Google Play Console のデバイス カタログを使用して、次のいずれかを行います。

  • 下記の例のように、デバイス カタログを使用して個々のデバイスを調べ、メーカーとモデルコードを見つけます(Google Pixel 4a の場合、メーカーは「Google」、モデルコードは「sunfish」となります)。

    デバイス カタログの Pixel 4a のページ

    デバイス カタログの Pixel 4a のページ

  • サポートされているデバイスの CSV をダウンロードし、build_brandbuild_device にそれぞれメーカーとモデルコードを使用します。

3 つの階層を持つ設定の例を以下に示します。階層 2 は、デバイス グループ high(7 GB を超えるすべてのデバイスと Pixel 4 が含まれる)を使用し、階層 1 はデバイス グループ medium(4~7 GB のすべてのデバイスが含まれる)を使用します。階層 0 はキャッチオール グループとして暗黙的に定義されています。

{
  device_groups: [
    {
      name: 'high',
      device_selectors: [
        {
          device_ram: {
            min_bytes: 7516192768
          },
        },
        {
          included_device_ids: [
            {
              build_brand: 'google',
              build_device: 'flame'
            }
          ],
        }
      ]
    },
    {
      name: 'medium',
      device_selectors: [
        {
          device_ram: {
            min_bytes: 4294967296,
            max_bytes: 7516192768
          },
        }
      ]
    }
  ],
  device_tier_set: {
    device_tiers: [
      {
        level: 1,
        device_group_names: [
          'medium'
        ]
      },
      {
        level: 2,
        device_group_names: [
          'high'
        ]
      }
    ]
  }
}

Google Play にアップロードする前に、次の手順に沿ってデバイス ターゲティング構成を検証してください。

デバイス階層設定を ID で取得する

次の呼び出しを使用して、ID で特定のデバイス階層設定を取得できます。

HTTP リクエスト GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs/{deviceTierConfigId}
パスパラメータ なし
リクエストの本文 なし
レスポンスの本文 デバイス階層設定

デバイス階層設定のリストを取得する

次の呼び出しを行うと、最新のデバイス階層設定を 10 個取得できます(または、page_token クエリ パラメータを使用して 10 個のセットを適切に指定します)。

HTTP リクエスト GET https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs
パスパラメータ なし
クエリ パラメータ page_token(省略可)- 10 個の DTC からなる特定のグループを指定するために使用されます。これは、10 個以上の DTC を作成している場合に、最近作成した 10 個よりも前に作成した DTC を確認したいときに便利です。
リクエストの本文 なし
レスポンスの本文 デバイス階層設定のリスト

page_token

デバイス ターゲティング構成を検証する

bundletool には、Google Play にアップロードする前に、デバイス ターゲティング構成が意図通りに動作することを検証するためのコマンドが 2 つあります。

bundletool print-device-targeting-config により、JSON ファイルの構文が正しいことを検証し、デバイス グループと階層をわかりやすい形式で可視化できます。

bundletool print-device-targeting-config --config=mydtc.json

bundletool evaluate-device-targeting-config により、特定のデバイスにどのグループと階層が一致するかを評価できます。ターゲット デバイスをワークステーションに接続し、--connected-device フラグを使用します。もしくは、デバイス プロパティを含む JSON ファイルを手動でコンパイルし、--device-properties フラグを使用して指定します。

bundletool evaluate-device-targeting-config --config=mydtc.json --connected-device
bundletool evaluate-device-targeting-config --config=mydtc.json --device-properties=deviceproperties.json

デバイス プロパティ ファイルは、DeviceProperties protobuf 構造に沿った JSON ファイルでなければなりません。次に例を示します。

{
  "ram": 2057072640,
  "device_id": {
    "build_brand":"google",
    "build_device":"redfin"
  },
  "system_features": [
    {
      "name":"android.hardware.bluetooth"
    },
    {
      "name":"android.hardware.camera"
    }
  ]
}

Android App Bundle を Google Play にアップロードする

API 経由

Google Play Developer API を使用して、Android App Bundle を Google Play にアップロードしたり、特定のデバイス階層ターゲティング設定をビルドにリンクしたりできます。

Edits メソッドの全般的な概要と、Google Play Console のさまざまなトラックへのリリースに関する詳細な例をご覧ください(最後のリンクでは、ページ内にリストされている APK 対応 API の代わりに、AAB 対応 API を使用する必要があります)。ビルドのデバイス階層設定を指定するには、edits.bundle.upload メソッドを呼び出す際に、次のように設定 ID を deviceTierConfigId クエリ パラメータに追加します。

https://androidpublisher.googleapis.com/upload/androidpublisher/v3/applications/{packageName}/edits/{editId}/bundles?deviceTierConfigId="{deviceTierConfigId}

Google Play Console 経由

こちらの手順に沿って Android App Bundle をアップロードします。最新の DTC 設定が App Bundle に適用されます。

(正しいビルドを選択した状態で)[App Bundle Explorer]> [Delivery] に移動し、各アセットパックをクリックすると、バンドルが正しくビルドされたことを確認できます。作成した N 個の階層が表示されるはずです。この例では、アセットパック main_asset に 0、1、2 の 3 つの階層があることがわかります。

3 層構成のアセットパック

正しい階層が配信されていることを確認する

正しい階層のみがデバイスに配信されるようにするには、次のメソッドを使用します。

adb shell pm path {packageName}

次のような出力が表示されます。

package:{...}/base.apk
package:{...}/split_config.en.apk
package:{...}/split_config.xxhdpi.apk
package:{...}/split_main_asset.apk
package:{...}/split_main_asset.config.tier_2.apk

補足事項

curl によるクイック スタート

以下に、コマンドライン ツール curl を使用した新しいデバイス階層設定の作成と、Edits API を使用した新しい編集の作成、新しい AAB のアップロード(特定のデバイス階層設定への関連付け)、トラックまたはリリース構成の設定、編集のコミット(変更の公開)の例を示します。以下のものの場所を確認してください。

まず、デバイス階層設定を作成し、呼び出しが成功したときに受け取る deviceTierConfigId をメモします。

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPOST -H "Content-Type: application/json" -d "{ device_groups: [ { name: 'high', device_selectors: [ { device_ram: { min_bytes: 7516192768 }, }, { included_device_ids: [ { build_brand: 'google', build_device: 'flame' } ], } ] }, { name: 'medium', device_selectors: [ { device_ram: { min_bytes: 4294967296, max_bytes: 7516192768 }, } ] } ], device_tier_set: { device_tiers: [ { level: 1, device_group_names: [ 'medium' ] }, { level: 2, device_group_names: [ 'high' ] } ] } }" https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/deviceTierConfigs

編集を開始すると、編集用の ID と有効期限が表示されます。次の呼び出し用に ID を保存します。

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPOST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/edits

AAB をアップロードし、クエリ パラメータとしてデバイス階層設定を指定します。呼び出しが成功すると、ビルドのバージョン コード、sha1、sha256 が表示されます。次回の呼び出し用にバージョン コードを保存します。

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" --data-binary @$HOME/{aabFile} -H "Content-Type: application/octet-stream" -XPOST https://androidpublisher.googleapis.com/upload/androidpublisher/v3/applications/{packageName}/edits/{editID}/bundles?deviceTierConfigId="{dttConfigID}"

AAB を目的のトラックに割り当てます(テストには内部テストトラックを使用することをおすすめします。こちらでさまざまなトラックの詳細をご覧いただけます。ここではリリースノートなしで簡単に公開していますが、未公開のリリースとリリースノートを段階的に公開する方法について詳しくは、こちらのページをご覧ください。Publisher API を初めて使用する場合は、すべてが正しく設定されるように、未公開のリリースとして作成してから、Google Play Console でリリースを完了することをおすすめします

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPUT -H "Content-Type: application/json" -d "{ releases: [{status: '{status}'</code>, <code><strong>versionCodes</strong></code>: <code>['{versionCode}']</code> <code><strong>}]}</strong></code>" <code>https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/edits/{editID}/tracks/{track}

変更をコミットします(Play 上の目的のトラックにすべての変更が公開されるため、慎重に行ってください)。

curl -H "$(oauth2l header --json $HOME/{apiKey} androidpublisher)" -XPOST https://androidpublisher.googleapis.com/androidpublisher/v3/applications/{packageName}/edits/{editID}:commit