Dynamic Delivery について

Google Play の Dynamic Delivery と呼ばれるアプリ配信モデルでは、Android App Bundle を使用して、個々のユーザーのデバイス設定に合わせて最適化した APK を生成、配信します。それにより、各ユーザーは、アプリの実行に必要なコードとリソースのみダウンロードすることができます。デベロッパー側ではさまざまなデバイスをサポートするために複数の APK をビルド、署名、管理する必要がなくなり、ユーザー側ではサイズが削減され、最適化されたファイルをダウンロードできます。

Dynamic Delivery を使用して最適化された分割 APK を配信できる App Bundle をビルドするのは、ほとんどのアプリ プロジェクトでそれほど難しいことではありません。たとえば、確立された手法に沿ってすでにアプリのコードとリソースを構成している場合、Android Studio またはコマンドラインを使用して、署名済みの Android App Bundle をビルドし、Google Play にアップロードするだけです。そして、Dynamic Delivery が自動化のメリットとなります。

アプリの特定の機能を条件付きで配信したりオンデマンドでダウンロードしたりできるようにする設定など、Dynamic Delivery の高度な機能をサポートするには、機能の配信をカスタマイズする方法についての説明をご覧ください。

Dynamic Delivery と分割 APK

Dynamic Delivery の基本的なコンポーネントは、Android 5.0(API レベル 21)以上で利用できる分割 APK のメカニズムです。分割 APK は標準の APK によく似ていて、コンパイルされた DEX バイトコード、リソース、Android マニフェストが含まれます。異なるのは、Android プラットフォームでインストールされた複数の分割 APK を単一のアプリとして扱えることです。つまり、共通のコードとリソースにアクセスできる複数の分割 APK をインストールして、デバイス上ではインストールされた 1 つのアプリとして表示することができます。

分割 APK のメリットは、モノリシック APK を分割できることです。アプリがサポートするすべての機能やデバイスの設定用のコードとリソースを含む一体構造のアプリを、それより小さい個別のパッケージに分割して、ユーザーのデバイスの必要に応じてインストールすることができます。

たとえば、ある分割 APK に少数のユーザーだけが必要とする追加機能のコードとリソースを含めたり、別の分割 APK には特定の言語や画面密度に専用のリソースを含めたりすることが考えられます。こうした分割 APK はそれぞれ、ユーザーがリクエストしたとき、またはデバイスが必要としたときにダウンロード、インストールされます。

以下、さまざまなタイプの APK について説明します。これらをまとめてデバイスにインストールすると、アプリのフル機能が形成されます。こうした APK をサポートするアプリ プロジェクトの設定方法については、このページの後半で説明します。

  • ベース APK: この APK は、他のすべての分割 APK からアクセスできるコードとリソースを備え、アプリの基本機能を提供します。ユーザーがアプリのダウンロードをリクエストすると、この APK が最初にダウンロード、インストールされます。ベース APK のマニフェストにのみ、アプリのサービス、コンテンツ プロバイダ、権限、プラットフォームのバージョン要件、システムの機能への依存性が完全に記述されているからです。Google Play がプロジェクトのアプリ モジュール(またはベース モジュール)からアプリのベース APK を生成します。アプリの初回ダウンロード サイズを削減したい場合、このモジュール内のコードとリソースはすべて、アプリのベース APK に含まれていることに注意してください。
  • 設定 APK: これらの各 APK には、特定の画面密度、CPU アーキテクチャ、または言語用のネイティブ ライブラリとリソースが含まれます。ユーザーがアプリをダウンロードすると、そのデバイスを対象とする設定 APK だけがダウンロード、インストールされます。各設定 APK はベース APK または動的機能 APK のどちらかの依存関係となります。そのため、そのどちらかの APK にコードとリソースを提供する設定 APK がその APK とともにダウンロード、インストールされます。ベース モジュールや動的機能モジュールとは異なり、設定 APK 用には個別のモジュールは作成しません。標準的な方法でベース モジュールと動的機能モジュールに設定固有の代替リソースを構成する場合、Google Play が自動的に設定 APK を生成してくれます
  • 動的機能 APK: これらの各 APK には、動的機能モジュールを使用してモジュール化したアプリの各機能に対するコードとリソースが含まれます。Dynamic Delivery を使用すると、その機能をデバイスにいつどのようにダウンロードするかをカスタマイズできます。たとえば、Play コアライブラリを使用すると、ベース APK をデバイスにインストールした後、オンデマンドで動的 APK をインストールして、ユーザーに追加の機能を提供することができます。たとえばあるチャットアプリで、写真を撮って送信する機能を、ユーザーがリクエストする場合にのみ、ダウンロードしてインストールすることを考えます。動的機能はインストール時には利用できない可能性もあるため、共通のコードとリソースはベース APK に含める必要があります。動的機能が利用できるのは、インストール時に利用できるベース APK のコードとリソースのみであることを前提にする必要があります。アプリの動的機能 APK は、プロジェクトの動的機能モジュールから Google Play によって生成されます。

