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

Android 9(API レベル 28)では、Android システムにいくつかの変更が加えられています。以下の動作変更は、ターゲットとする API レベルに関係なく、Android 9 プラットフォームで実行されるすべてのアプリに適用されます。すべてのデベロッパーは、これらの変更を確認し、該当する場合はアプリを修正して適切に対応する必要があります。

API レベル 28 以上をターゲットとするアプリにのみ影響する変更については、動作の変更: API レベル 28 以上をターゲットとするアプリをご覧ください。

電源管理

Android 9 には、デバイスの電源管理を改善する新機能が導入されています。これらの変更と、Android 9 より前にすでにあった機能により、システム リソースを最も必要とするアプリでシステム リソースを利用できるようになります。

詳しくは、電源管理をご覧ください。

プライバシーの変更点

Android 9 では、ユーザーのプライバシーを強化するために、デバイス センサーへのバックグラウンド アプリのアクセスの制限、Wi-Fi スキャンから取得される情報の制限、通話、スマートフォンの状態、Wi-Fi スキャンに関連する新しい権限ルールと権限グループなど、いくつかの動作変更が導入されています。

これらの変更は、ターゲット SDK のバージョンに関係なく、Android 9 で実行されるすべてのアプリに影響します。

バックグラウンドでのセンサーへのアクセスの制限

Android 9 では、バックグラウンド アプリがユーザー入力とセンサーデータにアクセスする機能が制限されています。Android 9 搭載デバイスでアプリがバックグラウンドで実行されている場合、次の制限がアプリに適用されます。

  • アプリはマイクやカメラにアクセスできません。
  • 加速度計やジャイロスコープなど、連続レポートモードを使用するセンサーはイベントを受信しません。
  • 変更時またはワンショットのレポートモードを使用するセンサーは、イベントを受信しません。

Android 9 搭載デバイスでアプリがセンサー イベントを検出する必要がある場合は、フォアグラウンド サービスを使用します。

通話履歴へのアクセスの制限

Android 9 では、CALL_LOG 権限グループが導入され、READ_CALL_LOGWRITE_CALL_LOGPROCESS_OUTGOING_CALLS の各権限がこのグループに移動されます。以前のバージョンの Android では、これらの権限は PHONE 権限グループに配置されていました。

この CALL_LOG 権限グループにより、ユーザーは、通話記録の読み取りや電話番号の識別など、通話に関する機密情報にアクセスする必要があるアプリを適切に管理して把握できるようになります。

アプリが通話履歴にアクセスする必要がある場合や、発信を処理する必要がある場合は、これらの権限を CALL_LOG 権限グループから明示的にリクエストする必要があります。そうでない場合は、SecurityException が発生します。

注: これらの権限によってグループが変更され、実行時に付与されるため、ユーザーは通話履歴情報へのアプリのアクセスを拒否できます。アプリはこの場合、情報にアクセスできない場合に適切に対処できる必要があります。

アプリがすでに実行時の権限に関するベスト プラクティスに従っている場合は、権限グループの変更を処理できます。

電話番号へのアクセスの制限

Android 9 で実行されるアプリは、アプリのユースケースに必要な他の権限に加えて、READ_CALL_LOG 権限を先に取得しない限り、電話番号やスマートフォンのステータスを読み取ることができません。

着信と発信に関連付けられた電話番号は、着信や発信などの電話ステータスのブロードキャストに表示され、PhoneStateListener クラスからアクセスできます。ただし、READ_CALL_LOG 権限がない場合、PHONE_STATE_CHANGED ブロードキャストと PhoneStateListener を通じて提供される電話番号フィールドは空になります。

スマートフォンの状態から電話番号を読み取るには、ユースケースに基づいて必要な権限をリクエストするようにアプリを更新します。

Wi-Fi の位置情報と接続情報へのアクセスが制限されています

