動作の変更点: すべてのアプリ

Android 17 プラットフォームには、アプリに影響する可能性がある動作変更が含まれています。下記の動作変更は、targetSdkVersion に関係なく、Android 17 上で稼働するすべてのアプリに適用されます。該当する場合は、アプリをテストし、必要に応じて修正して、これらの変更に対応してください。

Android 17 をターゲットとするアプリにのみ影響する動作変更のリストも必ずご確認ください。

コア機能

Android 17(API レベル 37)には、Android システムのさまざまなコア機能を変更または拡張する以下の変更が含まれています。

アプリのメモリ上限

Android 17 では、アプリと Android ユーザーにとってより安定した決定的環境を構築するため、デバイスの合計 RAM に基づくアプリのメモリ上限が導入されました。これらの制限は、メモリリークやその他の外れ値に焦点を当て、システム全体の不安定化を引き起こす前に、UI のスタッタリング、バッテリーの消耗、アプリの強制終了を防ぐことを目的としています。ほとんどのアプリ セッションへの影響は最小限に抑えられると予想されますが、メモリのベースラインの確立など、メモリに関するベスト プラクティスを実践することをおすすめします。

アプリ セッションが影響を受けたかどうかを判断するには、ApplicationExitInfo で getDescription を呼び出します。アプリが影響を受けた場合、終了理由は REASON_OTHER になり、説明には文字列 "MemoryLimiter:AnonSwap" とその他の情報が含まれます。TRIGGER_TYPE_ANOMALY でトリガーベースのプロファイリングを使用して、メモリ上限に達したときに収集されるヒープダンプを取得することもできます。

アプリのメモリを管理するのドキュメントには、アプリのメモリの問題を診断し、リソース消費を最適化するのに役立つ情報が記載されています。

メモリ制約下でのアプリの動作をテストする

Android Debug Bridge(adb)を使用すると、メモリ制限を課しているデバイスのメモリ制限を調整または無効にできます。シェルコマンド am には、メモリ上限を調整するための 3 つのサブコマンドが用意されています。(これらのコマンドは、メモリ制限を適用しないデバイスには影響しません)。

  • am memory-limiter ignore <uid>|none|all
  • am memory-limiter manual <pid> <limit>|max|none
  • am memory-limiter status
ignore

メモリリミッターに、一部またはすべてのプロセスを無視するよう指示します。UID(Android ユーザー ID)を渡すと、メモリリミッターは、その UID に関連付けられているすべてのプロセスに対する適用を無視します。all(すべてのアプリを無視する)または none(アプリを無視しない)を渡すこともできます。none を渡すと、am memory-limiter ignore の以前の呼び出しがオーバーライドされます。

メモリリミッターに UID を無視するように指示した場合でも、am memory-limiter manual を呼び出すことで、アプリ内のプロセスに手動でメモリ上限を適用できます。

manual

指定された PID(プロセス ID)を持つプロセスにメモリ制約を課すようシステムに指示します。メモリ制約は、MB 単位の整数で指定します。たとえば、30 を渡すと、プロセスは 30 MB のメモリに制限されます。max を渡すと、そのプロセスのメモリ上限がすべて削除されます。none を渡すと、プロセスに設定された手動制限が削除され、システムのデフォルト制限(存在する場合)が復元されます。

status

メモリリミッターの現在のステータスを報告します。ステータスには、表示プロセスと非表示プロセスに課せられたメモリ制限が含まれます。

プライバシー

Android 17 では、ユーザーのプライバシーを強化するために、次の変更が加えられています。

SMS OTP 保護

Android 17 以降、Android はワンタイム パスワード(OTP)を含む SMS メッセージの保護を強化しています。

以前のバージョンの Android では、この保護は主に SMS Retriever 形式に重点を置いていました。SMS リトリーバー ハッシュを含むメッセージの配信が、ほとんどのアプリで 3 時間遅延しました。ただし、特定のアプリ(デフォルトの SMS ハンドラなど)は遅延の対象外であり、ハッシュを所有するアプリも対象外でした。

Android 17 以降では、この保護は WebOTP 形式のメッセージにも適用されます。アプリに SMS メッセージの読み取り権限があるものの、WebOTP メッセージの対象受信者ではない場合(ドメイン検証で判断)、メッセージの受信から 3 時間が経過するまで、アプリはメッセージにアクセスできません。この変更は、メッセージに記載されているドメインに関連付けられたアプリのみがプログラムで確認コードを読み取れるようにすることで、ユーザーのセキュリティを強化することを目的としています。

この 3 時間の遅延の間、SMS_RECEIVED_ACTION ブロードキャストは保留され、SMS プロバイダのデータベース クエリはフィルタされます。SMS メッセージは、遅延後にこれらのアプリで使用できるようになります。この変更は、対象 API レベルに関係なく、すべてのアプリに適用されます。