動的機能モジュールが 3 つあり、複数のデバイス設定をサポートしているアプリについて考えます。下記の図 1 に、このアプリのさまざまな APK の依存関係ツリーを示します。ベース APK がツリーのルートを形成し、その他の APK はすべてベース APK に依存します(これらの APK のモジュールが Android App Bundle でどのように表されるかに興味があれば、Android App Bundle 形式についての記事をご覧ください)。

ベース APK はツリーのルートを形成し、動的機能 APK はベース APK に依存します。依存関係ツリーのリーフノードを形成する設定 APK には、ベース APK とそれぞれの動的機能 APK のデバイス設定に応じたコードとリソースが含まれます。

図 1. 分割 APK を使用して配信されるアプリの依存関係ツリー

これらの APK を自分でビルドする必要はありません。Android Studio でビルドした署名済みの 1 つの App Bundle から、Google Play が APK をビルドしてくれます。App Bundle 形式とそのビルド方法について詳しくは、Android App Bundle のビルド、デプロイ、アップロードに関する記事をご覧ください。

Android 4.4(API レベル 19)以下を稼働するデバイス

Android 4.4(API レベル 19)以下を稼働するデバイスは、分割 APK のダウンロードとインストールに対応していないので、Google Play ではそのデバイスに単一の APK を代わりに配信します。これは、「マルチ APK」と呼ばれ、デバイスの設定に合わせて最適化されています。このマルチ APK がそのアプリのフル機能を表しますが、他の画面密度や CPU アーキテクチャ用のコードとリソースのような不要なものは含まれません。

ただし、マルチ APK には、アプリがサポートするすべての言語のリソースが含まれます。それによって、たとえばユーザーがアプリの使用言語の設定を変更しても、別のマルチ APK をダウンロードする必要はありません。

マルチ APK には動的機能モジュールを後でオンデマンドでダウンロードする機能はありません。この APK に動的機能を含めるには、動的機能モジュールの作成時に、オンデマンドを無効にするか、融合を有効にする必要があります。

Dynamic Delivery を使用すると、アプリがサポートするデバイス設定ごとに APK のビルド、署名、アップロード、管理を行う必要がなくなります。アプリ全体で 1 つの App Bundle をビルドし、アップロードするだけで、後は Google Play に任せることができます。したがって、Android 4.4 以下を稼働するデバイスをサポートする計画があってもなくても、Dynamic Delivery がデベロッパーとユーザーの両方にとって、柔軟な配信メカニズムを提供します。

アプリをモジュール化する

アプリのモジュール化とは、アプリ プロジェクトの論理コンポーネントを個別のモジュールに分割するプロセスのことです。

アプリの各機能を個別のコンポーネントに再編成するには、綿密な検討と時間をかける必要があります。それでもモジュール化によって、プロジェクトには以下の利点がもたらされます。

  • 並行して開発: アプリの論理コンポーネントを複数のモジュールに分割すると、各モジュールを組織内の異なるチームまたは個人が所有して担当し、他のチームとの結合時の競合や障害を減らすようにすることができます。さらに、アプリのさまざまな部分で使用されるロジックがある場合、ライブラリ モジュールを使用して、コードの再利用やカプセル化を促すことができます。
  • ビルド時間の改善: Gradle を使用する Android Studio ビルドシステムなどのビルドシステムは、複数のモジュールで構成されるプロジェクト用に最適化されています。たとえば、Gradle のプロジェクトの並列実行による最適化を、マルチコア プロセッサが搭載されたワークステーションで有効にする場合、ビルドシステムは複数のモジュールを並行してビルドして、ビルドの所要時間を大幅に削減することができます。プロジェクトのモジュール化が進むほど、ビルドのパフォーマンスが大幅に向上します。
  • 機能の配信のカスタマイズ: アプリの機能を動的機能モジュールとしてモジュール化することは、Dynamic Delivery のカスタム配信方法(オンデマンド配信、条件付き配信、Instant 配信など)を活用するための要件です。オンデマンドの動的機能を作成するには、さらに労力をかけ、アプリで可能なリファクタリングを進める必要があります。ですから、どのアプリの機能を動的機能にモジュール化すればカスタム配信方法のメリットが最大になるかを、慎重に検討してください。