Android 9 では、アプリが Wi-Fi スキャンを実行するための権限要件が、以前のバージョンよりも厳格になっています。詳しくは、Wi-Fi スキャンの制限をご覧ください。

同様の制限が getConnectionInfo() メソッドにも適用されます。このメソッドは、現在の Wi-Fi 接続を記述する WifiInfo オブジェクトを返します。呼び出し元アプリに次の権限がある場合にのみ、このオブジェクトのメソッドを使用して SSID と BSSID の値を取得できます。

  • ACCESS_FINE_LOCATION または ACCESS_COARSE_LOCATION
  • アクセス_WIFI_STATE

SSID または BSSID を取得するには、デバイスの位置情報サービスも有効にする必要があります([設定] > [位置情報])。

Wi-Fi サービス メソッドから情報が削除される

Android 9 では、次のイベントとブロードキャストは、ユーザーの位置情報に関する情報や個人を特定できるデータを受信しません。

Wi-Fi からの NETWORK_STATE_CHANGED_ACTION システム ブロードキャストに、SSID(以前の EXTRA_SSID)、BSSID(以前の EXTRA_BSSID)、接続情報(以前の EXTRA_NETWORK_INFO)が含まれなくなりました。アプリでこの情報が必要な場合は、代わりに getConnectionInfo() を呼び出します。

電話に関する情報がデバイスの位置情報の設定に依存するようになりました

Android 9 を搭載したデバイスでユーザーがデバイスの位置情報を無効化した場合、以下のメソッドでは結果が返されません。

非 SDK インターフェースの使用制限

アプリの安定性と互換性を確保するため、プラットフォームでは、一部の非 SDK のメソッドとフィールドの使用が制限されています。これらの制限は、これらのメソッドとフィールドに直接アクセスするか、リフレクション経由でアクセスする場合や、JNI を使用する場合にも適用されます。Android 9 では、アプリは引き続きこれらの制限付きインターフェースにアクセスできます。プラットフォームはトーストとログエントリを使用して、注意を喚起します。アプリにそのようなトーストが表示される場合は、制限付きインターフェース以外の実装戦略を採用することが重要です。代替の戦略がないと思われる場合は、バグを報告して制限の再審査をリクエストできます。

非 SDK インターフェースの制限に、重要な情報が記載されています。ご確認いただき、引き続きアプリが適切に機能するようにしてください。

セキュリティ動作の変更

デバイスのセキュリティの変更

Android 9 には、アプリがターゲットとするバージョンに関係なく、アプリのセキュリティを強化する機能がいくつか追加されています。

TLS 実装の変更

Android 9 では、システムの TLS 実装に次のような変更が加えられています。

  • 作成中に SSLSocket のインスタンスの接続に失敗した場合、システムは NullPointerException ではなく IOException をスローします。
  • SSLEngine クラスは、発生した close_notify アラートを適切に処理します。

Android アプリで安全なウェブ リクエストを実行する方法について詳しくは、HTTPS の例をご覧ください。

SECCOMP フィルタの厳格化

Android 9 では、アプリで使用できるシステムコールがさらに制限されています。この動作は、Android 8.0(API レベル 26)に含まれる SECCOMP フィルタの拡張です。

暗号の変更

Android 9 では、暗号アルゴリズムの実装と処理に複数の変更が加えられています。

パラメータとアルゴリズムの Conscrypt 実装

Android 9 では、Conscrypt のアルゴリズム パラメータの追加実装を利用できます。AES、DESEDE、OAEP、EC などのパラメータがあります。Android 9 以降、これらのパラメータと多くのアルゴリズムの Bouncy Castle バージョンはサポートが終了しています。

Android 8.1(API レベル 27)以前をターゲットとしているアプリの場合、サポートが終了したアルゴリズムの Bouncy Castle 実装をリクエストすると、警告が表示されます。ただし、Android 9 をターゲットにしている場合、これらのリクエストはそれぞれ NoSuchAlgorithmException をスローします。