デフォルトの SMS アシスタント アプリ、接続済みデバイスのコンパニオン アプリなど、特定のアプリはこの遅延の対象外となります。OTP 抽出のために SMS メッセージの読み取りに依存しているすべてのアプリは、SMS Retriever API または SMS User Consent API を使用するように移行して、機能が継続されるようにする必要があります。

セキュリティ

Android 17 では、デバイスとアプリのセキュリティに関して次の改善が行われています。

usesClearTraffic のサポート終了計画

今後のリリースで、usesCleartextTraffic 要素は非推奨になる予定です。暗号化されていない(HTTP)接続を確立する必要があるアプリは、ネットワーク セキュリティ構成ファイルを使用するように移行する必要があります。これにより、アプリがクリアテキスト接続を確立する必要があるドメインを指定できます。

ネットワーク セキュリティ構成ファイルは、API レベル 24 以降でのみサポートされています。アプリの最小 API レベルが 24 未満の場合は、次の両方を行う必要があります。

  • usesCleartextTraffic 属性を true に設定する
  • ネットワーク構成ファイルを使用する

アプリの最小 API レベルが 24 以降の場合は、ネットワーク構成ファイルを使用できるため、usesCleartextTraffic を設定する必要はありません。

暗黙的な URI 権限付与を制限する

現在、アプリが ACTION_SEND、ACTION_SEND_MULTIPLE、ACTION_IMAGE_CAPTURE のアクションを含む URI を含むインテントを起動すると、システムはターゲット アプリに読み取りと書き込みの URI 権限を自動的に付与します。Android 18 以降、システムはこれらの権限を自動的に付与しなくなります。そのため、アプリは、システムによる権限の付与に依存するのではなく、関連する URI 権限を明示的に付与することをおすすめします。

アプリでこれらのインテントの使用を検出するには、StrictMode と detectImplicitUriPermissionGrant() を使用して違反をトリガーします。

Kotlin

val policy = StrictMode.VmPolicy.Builder()
    .detectImplicitUriPermissionGrant()
    .penaltyLog()
    .build()
StrictMode.setVmPolicy(policy)

Java

StrictMode.VmPolicy policy = new StrictMode.VmPolicy.Builder()
    .detectImplicitUriPermissionGrant()
    .penaltyLog()
    .build();
StrictMode.setVmPolicy(policy);

また、システムが暗黙的に権限を設定したときに表示されるメッセージ Please set the grant explicitly in the app を含むログに記録された例外をモニタリングすることもできます。これらのログをモニタリングするには、次の adb コマンドを使用します。

adb logcat | grep "Please set the grant explicitly in the app"

必要な権限を明示的に付与するには、FLAG_GRANT_READ_URI_PERMISSION フラグを ACTION_SEND インテントと ACTION_SEND_MULTIPLE インテントに追加します。

Kotlin

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)

Java

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

ACTION_IMAGE_CAPTURE インテントに FLAG_GRANT_READ_URI_PERMISSION フラグと FLAG_GRANT_WRITE_URI_PERMISSION フラグの両方を含めます。

Kotlin

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

Java

intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

アプリごとのキーストアの上限

Android Keystore はデバイス上のすべてのアプリで共有されるリソースであるため、アプリは Android Keystore で過剰な数の鍵を作成しないようにする必要があります。Android 17 以降、システムはアプリが所有できるキーの数に上限を適用します。上限は、Android 17(API レベル 37)以降をターゲットとする非システムアプリの場合は 50,000 キー、その他のすべてのアプリの場合は 200,000 キーです。システムアプリには、対象とする API レベルに関係なく、200,000 個のキーの上限があります。

アプリが上限を超える鍵を作成しようとすると、作成は失敗し、KeyStoreException が返されます。例外のメッセージ文字列には、キーの上限に関する情報が含まれています。アプリが例外で getNumericErrorCode() を呼び出す場合、戻り値はアプリがターゲットとする API レベルによって異なります。

  • Android 17(API レベル 37)以降をターゲットとするアプリ: getNumericErrorCode() は新しい ERROR_TOO_MANY_KEYS 値を返します。
  • その他のすべてのアプリ: getNumericErrorCode() は ERROR_INCORRECT_USAGE を返します。

クロス プロファイルのループバック トラフィックをブロックする

Android 17 以降、クロス プロファイルのループバック トラフィックはデフォルトで許可されなくなりました。同じプロファイル内のループバック トラフィックは影響を受けません。この変更は、アプリがターゲットとする API レベルに関係なく、Android 17 以降を搭載したすべてのアプリに適用されます。

ユーザー エクスペリエンスとシステム UI

Android 17 には、より一貫性のある直感的なユーザー エクスペリエンスを実現するための変更が加えられています。

回転後の IME の可視性に関するデフォルトを復元