アプリの機能ごとにプロジェクトをモジュール化するには、時間をかけて、適切な方法を検討する必要があります。アプリのモジュール化を始めると決断したら、まず、モジュール式機能をサポートするのに必要なプロパティを指定して、ベース モジュールを設定する必要があります。その後で、インストール時配信用に動的機能モジュールを設定することで、アプリの現在の動作を変えずにアプリの機能を徐々にモジュール化することができます。

動的機能モジュールをカスタム配信に使用する

Dynamic Delivery に固有のメリットをもたらすのは、Android 5.0(API レベル 21)以上を稼働するデバイス上に、アプリのさまざまな機能をいつどのようにダウンロードするかをカスタマイズできる機能です。たとえば、アプリの初回ダウンロード サイズを削減するために、一部の機能を必要に応じてオンデマンドでダウンロードするか、特定の機能(写真の撮影機能、拡張現実のサポート機能など)を持つデバイスにのみダウンロードするように設定できます。

アプリを App Bundle としてアップロードすると、デフォルトで高度に最適化されたダウンロードが可能になりますが、さらに高度なカスタマイズ可能な機能の配信方法では、「動的機能モジュール」を使用するアプリの機能について追加の設定とモジュール化が必要になります。つまり、動的機能モジュールは、必要に応じたダウンロードの設定が可能なモジュール式機能を作成するための構成要素を提供します。

オンライン ショップでユーザーが商品を売買できるようにするアプリについて考えます。アプリの以下の機能は、それぞれ個別の動的機能モジュールに無理なくモジュール化できます。

  • アカウントのログインと作成
  • ショップのブラウジング
  • 販売する商品の配置
  • 支払いの処理

動的機能モジュールがサポートするさまざまな配信方法と、その方法を使用して、ショップのサンプルアプリの初回ダウンロード サイズの最適化を行う方法を、下記の表に示します。

配信方法 動作 事例 最初の手順
インストール時配信 上記の配信方法のいずれも設定しない動的機能モジュールが、デフォルトでアプリのインストール時にダウンロードされます。これは、高度な配信方法を徐々に採用できることを意味するので重要な動作となります。たとえば、Play のコアライブラリを使ったオンデマンド ダウンロードを完全に実装した後でのみ、アプリの機能のモジュール化を活用して、オンデマンド配信を有効にすることができます。

さらに、アプリは後で機能のアンインストールをリクエストすることができます。それにより、アプリのインストール時に必要だった特定の機能がその後で不要になる場合、デバイスからその機能を削除するようリクエストすることで、インストール サイズを削減できます。

ショップでの商品の売買方法に関するインタラクティブ ガイドのような特定のトレーニング アクティビティがアプリにある場合、アプリのインストール時にデフォルトでその機能を含めることができます。

一方、アプリのインストール サイズを削減するために、ユーザーがトレーニングを完了した後で、アプリは機能の削除をリクエストできます。

高度な配信方法を設定しない動的機能モジュールを使って、アプリをモジュール化します。

ユーザーにとって不要になった特定の動的機能モジュールを削除することで、アプリのインストール サイズを削減する方法については、インストールしたモジュールを管理する場合についての説明をご覧ください。

オンデマンド配信 必要に応じて動的機能モジュールをリクエスト、ダウンロードすることをアプリに許可します。 ショップアプリを使用するユーザーのうち、販売する商品を投稿するのは 20% しかいない場合、大多数のユーザーにおける初回ダウンロード サイズを削減するおすすめの戦略としては、写真の撮影、商品の説明の指定、および販売する商品の配置の各機能をオンデマンド ダウンロードとして利用可能にすることです。つまり、アプリの販売機能に対する動的機能モジュールは、ユーザーが販売する商品をショップに配置することに関心を示したときにのみ、ダウンロードされるように設定することができます。

さらに、一定期間ユーザーが商品を販売しなかった場合、アプリは販売機能のアンインストールをリクエストすることで、インストール済みのサイズを削減することができます。

