結論から言うと、Google Playは解釈可能なcodeのLive Updateを許可しています。 Play Storeの再審査なしで、Androidアプリに新しいJavaScript、HTML、CSSを配信できます。ただし、dexやJARなどのネイティブなcodeを .so files.
この点に関してはGoogleの方がAppleよりも明確です。WebView内でのJavaScriptに関する例外規定は、ポリシーに直接明記されています。本ページではその引用、境界線、およびGoogleによる適用方法について解説します。
これは法的助言ではありません。現在のポリシーの解釈と、数千ものアプリが本番環境でどのように運用しているかに基づいています。
Google Playのポリシーの実際の内容
規定は以下の Device and Network Abuse policy に記載されています:
Google Playを通じて配信されるアプリは、Google Playのアップデートメカニズム以外の方法で、自身を修正、置換、またはアップデートしてはなりません。同様に、アプリはGoogle Play以外のソースから実行可能な code (dex、JAR、.soファイルなど) をダウンロードしてはなりません。この制限は、仮想マシンまたはインタプリタ内で実行され、それらがAndroid APIへの間接的なアクセスを提供する(WebViewやブラウザ内のJavaScriptなど)code には適用されません。
そして、その直後にこう続きます:
実行時にロードされる(例:アプリにパッケージ化されていない)解釈可能な言語(JavaScript、Python、Luaなど)を持つアプリやサードパーティ製の code (SDKなど) は、Google Playポリシーに違反する可能性のある動作を許可してはなりません。
つまり、ルールは2つあります:
- ネイティブな code はGoogle Playからのみ提供すること。 ダウンロードしたdex、JAR、またはネイティブライブラリは禁止。
- 解釈可能な code はどこから取得しても構いませんが、 その動作は常にすべてのPlayポリシーに従う必要があります。
Capacitor アプリのウェブレイヤーは、Googleが例示している通り、Android WebView上で動作するJavaScript、HTML、CSSです。これは免除対象に含まれます。
境界線はどこにあるのか
| live update で許可されるケース | live update で許可されないケース |
|---|---|
| JavaScript、HTML、CSSにおけるバグ修正 | dex、JAR、APK、または .so ファイルのダウンロード |
| 既存のウェブスタック内でのUI変更、文言変更、新規画面の追加 | Google Playのアップデートメカニズムを介さないアプリの入れ替え |
| ウェブ code のA/Bテストや段階的なロールアウト | Playポリシーに違反する code の配信(欺瞞的な動作、マルウェア、ポリシー違反コンテンツ) |
| 画像、翻訳、設定の更新 | ストアの記載内容と異なるアプリへの変貌 |
| 不具合のあるリリースのロールバック | Androidの権限やセキュリティの回避 |
Capgo は左側のカラムのみを配信します。新しい Capacitor プラグインや、新しい権限、 AndroidManifest.xmlまたは Gradle の依存関係など、ネイティブに関する変更は、引き続き Google Play 経由の新しいリリースが必要です。Capgo の バージョンターゲット機能は、 新しいネイティブ code を必要とする bundle を古いバイナリから分離します。
Google による強制措置の仕組み
Google は、ダウンロードされた実行可能な code や、インストール後に変化する挙動がないかアプリをスキャンします。自動チェックでは、APK 外部からの dex やネイティブライブラリのロードを監視しますが、WebView 内の JavaScript は検知対象になりません。
真のリスクは2番目のルールにあります。live update によってアプリが Play のポリシーで禁止されている動作を行う場合、code がどのように配信されたかにかかわらず違反となります。また、レビュー後に機能が変化するアプリには、欺瞞的な動作に関するポリシーも適用されます。
実務上のポイント:
- 公開済みのアプリの修正や改善には、Live Update を活用してください。
- Play Storeの掲載情報とデータ セーフティ フォームの内容を一致させましょう。
- ネイティブの変更や大規模なリリースはGoogle Play経由で配信し、 段階的なリリース を使えば、徐々に展開できます。
Androidで対応できるスタックは?
AndroidでOTAアップデートを配信できるかどうかは、1つの問いにかかっています。アプリのロジックは実行時に解釈されるか?JavaScriptなどのインタプリタ型 code なら「はい」。ダウンロードしたdex、JAR、ネイティブ .so ファイルは「いいえ」です。FlutterのようなAOTコンパイル型フレームワークは、VMまたはインタプリタ経由でのみ対象となります。
スタック別 Android live update 互換性
| スタック | Androidで code が動く仕組み | ライブアップデートは可能? | ツール |
|---|---|---|---|
| Capacitor | Android WebView内のJavaScript, HTML, CSS | はい | Capgo |
| Ionic (Capacitor 上) | Capacitor と同様 | はい | Capgo |
| Cordova | Android WebView内のJavaScript | はい | Capacitorへの移行後のCapgo, レガシーなCordovaプラグイン |
| React Native / Expo | Hermes上のJavaScript bundle | はい、JavaScriptのみ | Expo Updates、セルフホスト型のCodePush代替案 |
| NativeScript | V8上のJavaScript | はい、JavaScriptのみ | 限定的、主に自作 |
| Flutter | ネイティブライブラリへAOTコンパイルされたDart | VMまたはインタプリタ経由のみ | Shorebird |
| ネイティブのKotlin / Java | ART上のdexバイトコード | ネイティブのcodeは不可、WebView内のJavaScriptは可 | リモート構成、Play Feature Delivery |
| Kotlin / Compose Multiplatform | ART上のdexバイトコード | いいえ | リモート構成、Play Feature Delivery |
| .NET MAUI / Xamarin | .NETランタイムとAPK同梱のネイティブライブラリ | いいえ | リモート構成のみ |
| Unity / Unreal | IL2CPP経由のC#またはコンパイル済みC++ | codeは不可、コンテンツは可 | Asset bundles、Play Asset Delivery、スクリプトコンテンツ (Lua) |
| Web wrapper / TWA | WebViewまたはChromeで読み込まれるWebサイト | 常にライブ | 不要 |
Capacitor、Ionic、Cordova:完全対応
UIとビジネスロジックがAndroid WebView上で動作するJavaScriptである場合、これはGoogleのポリシーが許可しているcodeの正確な例です。live updateはWeb bundleを置き換えますが、APK、ネイティブプラグイン、権限は公開時のものが維持されます。
Capgo は、Webレイヤーのみを変更するため、設計段階からポリシーに準拠しています。新しいネイティブプラグインや、新しい権限の追加、 AndroidManifest.xml Gradleの依存関係の変更には、引き続き Google Play でのリリースが必要です。
React Native と Expo: JavaScript は OK、ネイティブモジュールは NG
React Native は Hermes 上で JavaScript bundle を実行しますが、これは解釈型の code とみなされます。Expo Updates や、現在は廃止された Microsoft CodePush も、その bundle をアップデートします。 CodePush から移行するチームは、 代替手段が必要です。ネイティブモジュールや React Native のアップグレードには、新しいリリースが必要になります。
Flutter: VM またはインタプリタ経由のみ可能
Flutter は Dart を事前にコンパイルして libapp.soを作成します。新しい .so をダウンロードすることは明示的に禁止されているため、標準の Flutter では live updates を使用できません。Shorebird は code push を追加し、Dart 仮想マシンを通じてアップデートを実行することで Play のポリシーに準拠していると述べています。詳細は Flutter アプリ向けの live updates について.
Native Kotlin, Java, Kotlin Multiplatform: code アップデート不可
を使用してダウンロード済みのdexやJARファイルをロードすることは、 DexClassLoader ポリシーが禁止している挙動そのものです。Google自身が提供する代替手段は、 Play Feature Deliveryであり、Google Playを通じてcodeモジュールをダウンロードします。これを行わない限り、ネイティブのcodeを変更することはできません。WebView内でJavaScriptを実行するKotlinやJavaのアプリであれば、そのcodeを更新することは可能です。なぜなら、ポリシーでは解釈実行されるcodeは例外としているからです。その他のネイティブロジックは、リモート構成、フィーチャーフラグ、サーバー駆動UI(SDUI)に限定されます。
Unityやゲームエンジン:コンテンツはOK、codeはNG
ゲームのcodeはコンパイルされています。アセットバンドルやPlay Asset Deliveryはコンテンツを扱います。一方、Luaのような組み込みスクリプト言語はcodeとして解釈されるため、その結果がPlayのポリシーに従っている限り、ポリシー上許可されています。
WebラッパーとTrusted Web Activities:本質的にライブ更新が可能
Trusted Web ActivityやWebViewラッパーはウェブサイトをロードするため、デプロイのたびに更新されます。Google PlayはTWAを認めています。オフラインキャッシュやネイティブブリッジは、そのラッパーの実装に依存します。TWAであればPWAのサービスワーカーを利用できますし、WebViewシェルであれば、自身で構築したJavaScriptブリッジを公開できます。Capacitorをバンドルしたアプリは、ウェブバンドルをAPKに含め、ライブアップデート用に一貫したプラグインレイヤーを追加します。
Androidでどのスタックでも不可能なこと
どのフレームワークを使用していても、live updateでは以下はできません:
- Google Play以外からdex、JAR、APK、またはネイティブ
.soファイルをダウンロードすること - 新しいAndroid権限の追加
- Google Playのポリシーで禁止されている動作の実行
- Play Storeの掲載内容と異なるアプリへの変更
次のステップ
- iOSの場合: AppleはApp Storeの審査なしでLive Updateを許可しているか?
- コンプライアンス・チェックリスト: Google Play OTAコンプライアンス・チェックリスト
- リリース戦略: Google Playコンプライアンス:主要なアップデート戦略
審査を待たず、今日中に修正をリリースする
Capgo Live Updates チャンネル、ロールバック、差分アップデート、エンドツーエンド暗号化を備え、JavaScript、HTML、CSSの変更を数分でCapacitorアプリに反映できます。オープンソースであり、セルフホストも可能です。
bunx @capgo/cli@latest init
こちらの クイックスタート に従って、最初のアップデートを送信しましょう。