Android 17 以降では、デバイスの構成が変更されたとき(回転など)、アプリ自体で処理されない場合、以前の IME の可視性は復元されません。

アプリが処理しない構成変更が行われ、変更後にキーボードを表示する必要がある場合は、明示的にリクエストする必要があります。このリクエストは、次のいずれかの方法で行うことができます。

  • android:windowSoftInputMode 属性を stateAlwaysVisible に設定します。
  • アクティビティの onCreate() メソッドでプログラムによってソフト キーボードをリクエストするか、onConfigurationChanged() メソッドを追加します。

手入力

Android 17 では、アプリがキーボードやタッチパッドなどの入力デバイスを操作する方法に影響する、次の変更が加えられています。

ポインタ キャプチャ中にタッチパッドがデフォルトで相対イベントを配信する

Android 17 以降では、アプリが View.requestPointerCapture() を使用してポインタ キャプチャをリクエストし、ユーザーがタッチパッドを使用している場合、システムはユーザーのタッチからポインタの移動とスクロール ジェスチャーを認識し、キャプチャされたマウスからのポインタとスクロール ホイールの移動と同じ方法でアプリに報告します。ほとんどの場合、キャプチャされたマウスをサポートするアプリで、タッチパッド用の特別な処理ロジックを追加する必要がなくなります。詳細については、View.POINTER_CAPTURE_MODE_RELATIVE のドキュメントをご覧ください。

以前は、システムはタッチパッドからのジェスチャーを認識しようとせず、代わりに、タッチスクリーンのタップと同様の形式で、未加工の絶対的な指の位置をアプリに配信していました。アプリでこの絶対データが引き続き必要な場合は、代わりに View.POINTER_CAPTURE_MODE_ABSOLUTE を指定して新しい View.requestPointerCapture(int) メソッドを呼び出す必要があります。

メディア

Android 17 では、メディアの動作に次の変更が加えられています。

バックグラウンド音声の強化

Android 17 以降、オーディオ フレームワークは、オーディオ再生、オーディオ フォーカス リクエスト、音量変更 API などのバックグラウンド オーディオ インタラクションに制限を適用し、これらの変更がユーザーによって意図的に開始されるようにします。

アプリが有効なライフサイクルにないときにオーディオ API を呼び出そうとすると、オーディオ再生 API と音量変更 API は例外をスローしたり、失敗メッセージを提供したりすることなく、サイレントに失敗します。オーディオ フォーカス API が失敗し、結果コード AUDIOFOCUS_REQUEST_FAILED が返されます。

緩和戦略などの詳細については、バックグラウンド オーディオの強化をご覧ください。

接続

Android 17 では、デバイスの接続性を強化するために、以下の変更が加えられています。

Bluetooth 接続が失われた場合の自動再ペア設定

Android 17 では、Bluetooth のボンディングの喪失を自動的に解決するように設計されたシステムレベルの機能強化である、自律的な再ペアリングが導入されています。

以前は、ボンディングが失われた場合、ユーザーは手動で [設定] に移動してペア設定を解除し、周辺機器を再度ペア設定する必要がありました。この機能は、Android 16 のセキュリティ強化を基盤としており、ユーザーが手動で [設定] に移動して周辺機器のペア設定を解除して再ペア設定しなくても、システムがバックグラウンドでボンディングを再確立できるようにします。

ほとんどのアプリではコードの変更は必要ありませんが、デベロッパーは Bluetooth スタックの次の動作変更に注意する必要があります。

  • 新しいペア設定コンテキスト: ACTION_PAIRING_REQUEST に EXTRA_PAIRING_CONTEXT エクストラが含まれるようになり、アプリは標準のペア設定リクエストと、自律システムによって開始された再ペア設定の試行を区別できるようになりました。
  • 条件付きの鍵の更新: 既存のセキュリティ キーは、再ペア設定が成功し、新しい接続が以前のボンドのセキュリティ レベルを満たすか、それを上回る場合にのみ置き換えられます。
  • インテントのタイミングの変更: ACTION_KEY_MISSING インテントは、自律的な再ペア設定の試行が失敗した場合にのみブロードキャストされるようになりました。これにより、システムがバックグラウンドでボンディングを正常に復元した場合に、アプリで不要なエラー処理を行う必要がなくなります。
  • ユーザー通知: システムは、新しい UI 通知とダイアログを介して再ペア設定を管理します。ユーザーは、再接続を認識できるように、再ペアリングの試行を確認するよう求められます。

周辺機器メーカーとコンパニオン アプリ デベロッパーは、ハードウェアとアプリがボンドの移行を適切に処理することを確認する必要があります。この動作をテストするには、次のいずれかの方法でリモート ボンドの損失をシミュレートします。

  • 周辺機器から結合情報を手動で削除する
  • [設定] > [接続済みのデバイス] で、デバイスのペア設定を手動で解除します。