動的機能モジュールを作成して、オンデマンド配信を設定します。その後に、アプリは Play のコアライブラリを使って、そのモジュールをオンデマンドでダウンロードするようリクエストできます。
条件付き配信 ハードウェアの機能、言語、地域、最小 API レベルなど、特定のユーザー デバイス要件を指定することで、モジュール化した機能をダウンロードするかどうかを、アプリのインストール時に判断可能にすることができます。 ショップアプリがグローバル ユーザーを対象とする場合、一部の地域や言語でのみよく使用される支払い方法のサポートが必要になることがあります。アプリの初回ダウンロード サイズを削減するために、特定のタイプの支払い方法を処理する動的機能モジュールを個別に作成して、ユーザーのデバイスに、登録されている言語や地域に基づく条件付きでインストールさせることができます。 動的機能モジュールを作成して、条件付き配信を設定します。
Instant 配信 Google Play Instant を使用すると、デバイスに APK をインストールしなくても、ユーザーがアプリを利用できるようになります。インストールする代わりに、ユーザーは Google Play ストアの [今すぐ試す] ボタンか、デベロッパーが作成した URL を使ってアプリを利用できます。このコンテンツの配信形式は、アプリへの関心を簡単に増大させることができます。

Instant 配信により Google Play Instant を活用すると、インストールしなくてもアプリの一部の機能をユーザーがすぐに試せるようになります。

ゲームの最初の数レベルを軽量の動的機能モジュールに含めることを検討します。そのモジュールで Instant を有効にすると、ユーザーはアプリをインストールしなくても、URL リンクまたは [今すぐ試す] ボタンからすぐにゲームを使ってみることができます。 動的機能モジュールを作成し、Instant 配信を設定します。その後、アプリは Play のコアライブラリを使って、オンデマンドでそのモジュールをダウンロードするようリクエストできます。

動的機能モジュールを使用するアプリの機能のモジュール化は最初のステップにすぎません。Google Play Instant をサポートするには、アプリのベース モジュールと Instant を有効にした特定の動的機能のダウンロード サイズが厳しいサイズ要件を満たす必要があります。詳しくは、アプリまたはゲームのサイズを削減して Instant 機能を有効にする場合についての説明をご覧ください。

動的機能モジュールのマニフェスト

Android Studio を使用して新しい動的機能モジュールを作成する際、動的機能として動作するモジュールに必要なほとんどのマニフェスト属性は IDE に含まれています。また、一部の属性はコンパイル時にビルドシステムによって挿入されるので、自分で指定または変更する必要はありません。次の表に、動的機能モジュールの重要なマニフェスト属性を示します。

属性 説明
<manifest
...
これは典型的な <manifest> ブロックです。
xmlns:dist="http://schemas.android.com/apk/distribution" 新しい dist: XML 名前空間を指定します。これについてはさらに下記で説明します。
split="split_name" Android Studio が App Bundle をビルドする際、この属性が自動的に含まれます。そのため、この属性を自分で指定または変更する必要はありません

モジュールの名前を定義します。これは、Play のコアライブラリを使用してオンデマンド モジュールをリクエストする際に、アプリで指定するものです。

Gradle がこの属性の値を判断する方法:

デフォルトでは、Android Studio を使用して新しい動的機能モジュールを作成する際、モジュール名として指定する名前を IDE が使用して、Gradle 設定ファイル内の Gradle サブプロジェクトとしてそのモジュールを特定します。

App Bundle をビルドする際、Gradle はそのサブプロジェクト パスの最後の要素を使って、モジュールのマニフェスト内にこのマニフェスト属性を挿入します。たとえば、新しい動的機能モジュールを MyAppProject/features/ ディレクトリ内に作成して、モジュール名として "dynamic_feature1" を指定した場合、IDE は ':features:dynamic_feature1'settings.gradle ファイル内のサブプロジェクトとして追加します。この App Bundle をビルドすると、Gradle はそのモジュールのマニフェストに <manifest split="dynamic_feature1"> を挿入します。

android:isFeatureSplit="true | false"> Android Studio が App Bundle をビルドする際、この属性が自動的に含まれます。そのため、この属性を手動で指定または変更する必要はありません

このモジュールが動的機能モジュールであることを指定します。ベース モジュールと設定 APK のマニフェストでは、この属性は省略されるか、false に設定されます。

<dist:module この新しい XML 要素は、モジュールを APK としてパッケージ化して配信する方法を決定する属性を定義します。
dist:instant="true | false" モジュールを Google Play Instant を介して Instant 機能として利用できるようにするかどうかを指定します。

アプリに Instant を有効にした動的機能モジュールが含まれる場合、ベース モジュールでも Instant を有効にする必要があります。Android Studio 3.3 以上を使用して、Instant を有効にした動的機能モジュールを作成すると、IDE が Instant を自動的に有効にします。