その他の変更点

Android 9 では、暗号に関連するその他の変更がいくつか導入されています。

  • PBE 鍵を使用する際、Bouncy Castle が初期化ベクトル(IV)を想定しているのに、アプリが初期化ベクトル(IV)を提供しない場合は、警告が表示されます。
  • ARC4 暗号の Conscrypt 実装では、ARC4/ECB/NoPadding または ARC4/NONE/NoPadding のいずれかを指定できます。
  • Crypto Java Cryptography Architecture(JCA)プロバイダは削除されました。そのため、アプリが SecureRandom.getInstance("SHA1PRNG", "Crypto") を呼び出すと、NoSuchProviderException が発生します。
  • アプリが鍵構造より大きいバッファから RSA 鍵を解析する場合、例外は発生しなくなります。

Android の暗号機能の使用について詳しくは、暗号化をご覧ください。

Android の安全な暗号化ファイルのサポートは終了しました

Android 9 では、Android セキュア暗号化ファイル(ASEC)のサポートは完全に削除されています。

Android 2.2(API レベル 8)では、SD カード上のアプリ機能をサポートする ASEC が導入されました。Android 6.0(API レベル 23)では、デベロッパーが ASEC の代わりに使用できる Adoptable Storage デバイス技術がプラットフォームに導入されました。

ICU ライブラリの更新

Android 9 は、ICU ライブラリのバージョン 60 を使用します。Android 8.0(API レベル 26)と Android 8.1(API レベル 27)では、ICU 58 を使用します。

ICU は、android.icu package の下で公開 API を提供するために使用され、多言語化をサポートするために Android プラットフォームの内部で使用されます。たとえば、java.utiljava.textandroid.text.format で Android クラスを実装するために使用されます。

ICU 60 のアップデートには、絵文字 5.0 データのサポートや改善された日時形式など、小規模ながら有用な変更が多数含まれています(ICU 59 と ICU 60 のリリースノートを参照)。

今回のアップデートの重要な変更点:

  • プラットフォームによるタイムゾーンの処理方法が変更されました。
    • プラットフォームでは、GMT と UTC の処理が改善されており、UTC は GMT の同義語ではなくなりました。

      ICU では、GMT と UTC の翻訳されたゾーン名が提供されるようになりました。この変更は、「GMT」、「Etc/GMT」、「UTC」、「Etc/UTC」、「Zulu」などのゾーンの android.icu の形式と解析動作に影響します。

    • java.text.SimpleDateFormat は ICU を使用して UTC /GMT の表示名を提供するようになりました。つまり、以下を意味します。
      • zzzz とフォーマットすると、多くの言語 / 地域向けにローカライズされた長い文字列が生成されます。これまでは、UTC には「UTC」、GMT には「GMT+00:00」のような文字列が生成されていました。
      • zzzz の解析では、「協定世界時」や「グリニッジ標準時」などの文字列が認識されます。
      • すべての言語で zzzz が「UTC」または「GMT+00:00」を出力すると想定していると、アプリで互換性の問題が発生する可能性があります。
    • java.text.DateFormatSymbols.getZoneStrings() の動作が次のように変更されました。
      • SimpleDateFormat と同様に、UTC と GMT には長い名前が付けられています。「UTC」、「Etc/UTC」、「Zulu」など、UTC ゾーンのタイムゾーン名の DST バリアントは、GMT+00:00 になります。これは、ハードコードされた文字列 UTC ではなく、利用可能な名前がない場合の標準的なフォールバックです。
      • 一部のゾーン ID は他のゾーンの同義語として正しく認識されるため、Android は、以前は解決できなかった古いゾーン ID(Eire など)の文字列を検出します。
    • アジア/ハノイは、認識されなくなったゾーンではなくなりました。このため、java.util.TimeZones.getAvailableIds() はこの値を返さず、java.util.TimeZone.getTimeZone() はこの値を認識しません。この動作は、既存の android.icu の動作と整合しています。
  • android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String) メソッドは、正規の通貨テキストを解析している場合でも ParseException をスローすることがあります。この問題を回避するには、Android 7.0(API レベル 24)以降で利用可能な NumberFormat.parseCurrencyPLURALCURRENCYSTYLE スタイルの通貨テキストに使用します。

