これまでのリリースと同様、Android 17 には、アプリに影響する可能性がある動作変更が含まれています。下記の動作変更は、Android 17 以上をターゲットとするアプリにのみ適用されます。アプリが Android 17 以上をターゲットとする場合は、必要に応じてアプリを変更し、下記の動作に対応できるようにしてください。
アプリの targetSdkVersion に関係なく、Android 17 で実行されるすべてのアプリに影響する動作変更のリストも必ずご確認ください。
ユーザー エクスペリエンスとシステム UI
Android 17 には、より一貫性のある直感的なユーザー エクスペリエンスを実現するための、以下の変更が含まれています。
メモリ上限ウィジェット
Android 17 以降では、Android 17(API レベル 37)以降を対象とするアプリの RemoteViews の更新に、システムが厳格なメモリ上限を適用します。アプリが RemoteViews オブジェクトを AppWidgetManager.updateAppWidget に渡すと、system_server は、ペイロード内のすべての向きとサイズバケットにわたるすべての画像データの合計メモリ使用量を計算します。合計メモリがシステムの上限(mMaxWidgetBitmapMemory)を超えると、システムは更新を拒否し、IllegalArgumentException をスローします。
java.lang.IllegalArgumentException: RemoteViews for widget update exceeds maximum bitmap memory usage (used: XXXXX, max: YYYYY)
API レベル 36 以下を対象とするアプリの場合、システムはこのメモリ違反を警告(Slog.w)としてログに記録し、例外はスローしません。
Android のスキル
GitHub で表示AppWidget の更新とビットマップ メモリを管理する
android skills add glance-appwidget-updates-and-memoryシステムがメモリの上限を計算する方法
システムは、アクティブなディスプレイ構成に対して、ウィジェットのビットマップ メモリ予算を 6 * width * height バイト(1.5 * 4 * width * height、全画面 ARGB_8888 バッファのサイズの 1.5 倍に相当)に設定します。API レベル 37 以降では、この計算に次の両方が含まれます。
RemoteViews.mBitmapCacheに保存されている、メモリ内のBitmapオブジェクトとビットマップを基盤とするIconオブジェクト(Icon.TYPE_BITMAPとIcon.TYPE_ADAPTIVE_BITMAP)(setImageViewBitmap、Icon.createWithBitmap、Icon.createWithAdaptiveBitmap、Jetpack GlanceImageProvider(bitmap)への呼び出しなど)。mBitmapCache内の一意のBitmapインスタンスまたはビットマップを基盤とするIconインスタンスは、RemoteViews階層ごとに 1 回カウントされます。- URI ベースの画像(
Icon.createWithContentUri、setImageViewUri、GlanceImageProvider(uri))は、system_serverのRemoteViewsIPC バイト上限にはカウントされませんが、ウィジェット ホスト プロセスは、参照されたcontent://ファイルをフル解像度で独自のヒープにデコードします。ダウンサンプリングされた画像は、FileProviderURI を介して公開する前に、必ずcontext.cacheDirに書き込みます。
緩和策
スマートフォン、タブレット、折りたたみ式デバイスでウィジェットの更新をメモリの上限内に抑えるには、次の操作を行います。
WindowMetricsからランタイム メモリ予算を計算する: API レベル 30 以降では、resources.displayMetricsではなくWindowManager.currentWindowMetrics.boundsからアクティブ ウィンドウの境界を読み取ります。マルチ解像度デバイスや折りたたみ式デバイスでは、displayMetricsが非アクティブなディスプレイのサイズを報告することがあります。次の例に示すように、ウィジェットの画像予算の合計を6L * bounds.width() * bounds.height()と見積もります。private const val FALLBACK_MAX_BYTES = 15_000_000L fun calculateWidgetMemoryCapBytes(context: Context): Long { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { val wm = context.getSystemService(WindowManager::class.java) ?: return FALLBACK_MAX_BYTES val bounds = wm.currentWindowMetrics.bounds return 6L * bounds.width().toLong() * bounds.height().toLong() } val dm = context.resources.displayMetrics return 6L * dm.widthPixels.toLong() * dm.heightPixels.toLong() }ウィジェットの表示可能なサイズに画像をダウンサンプリングし、
RGB_565を使用する: ウィジェットの最大表示サイズ(maxWidthDpxmaxHeightDp)に合わせた 2 のべき乗のBitmapFactory.Options.inSampleSize値でビットマップをデコードし、不透明な写真やサムネイルにはARGB_8888(1 ピクセルあたり4バイト)ではなくBitmap.Config.RGB_565(1 ピクセルあたり2バイト)を使用します。Jetpack Glance の
provideContentの外部でビットマップ デコードをホイスティングする:SizeMode.ResponsiveまたはSizeMode.Exactを使用する場合、Glance はサイズバケットごとに 1 回provideContentラムダを呼び出します。provideContentを呼び出す前に、provideGlance内で共有Bitmapを 1 回デコードします。これにより、すべてのサイズバケットがRemoteViews.mBitmapCache内の同じBitmapインスタンスを参照するようになります。画像を置き換える場合は、完全な
updateAppWidget呼び出しを使用する: 従来のAppWidgetProvider実装では、AppWidgetManager.partiallyUpdateAppWidgetを呼び出してBitmapビューまたはIconビューをスワップしないでください。部分更新では、以前にキャッシュに保存されたイメージ アクションを削除せずに、新しいアクションをsystem_serverの既存のRemoteViewsツリーにマージします。完全なRemoteViewsレイアウトを作成し、代わりにupdateAppWidgetを呼び出します。エラー フォールバック レイアウトを提供する: Jetpack Glance で
onCompositionErrorをオーバーライドして、更新が失敗した場合にゼロビットマップのRemoteViewsフォールバックをレンダリングします。
接続されているデバイスでウィジェットの現在のシリアル化されたビットマップ メモリ使用量を検査するには、次のコマンドを実行します。
adb shell dumpsys appwidget
コア機能
Android 17 には、Android システムのさまざまなコア機能を変更または拡張する、以下の変更が含まれています。
MessageQueue の新しいロックフリー実装
Android 17 以降、Android 17(API レベル 37)以降をターゲットとするアプリは、android.os.MessageQueue の新しいロックフリー実装を受け取ります。新しい実装では、パフォーマンスが向上し、フレームの欠落が減少しますが、MessageQueue のプライベート フィールドとメソッドを反映するクライアントが破損する可能性があります。
緩和戦略などの詳細については、MessageQueue の動作変更に関するガイダンスをご覧ください。
静的 final フィールドが変更不可に
Android 17(API レベル 37)以降をターゲットとする Android 17 以降で動作するアプリは、static final フィールドを変更できません。アプリがリフレクションを使用して static final フィールドを変更しようとすると、IllegalAccessException が発生します。JNI API(SetStaticLongField() など)を介してこれらのフィールドのいずれかを変更しようとすると、アプリがクラッシュします。
ユーザー補助
Android 17 では、ユーザー補助機能を改善するために次の変更が加えられています。
複雑な IME 物理キーボード入力のユーザー補助サポート
This feature introduces new AccessibilityEvent and TextAttribute
APIs to enhance screen reader spoken feedback for CJKV language input. CJKV IME
apps can now signal whether a text conversion candidate has been selected during
text composition. Apps with edit fields can specify text change types when
sending text changed accessibility events.
For example, apps can specify that a text change occurred during text
composition, or that a text change resulted from a commit.
Doing this enables accessibility
services such as screen readers to deliver more precise feedback based on the
nature of the text modification.
App adoption
IME Apps: When setting composing text in edit fields, IMEs can use
TextAttribute.Builder.setTextSuggestionSelected()to indicate whether a specific conversion candidate was selected.Apps with Edit Fields: Apps that maintain a custom
InputConnectioncan retrieve candidate selection data by callingTextAttribute.isTextSuggestionSelected(). These apps should then callAccessibilityEvent.setTextChangeTypes()when dispatchingTYPE_VIEW_TEXT_CHANGEDevents. Apps targeting Android 17 (API level 37) that use the standardTextViewwill have this feature enabled by default. (That is,TextViewwill handle retrieving data from the IME and setting text change types when sending events to accessibility services).Accessibility Services: Accessibility services that process
TYPE_VIEW_TEXT_CHANGEDevents can callAccessibilityEvent.getTextChangeTypes()to identify the nature of the modification and adjust their feedback strategies accordingly.
プライバシー
Android 17 では、ユーザーのプライバシーを強化するために、次の変更が加えられています。
ECH(Encrypted Client Hello)が有効
Android 17 では、Encrypted Client Hello(ECH)のプラットフォーム サポートが導入されています。ECH は、TLS handshake で Server Name Indication(SNI)を暗号化することで、ユーザーのプライバシーを強化する TLS 拡張機能です。この暗号化により、ネットワーク監視者がアプリの接続先である特定のドメインを簡単に特定できなくなります。
Android 17(API レベル 37)以降をターゲットとするアプリの場合、TLS 接続に ECH が使用されます。ECH は、アプリで使用されるネットワーキング ライブラリ(HttpEngine、WebView、OkHttp など)に ECH サポートが統合されており、リモート サーバーも ECH プロトコルをサポートしている場合にのみ有効になります。ECH をネゴシエートできない場合、クライアントはランダム化されたコンテンツを含む ECH 拡張機能を送信します(ECH GREASE と呼ばれるメカニズム)。ECH GREASE の仕組みについて詳しくは、RFC 9849 をご覧ください。
アプリでこの動作をカスタマイズできるように、Android 17 ではネットワーク セキュリティ構成ファイルに新しい <domainEncryption> 要素が追加されています。デベロッパーは、<base-config> タグまたは <domain-config> タグ内で <domainEncryption> を使用して、グローバルまたはドメインごとに ECH モード("enabled" や "disabled" など)を選択できます。
詳細については、Encrypted Client Hello のドキュメントをご覧ください。
Android 17 をターゲットとするアプリに必要なローカル ネットワーク権限
Android 17 では、不正なローカル ネットワーク アクセスからユーザーを保護するために、ACCESS_LOCAL_NETWORK 実行時の権限が導入されています。これは既存の NEARBY_DEVICES 権限グループに該当するため、他の NEARBY_DEVICES 権限をすでに付与しているユーザーには、再度プロンプトが表示されることはありません。この新しい要件により、悪意のあるアプリが制限のないローカル ネットワーク アクセスを悪用して、ユーザーの追跡やフィンガープリントを密かに行うことを防ぎます。この権限を宣言してリクエストすることで、アプリはスマートホーム デバイスやキャスト レシーバーなどのローカル エリア ネットワーク(LAN)上のデバイスを検出して接続できるようになります。
Android 17(API レベル 37)以降をターゲットとするアプリには、LAN デバイスとの通信を維持するための 2 つのパスがあります。システムを介したプライバシー保護デバイス選択ツールを採用して権限プロンプトをスキップするか、実行時にこの新しい権限を明示的にリクエストしてローカル ネットワーク通信を維持します。
詳細については、ローカル ネットワークの権限に関するドキュメントをご覧ください。
実機でパスワードを非表示にする
If an app targets Android 17 (API level 37) or higher and the user is using
a physical input device (for example, an external keyboard), the Android
operating system applies the new show_passwords_physical setting to all
characters in the password field. By default, that setting hides all password
characters.
The Android system shows the last-typed password character to help the user see if they mistyped the password. However, this is much less necessary with larger external keyboards. In addition, devices with external keyboards often have larger displays, which increases the danger of someone seeing the typed password.
If the user is using the device's touchscreen, the system applies the new
show_passwords_touch setting.
標準の SMS メッセージの OTP 保護
Android 17 以降、Android は SMS OTP 保護を拡張し、標準の SMS メッセージ(WebOTP 形式または SMS Retriever 形式を使用しない OTP を含む SMS メッセージ)に適用します。Android 17(API レベル 37)以降をターゲットとするほとんどのアプリでは、これらの SMS メッセージは受信から 3 時間経過するまで利用できません。この遅延は、OTP のハイジャックを防ぐことを目的としています。この 3 時間の遅延の間、SMS_RECEIVED_ACTION ブロードキャストは保留され、SMS プロバイダのデータベース クエリはフィルタされます。SMS メッセージは、遅延後にこれらのアプリで利用できるようになります。
デフォルトの SMS アシスタント アプリ、接続済みデバイスのコンパニオン アプリなど、特定のアプリはこの遅延の対象外となります。OTP 抽出のために SMS メッセージの読み取りに依存しているすべてのアプリは、SMS Retriever API または SMS User Consent API を使用するように移行して、機能が継続されるようにする必要があります。
セキュリティ
Android 17 では、デバイスとアプリのセキュリティが次のように改善されています。
アクティビティのセキュリティ
Android 17 では、プラットフォームが「デフォルトで保護」アーキテクチャに移行し、フィッシング、インタラクション ハイジャック、混乱した代理攻撃などの重大度の高いエクスプロイトを軽減するように設計された一連の機能強化が導入されています。このアップデートでは、アプリの互換性とユーザー保護を維持するために、デベロッパーが新しいセキュリティ標準を明示的に有効にする必要があります。
デベロッパーへの主な影響は次のとおりです。
- BAL の強化とオプトインの改善: バックグラウンド アクティビティの起動(BAL)の制限を改良し、
IntentSenderに保護を拡張しています。デベロッパーは、以前のMODE_BACKGROUND_ACTIVITY_START_ALLOWED定数から移行する必要があります。代わりに、MODE_BACKGROUND_ACTIVITY_START_ALLOW_IF_VISIBLEなどのきめ細かい制御を採用する必要があります。これにより、アクティビティの開始を呼び出し元アプリが表示されているシナリオに制限し、攻撃対象領域を大幅に縮小できます。 - 導入ツール: デベロッパーは、厳格モードと更新された lint チェックを利用して、以前のパターンを特定し、将来のターゲット SDK 要件に備える必要があります。
CT をデフォルトで有効にする
Android 17(API レベル 37)以降をターゲットとするアプリの場合、Certificate Transparency(CT)がデフォルトで有効になります。(Android 16 では、CT は利用可能ですが、アプリはオプトインする必要がありました)。
より安全なネイティブ DCL - C
アプリが Android 17(API レベル 37)以降をターゲットとしている場合、Android 14 で DEX ファイルと JAR ファイルに導入された、より安全な動的コード読み込み(DCL)保護がネイティブ ライブラリにも適用されるようになりました。
System.load() を使用して読み込まれるすべてのネイティブ ファイルは、読み取り専用としてマークする必要があります。そうしないと、システムは UnsatisfiedLinkError をスローします。
アプリでは可能な限り、コードを動的に読み込まないようにすることをおすすめします。コードを動的に読み込むと、コード インジェクションやコードの改ざんによってアプリが不正使用されるリスクが大幅に高まります。
CP2 データビューで PII フィールドを制限する
Android 17(API レベル 37)以降をターゲットとするアプリの場合、連絡先プロバイダ 2(CP2)は、個人を特定できる情報(PII)を含む特定の列をデータビューから制限します。この変更が有効になると、ユーザーのプライバシーを強化するために、これらの列がデータビューから削除されます。制限付きの列は次のとおりです。
ContactsContract.Data のこれらの列を使用しているアプリは、RAW_CONTACT_ID と結合することで、代わりに ContactsContract.RawContacts から抽出できます。
CP2 で厳格な SQL チェックを適用する
For apps targeting Android 17 (API level 37) and
higher, Contacts Provider 2 (CP2) enforces strict SQL query validation when
the ContactsContract.Data table is accessed without
READ_CONTACTS permission.
With this change, if an app doesn't have READ_CONTACTS
permission, StrictColumns and
StrictGrammar options are set when querying
the ContactsContract.Data table. If a query
uses a pattern that isn't compatible with these, it will be
rejected and cause an exception to be thrown.
インテリジェンス
Android 17 では、システム インテリジェンスに次の変更が加えられています。
setContentCaptureEnabled のサポート終了
コンテンツ キャプチャは、特定のデバイスでデフォルトで有効になっており、オンデバイス AI 機能が画面コンテンツを分析してインテリジェントなエクスペリエンスを提供できるようにします。
Android 17 以降、ContentCaptureManager.setContentCaptureEnabled(boolean) API メソッドは非推奨になりました。Android 17(API レベル 37)以降をターゲットとするアプリの場合、setContentCaptureEnabled(false) を呼び出してもコンテンツ キャプチャが無効にならなくなりました。
アプリで引き続きコンテンツ キャプチャを無効にする必要がある場合や、画面コンテンツがシステムによってキャプチャされないように制限する必要がある場合は、FLAG_SECURE ウィンドウ レイアウト パラメータを使用するように移行する必要があります。
コンテンツ キャプチャを無効にするには、次の例に示すように、ウィンドウに FLAG_SECURE フラグを設定します。
Kotlin
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
Java
getWindow().setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
);
詳細については、WindowManager.LayoutParams.FLAG_SECURE リファレンス ドキュメントをご覧ください。
メディア
Android 17 では、メディアの動作に次の変更が加えられています。
バックグラウンド音声の強化
Android 17 以降、オーディオ フレームワークは、オーディオ再生、オーディオ フォーカス リクエスト、音量変更 API などのバックグラウンド オーディオ インタラクションに制限を適用し、これらの変更がユーザーによって意図的に開始されるようにします。
一部のオーディオ制限はすべてのアプリに適用されます。ただし、アプリが Android 17(API レベル 37)をターゲットとしている場合は、制限がより厳しくなります。これらのアプリのいずれかがバックグラウンドでオーディオを操作する場合は、フォアグラウンド サービスを実行する必要があります。さらに、アプリは次の要件のいずれかまたは両方を満たす必要があります。
- フォアグラウンド サービスには、使用中(WIU)機能が必要です。
- アプリに正確なアラームの権限があり、
USAGE_ALARM音声ストリームを操作している。
緩和戦略などの詳細については、バックグラウンド オーディオの強化をご覧ください。
デバイスのフォーム ファクタ
Android 17 には、さまざまなデバイスサイズとフォーム ファクタでユーザー エクスペリエンスを向上させるための、以下の変更が含まれています。
大画面(sw>=600dp)で画面の向き、サイズ変更、アスペクト比の制約を無視するようにプラットフォーム API を変更
Android 16 では、対象 API レベル 36 以降をターゲットとするアプリに対して、大画面(sw >= 600dp)での画面の向き、サイズ変更、アスペクト比の制限を無視するようにプラットフォーム API が変更されました。デベロッパーは SDK 36 でこれらの変更をオプトアウトできますが、Android 17(API レベル 37)以降をターゲットとするアプリでは、このオプトアウトは利用できなくなります。
詳細については、向きとサイズ変更の制限が無視されるをご覧ください。
接続
Android 17 では、Bluetooth RFCOMM ソケットの標準的な Java InputStream 動作との整合性を高めるため、以下の変更が導入されています。
RFCOMM の一貫した BluetoothSocket read() 動作
Android 17(API レベル 37)をターゲットとするアプリでは、RFCOMM ベースの BluetoothSocket から取得した InputStream の read() メソッドは、ソケットが閉じられたとき、または接続が切断されたときに -1 を返すようになりました。
この変更により、RFCOMM ソケットの動作が LE CoC ソケットと整合し、ストリームの終わりに達すると -1 が返されるという標準の InputStream.read() ドキュメントに沿った動作になります。
IOException をキャッチして読み取りループを抜けることにのみ依存しているアプリは、この変更の影響を受ける可能性があります。BluetoothSocket の読み取りループを更新して、戻り値が -1 であることを明示的に確認する必要があります。これにより、リモート デバイスが切断されたとき、またはソケットが閉じられたときに、ループが正しく終了します。推奨される実装の例については、Bluetooth データを転送するガイドのコード スニペットをご覧ください。