Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

動作の変更点: API レベル 28 以降をターゲットとするアプリ

Android 9(API レベル 28)では、Android システムにさまざまな変更が加えられています。以下の動作の変更点は、API レベル 28 以降をターゲットとするアプリにのみ適用されます。targetSdkVersion を API レベル 28 以降に設定するアプリは、必要に応じてアプリを修正してこれらの動作を適切にサポートする必要があります。

Android 9 で実行されるすべてのアプリに影響を与える変更点については、ターゲットとする API レベルに関係なく、動作の変更点: すべてのアプリをご覧ください。

フォアグラウンド サービス

Android 9 以降をターゲットとするアプリは、フォアグラウンド サービスを使用する場合、FOREGROUND_SERVICE 権限をリクエストする必要があります。これは normal 権限であり、リクエストしたアプリに自動で付与されます。

Android 9 以降をターゲットとするアプリが FOREGROUND_SERVICE をリクエストせずにフォアグラウンド サービスを作成しようとすると、システムによって SecurityException がスローされます。

プライバシーの変更点

アプリが Android 9 をターゲットとしている場合、以下の動作の変更点に留意する必要があります。デバイスのシリアル番号および DNS 情報に関する以下のアップデートにより、ユーザー プライバシーが強化されます。

ビルドシリアル番号のサポートの終了

Android 9 では、ユーザーのプライバシーを保護するために、Build.SERIAL が常に "UNKNOWN" に設定されます。

アプリでデバイスのハードウェア シリアル番号を使用する必要がある場合は、READ_PHONE_STATE 権限をリクエストしてから getSerial() を呼び出してください。

DNS プライバシー

Android 9 をターゲットとするアプリでは、プライベート DNS API を考慮する必要があります。特に、システム リゾルバが DNS-over-TLS を実行している場合、アプリでは、ビルトインの DNS クライアントがシステムと同じホスト名で暗号化 DNS を使用しているか、システム リゾルバを優先するために DNS クライアントが無効にされている必要があります。

フレームワーク セキュリティの変更

Android 9 には、アプリのセキュリティを強化する動作の変更点がいくつか追加されていますが、これらの変更は、アプリが API レベル 28 以降をターゲットとしている場合にのみ効力を生じます。

デフォルトで有効になっているネットワーク TLS

アプリが Android 9 以降をターゲットとしている場合、isCleartextTrafficPermitted() メソッドはデフォルトで false を返します。アプリで特定のドメインのクリアテキストを有効にする必要がある場合、アプリのネットワーク セキュリティ構成でそのドメインの cleartextTrafficPermitted を明示的に true に設定する必要があります。

プロセスで分けられたウェブベース データ ディレクトリ

Android 9 では、アプリの安定性とデータの整合性を向上させるために、アプリが複数のプロセス間で 1 つの WebView データ ディレクトリを共有することはできません。通常、このようなデータ ディレクトリには、ウェブ ブラウジングに関連する Cookie、HTTP キャッシュ、その他の永続および一時ストレージが格納されます。

ほとんどの場合、アプリは android.webkit パッケージのクラス(WebViewCookieManager など)を 1 つのプロセスのみで使用する必要があります。たとえば、WebView を使用するすべての Activity オブジェクトを同じプロセスに移動する必要があります。disableWebView() をアプリの他のプロセスで呼び出すことで、「1 つのプロセスのみ」というルールをより厳密に適用することができます。このように呼び出すことで、WebView が依存ライブラリから呼び出された場合でも、他のプロセスで誤って初期化されることがなくなります。

アプリが複数のプロセスで WebView のインスタンスを使用する必要がある場合、各プロセスで WebView の特定のインスタンスを使用する前に、WebView.setDataDirectorySuffix() メソッドを使って、そのプロセスに一意のデータ ディレクトリ サフィックスを割り当てる必要があります。このメソッドは、各プロセスのウェブデータをアプリのデータ ディレクトリ内にある専用のディレクトリに格納します。

アプリ別の SELinux ドメイン

Android 9 以降をターゲットとするアプリでは、どこからでもアクセス可能な UNIX 権限を使用して他のアプリとデータを共有することができません。この変更により、Android アプリケーション サンドボックスの整合性が向上し、特に、アプリのプライベート データにはそのアプリのみがアクセスできるという要件が強化されています。

他のアプリとファイルを共有するには、コンテンツ プロバイダを使用します。

接続の変更

接続データのカウントとマルチパス

Android 9 以降をターゲットとするアプリ内では、システムにより、デバイスが Wi-Fi を使用しているときのモバイル トラフィックなど、現在のデフォルトではないネットワーク上のネットワーク トラフィックがカウントされ、そのトラフィックをクエリするために、NetworkStatsManager クラスのメソッドが提供されます。