Android Test の変更

Android 9 では、Android テスト フレームワークのライブラリとクラス構造にいくつかの変更が加えられています。これらの変更により、デベロッパーはフレームワークでサポートされている公開 API を使用できるようになりますが、サードパーティのライブラリやカスタム ロジックを使用したテストのビルドと実行の柔軟性も向上します。

フレームワークから削除されたライブラリ

Android 9 では、JUnit ベースのクラスが android.test.baseandroid.test.runnerandroid.test.mock の 3 つのライブラリに再編成されています。この変更により、プロジェクトの依存関係で最適に機能する JUnit のバージョンに対してテストを実行できるようになりました。このバージョンの JUnit は、android.jar が提供するものとは異なる場合があります。

JUnit ベースのクラスがこれらのライブラリに整理される仕組みと、テストの作成と実行のためにアプリのプロジェクトを準備する方法の詳細については、Android Test 用にプロジェクトをセットアップするをご覧ください。

テストスイートのビルド変更

TestSuiteBuilder クラスの addRequirements() メソッドが削除され、TestSuiteBuilder クラス自体のサポートが終了しました。addRequirements() メソッドでは、デベロッパーは API の型が非表示の引数を指定する必要があり、API が無効になっていました。

Java UTF デコーダ

UTF-8 は Android のデフォルト文字セットです。UTF-8 バイト シーケンスは、String(byte[] bytes) などの String コンストラクタでデコードできます。

Android 9 の UTF-8 デコーダは、以前のバージョンよりも Unicode 標準に厳密に準拠しています。変更内容は次のとおりです。

  • <C0, AF> などの UTF-8 の最短形式でないものは、不正な形式として扱われます。
  • UTF-8 のサロゲート形式(U+D800..U+DFFF など)は、不適切な形式として扱われます。
  • 最大のサブパートは 1 つの U+FFFD に置き換えられます。たとえば、バイト シーケンス「41 C0 AF 41 F4 80 80 41」の最大のサブパートは「C0」、「AF」、「F4 80 80」です。「F4 80 80」は「F4 80 80 80」の最初のサブシーケンスにできますが、「C0」を正しい形式のコード単位シーケンスの初期サブシーケンスにすることはできません。出力は「A\ufffd\ufffdA\ufffdA」になります。
  • Android 9 以降で変更された UTF-8 / CESU-8 シーケンスをデコードするには、DataInputStream.readUTF() メソッドまたは NewStringUTF() JNI メソッドを使用します。

証明書を使用したホスト名の検証

RFC 2818 には、ドメイン名を証明書と照合するための 2 つの方法が記述されています。1 つは subjectAltNameSAN)拡張内で使用可能な名前を使用する方法で、もう 1 つは commonNameCN)にフォールバックする SAN 拡張がない場合です。

ただし、CN へのフォールバックは RFC 2818 で非推奨になりました。このため、Android は CN の使用にフォールバックしなくなりました。ホスト名を確認するには、サーバーは SAN が一致する証明書を提示する必要があります。ホスト名に一致する SAN を含まない証明書は信頼されなくなります。

ネットワーク アドレスのルックアップによってネットワーク違反が発生することがある

名前解決が必要なネットワーク アドレスのルックアップでは、ネットワーク I/O が関係する場合があるため、ブロッキング オペレーションと見なされます。メインスレッドでブロッキング オペレーションを行うと、一時停止やジャンクが発生する可能性があります。

StrictMode クラスは、デベロッパーがコード内の問題を検出できるようにする開発ツールです。