dist:onDemand="true" を設定している場合は、この XML 要素を true に設定することはできません。その場合でも、Instant を有効にした動的機能を「Instant 機能」として Play のコアライブラリを使用すると、オンデマンドのダウンロードをリクエストすることができます。ユーザーがアプリをダウンロード、インストールする際、デバイスはアプリの Instant を有効にした動的機能を、デフォルトではベース APK とともに、ダウンロード、インストールします。

dist:onDemand="true | false" モジュールをオンデマンドでダウンロード可能とするかどうかを指定します。この属性が true に設定されている場合、そのモジュールはインストール時には利用できませんが、後でアプリがダウンロードをリクエストすることができます。

この属性が false に設定されている場合、ユーザーがアプリを初めてダウンロードしてインストールする際に、そのモジュールも含まれます。

オンデマンドのダウンロードについて詳しくは、Play のコアライブラリを使ってモジュールをダウンロードする場合についての記事をご覧ください。

dist:title="@string/feature_name" モジュールのユーザー向けのタイトルを指定します。たとえば、デバイスがダウンロードの確認を求めるときに、このタイトルが表示されることがあります。

このタイトルの文字列リソースを、ベース モジュールの module_root/src/source_set/res/values/strings.xml ファイルに含める必要があります。

<dist:fusing dist:include="true | false" />
</dist:module>
Android 4.4(API レベル 20)以下を稼働しているデバイスを対象とするマルチ APK 内にそのモジュールを含めるかどうかを指定します。

さらに、bundletool を使って App Bundle から APK を生成する際、このプロパティが true に設定されている動的機能モジュールだけがユニバーサル APK に含まれます。ユニバーサル APK は、アプリがサポートするすべてのデバイス設定用のコードとリソースが含まれるモノリシック APK です。

<application
android:hasCode="true | false">
...
</application>
DEX ファイルが生成されない動的機能モジュールの場合、後で DEX ファイル形式にコンパイルされるようなコードが含まれていないので、以下のように設定する必要があります(設定しない場合は、ランタイム エラーが発生することがあります)。
  1. 動的機能モジュールのマニフェスト内で android:hasCode"false" に設定します。
  2. 以下をベース モジュールのマニフェストに追加します。
    
        <application
          android:hasCode="true"
          tools:replace="android:hasCode">
          ...
        </application>
        

Dynamic Delivery をテストする

Dynamic Delivery のテストは Google Play ストアから行うことをおすすめします。Dynamic Delivery のメリットの多くが、APK の生成、署名、Play ストアへの配信の最適化の保留に依存しているからです。そのため、App Bundle をアップロードして Dynamic Delivery の基本サポートを含める場合でも、カスタム配信方法を設定する場合でも、以下の方法で Dynamic Delivery についてアプリをテストする必要があります。

動的機能についての検討事項

動的機能モジュールが含まれるアプリを製品版トラックに公開する場合、以下の検討事項について考慮してください。

  • Android 5.0(API レベル 21)以上を稼働するデバイスだけが、動的機能のオンデマンドによるダウンロードとインストールに対応しています。Android のそれより前のバージョンで動的機能を利用できるようにするには、動的機能モジュールの作成時に、融合を有効にしてください。
  • 必ず SplitCompat を有効にすることで、ダウンロードされた動的機能モジュールにアプリがすぐにアクセスできます。
  • 動的機能のダウンロード サイズが大きい場合、デバイスに動的機能モジュールをダウンロードする前に、アプリがユーザーの確認をとる必要があります。
  • 動的機能モジュールは android:exportedtrue に設定したアクティビティをマニフェストに指定してはなりません。別のアプリがそのアクティビティを開始しようとしているとき、デバイスがその動的機能モジュールをダウンロード済みだという保証はないからです。さらに、アプリは動的機能のコードとリソースにアクセスしようとする前に、その機能がダウンロードされていることを確認する必要があります。詳しくは、インストールしたモジュールの管理についての説明をご覧ください。
  • Dynamic Delivery では App Bundle を使用してアプリを公開する必要があるので、App Bundle の既知の問題について必ずご確認ください。

参考情報

Dynamic Delivery のサポートについて詳しくは、以下のリソースをご覧ください。

サンプル

コードラボ

  • 初めての Android App Bundle: Android App Bundle の基本原則を探り、Android Studio を使って独自のビルドをすぐに始める方法を示すコードラボです。このコードラボは、bundletool を使用して App Bundle をテストする方法についても検討します。
  • オンデマンド モジュール: オンデマンドで動的機能をダウンロード、インストールするアプリの作成方法について紹介します。

ブログ投稿

動画