特に、getMultipathPreference() は、このネットワーク トラフィックに基づいた値を返すようになりました。Android 9 以降では、このメソッドにより、モバイルデータに対して true が返されますが、1 日のうちに特定の量を超えるトラフィックが蓄積すると、false が返されるようになります。Android 9 で実行されるアプリでは、このメソッドを呼び出す際にはこのヒントを考慮する必要があります。

ConnectivityManager.NetworkCallback クラスが VPN に関する情報をアプリに送信するようになりました。この変更により、アプリできわめて簡単に接続イベントをリッスンできるようになりました。しかも、同期呼び出しと非同期呼び出しを組み合わせたり、制限付きの API を使用したりする必要もありません。また、デバイスが複数の Wi-Fi ネットワークや複数のモバイル ネットワークに同時に接続されている場合でも、情報の転送が想定どおりに機能します。

Apache HTTP クライアントのサポートの終了

Android 6.0 では、Apache HTTP クライアントのサポートが削除されました。Android 9 以降では、そのライブラリが bootclasspath から削除されており、デフォルトではアプリで利用できません。

Android 9 以降をターゲットとしているアプリでは、Apache HTTP クライアントの使用を継続するために、次のコードを AndroidManifest.xml に追加できます。

<uses-library android:name="org.apache.http.legacy" android:required="false"/>
    

アプリでは、Apache ランタイム ライブラリを使用する代わりに、APK に独自のバージョンの org.apache.http ライブラリをバンドルできます。その場合、(Jar Jar などのユーティリティを使って)ライブラリを再パッケージ化し、ランタイムで提供されるクラスとのクラス互換性の問題を回避する必要があります。

UI の変更

View のフォーカス

面積が 0 のビュー(幅または高さが 0)はフォーカス不可となりました。

また、タップモードでは、Activity は初期フォーカスを暗黙的に指定することができません。代わりに、ご自身の判断で必要に応じて明示的に初期フォーカスを要求するようにしてください。

CSS RGBA 16 進値の処理

Android 9 以降をターゲットとするアプリでは、4 桁および 8 桁の 16 進数 CSS 色を扱うために、ドラフトの CSS Color Module Level 4 で策定された動作を有効にする必要があります。

CSS Color Module Level 4 は、Chrome 52 からサポートされていますが、現在は WebView で無効になっています。これは、既存の Android アプリが Android のバイト順(ARGB)で 32 ビットの 16 進数色を含み、レンダリング エラーを引き起こす可能性があると判明したためです。

たとえば現在、API レベル 27 以前をターゲットとするアプリでは、WebView#80ff8080 という色が不透明のライトレッド(#ff8080)にレンダリングされます。現在は、先頭のコンポーネント(Android ではアルファ コンポーネントとして認識される)は無視されます。一方、API レベル 28 以降をターゲットとするアプリの場合、#80ff8080 は、透明度が 50% のライトグリーン(#80ff80)として認識されます。

ファイルの MIME タイプ スニッフィング: URI

Android 9 より前のバージョンの Android では、MIME タイプをファイルの内容から推測することができました。Android 9(API レベル 28)以降では、WebViewfile: URI を読み込む場合、アプリで正確なファイル拡張子を使用する必要があります。

MIME タイプを推測するためにファイルの内容を使用すると、セキュリティ バグの原因になる可能性があるため、最近のブラウザでは一般に、この方法は許可されていません。

一般的なファイル拡張子(.html.txt.js.css など)の場合、MIME タイプはその拡張子によって決まります。ファイルに拡張子がない場合、または一般的でない拡張子の場合、MIME タイプは書式なしテキストになります。

たとえば、file:///sdcard/test.html のような URI は HTML としてレンダリングされますが、file:///sdcard/test のような URI は、ファイルに HTML データが含まれていても、書式なしテキストとしてレンダリングされます。

ドキュメントのスクロール要素

Android 9 では、ドキュメントのルート要素がスクロール要素である場合、適切な処理が実行されます。Android 9 より前のバージョンでは、スクロール位置が本文要素で設定され、ルート要素のスクロール値は 0 でした。Android 9 では標準に準拠した動作が可能で、スクロール要素がルート要素になります。

また、document.body.scrollTopdocument.body.scrollLeftdocument.documentElement.scrollTopdocument.documentElement.scrollLeft に直接アクセスした場合の動作は、ターゲット SDK によって異なります。ビューポートのスクロール値にアクセスするには、可能であれば document.scrollingElement を使用します。

停止中のアプリからの通知

Android 9 より前のバージョンでは、停止中のアプリからの通知はキャンセルされていました。Android 9 以降では、停止中のアプリからの通知は、アプリが再開されるまで非表示になります。