Android 9 以降では、StrictMode は名前解決が必要なネットワーク アドレス ルックアップによるネットワーク違反を検出します。

StrictMode を有効にしてアプリをリリースしないでください。追加すると、detectNetwork() メソッドまたは detectAll() メソッドを使用してネットワーク違反を検出するポリシーを取得したときに、アプリで NetworkOnMainThreadException などの例外が発生する可能性があります。

数値 IP アドレスの解決はブロッキング オペレーションとは見なされません。数値 IP アドレスの解決は、Android 9 より前のバージョンと同じように機能します。

ソケットのタグ付け

Android 9 より前のプラットフォーム バージョンでは、setThreadStatsTag() メソッドを使用してソケットにタグが付けられている場合、ParcelFileDescriptor コンテナでバインダ IPC を使用して別のプロセスに送信されると、ソケットはタグ付けされません。

Android 9 以降では、バインダ IPC を使用してソケットタグが別のプロセスに送信された場合でも、ソケットタグは保持されます。この変更は、queryDetailsForUidTag() メソッドを使用する場合など、ネットワーク トラフィックの統計情報に影響する可能性があります。

前のバージョンの動作(別のプロセスに送信されたソケットのタグを解除する)を保持する場合は、ソケットを送信する前に untagSocket() を呼び出します。

ソケット内の使用可能なバイト数を報告しました

available() メソッドは、shutdownInput() メソッドを呼び出した後に呼び出されると 0 を返します。

VPN のネットワーク機能のより詳細なレポート

Android 8.1(API レベル 27)以前では、NetworkCapabilities クラスは VPN に関する限られた情報セット(TRANSPORT_VPN など)のみをレポートし、NET_CAPABILITY_NOT_VPN は省略していました。情報が限定されていたため、VPN を使用するとアプリのユーザーに課金されるかどうかを判断するのが困難でした。たとえば、NET_CAPABILITY_NOT_METERED を確認しても、基盤となるネットワークが従量制であるかどうかを判断できません。

Android 9 以降では、VPN が setUnderlyingNetworks() メソッドを呼び出すと、Android システムは基盤となるネットワークのトランスポートと機能をマージし、その結果を VPN ネットワークの有効なネットワーク機能として返します。

Android 9 以降では、すでに NET_CAPABILITY_NOT_METERED をチェックしているアプリは、VPN と基盤となるネットワークのネットワーク機能を受け取ります。

xt_qtaguid フォルダ内のファイルをアプリで利用できなくなりました

Android 9 以降では、アプリは /proc/net/xt_qtaguid フォルダ内のファイルに直接アクセスできません。これは、このようなファイルを一切持たないデバイスとの整合性を確保するためです。

これらのファイルに依存する公開 API(TrafficStatsNetworkStatsManager)は、引き続き意図したとおりに機能します。ただし、サポートされていない cutils 関数(qtaguid_tagSocket() など)は、デバイスによっては想定どおりに動作しない場合があります。

FLAG_ACTIVITY_NEW_TASK 要件が適用されました

Android 9 では、インテント フラグ FLAG_ACTIVITY_NEW_TASK を渡さない限り、アクティビティ以外のコンテキストからアクティビティを開始することはできません。このフラグを渡さずにアクティビティを起動しようとすると、アクティビティは開始せず、ログにメッセージが出力されます。

画面の回転の変更

Android 9 以降、縦向きの回転モードに大きな変更があります。Android 8.0(API レベル 26)では、QuickSettings タイルまたはディスプレイ設定を使用して、自動回転縦向きの回転モードを切り替えることができました。縦向きモードは回転ロックという名称に変更されました。このモードは、自動回転をオフに切り替えるとアクティブになります。自動回転モードに変更はありません。

デバイスが回転ロックモードのとき、ユーザーは上部に表示されているアクティビティでサポートされている任意の回転に画面をロックできます。アクティビティが常に縦向きに表示されるとは限りません。一番上のアクティビティを自動回転モードで複数の回転でレンダリングできる場合は、回転ロックモードでも同じオプションを使用できますが、アクティビティの screenOrientation 設定に基づいて例外があります(以下の表を参照)。

特定の向きをリクエストするアクティビティ(screenOrientation=landscape など)はユーザーのロック設定を無視し、Android 8.0 と同じように動作します。

画面の向きの設定は、Android マニフェストでアクティビティ レベルで設定することも、setRequestedOrientation() を使用してプログラムで設定することもできます。

回転ロックモードは、WindowManager がアクティビティの回転を処理するときに使用するユーザーの回転設定を指定することで機能します。ユーザーのローテーション設定は、次のような場合に変更されることがあります。デバイスの自然な回転に戻すバイアスがあります。これは通常、スマートフォンのフォーム ファクタ デバイスでは縦向きです。

  • ユーザーが回転の提案を承認すると、回転設定は提案に変わります。
  • 強制縦向きアプリ(ロック画面またはランチャーを含む)に切り替えると、回転設定が縦向きに変わります。

次の表は、一般的な画面の向きでの回転動作をまとめたものです。

画面の向き 動作
指定なし、ユーザー 自動回転と回転ロックでは、アクティビティを縦向きまたは横向き(およびその逆)にレンダリングできます。縦向きと横向きの両方のレイアウトをサポートすることが想定されます。
userLandscape 自動回転と回転ロックでは、アクティビティを横向きまたは逆の横向きにレンダリングできます。横向きのレイアウトのみがサポートされます。
ユーザーポートレート 自動回転と回転ロックでは、アクティビティを縦向きまたは逆の縦向きにレンダリングできます。縦向きのレイアウトのみがサポートされます。
フルユーザー 自動回転と回転ロックでは、アクティビティを縦向きまたは横向き(およびその逆)にレンダリングできます。縦向きと横向きの両方のレイアウトをサポートすることが想定されています。

回転をロックするユーザーには、逆の縦向き(多くの場合 180 度)にロックするオプションが表示されます。
sensor、fullSensor、sensorPortrait、sensorLandscape 回転ロックモードの設定は無視され、自動回転が有効であるかのように扱われます。UX について慎重に検討が必要な例外的な状況でのみ使用してください。

Apache HTTP クライアントの非推奨が、標準以外の ClassLoader を使用するアプリに影響する

Android 6.0 で、Apache HTTP クライアントのサポートが削除されました。この変更は、Android 9 以降をターゲットとしていない大部分のアプリには影響しません。ただし、標準以外の ClassLoader 構造を使用する特定のアプリは、Android 9 以降をターゲットとしていなくても、影響を受ける可能性があります。

システムの ClassLoader に明示的に委任された標準以外の ClassLoader をアプリが使用している場合、影響を受ける可能性があります。このようなアプリは、org.apache.http.* でクラスを検索するときに、代わりにアプリ ClassLoader にデリゲートする必要があります。Android 9 以降では、アプリがシステムの ClassLoader にデリゲートすると、NoClassDefFoundError で失敗します。これは、これらのクラスがシステムの ClassLoader に認識されなくなるためです。今後同様の問題が発生しないよう、アプリは一般的に、システムの ClassLoader に直接アクセスするのではなく、アプリの ClassLoader を使用してクラスを読み込む必要があります。

カメラの列挙

Android 9 デバイスで動作するアプリは、getCameraIdList() を呼び出すことで、利用可能なすべてのカメラを検出できます。デバイスに背面カメラが 1 つしかない、または前面カメラが 1 つしかないことをアプリで想定すべきではありません。

たとえば、アプリに前面カメラと背面カメラを切り替えるボタンがある場合、複数の前面カメラまたは背面カメラを選択できます。カメラリストを確認し、各カメラの特性を調べて、ユーザーに公開するカメラを決定する必要があります。