Android 10 には、アプリに影響を与える可能性のある動作変更が含まれています。このページに記載されている変更は、アプリの targetSdkVersion
にかかわらず、Android 10 で実行されているアプリに適用されます。これらの変更に適切に対応するには、アプリをテストし、必要に応じて修正する必要があります。
アプリの targetSdkVersion が 29
以降の場合は、その他の変更にも対応する必要があります。詳しくは、29 をターゲットとするアプリの動作変更をご覧ください。
注: Android 10 では、このページに記載されている変更以外にも、以下のようなプライバシーに基づく多くの変更や制限が導入されています。
- デバイスの位置情報へのバックグラウンドでのアクセス
- バックグラウンドからのアクティビティの起動
- 連絡先アフィニティ情報
- MAC アドレスのランダム化
- カメラのメタデータ
- 権限モデル
これらの変更はすべてのアプリに影響し、ユーザーのプライバシーを強化します。これらの変更をサポートする方法について詳しくは、プライバシーの変更点のページをご覧ください。
非 SDK インターフェースの制限
アプリの安定性と互換性を確保するため、Android 9(API レベル 28)から、アプリで使用できる非 SDK インターフェースが制限されています。Android 10 では、Android デベロッパーの協力や最新の内部テストに基づいて、制限対象となる非 SDK インターフェースのリストが更新されています。Google は、非 SDK インターフェースを制限する前に、その代わりとなる公開インターフェースを利用できるようにすることを目指しています。
Android 10(API レベル 29)をターゲットとしないアプリの場合、変更点によっては、すぐに影響が生じないこともあります。ただし、現時点で(アプリのターゲット API レベルに応じて)一部の非 SDK インターフェースを利用できていても、非 SDK のメソッドまたはフィールドをそのまま使用し続けると、将来的にアプリが機能しなくなるリスクが高くなります。
アプリが非 SDK インターフェースを使用しているかどうか不明な場合は、アプリをテストして確認できます。アプリが非 SDK インターフェースに依存している場合は、SDK の代替インターフェースへの移行を計画してください。ただし Google も、一部のアプリには非 SDK インターフェースを使用する正当なユースケースがあると承知しています。現在のアプリの機能に使用している非 SDK インターフェースの代わりが見つからない場合は、新しい公開 API をリクエストしてください。
詳しくは、非 SDK インターフェースの制限に関する Android 10 での変更点と非 SDK インターフェースの制限についての記事をご覧ください。
ジェスチャー ナビゲーション
Android 10 以降、デバイス全体でジェスチャー ナビゲーションを有効にできます。ユーザーがジェスチャー ナビゲーションを有効にすると、アプリが API レベル 29 をターゲットにしているかどうかに関係なく、デバイス上のすべてのアプリが影響を受けます。たとえば、ユーザーが画面の端から内側にスワイプすると、アプリが画面の一部に対してそのジェスチャーを特別にオーバーライドしている場合を除き、システムはそのジェスチャーを「戻る」操作と解釈します。
アプリをジェスチャー ナビゲーションに対応させるには、アプリのコンテンツを画面全体に拡大し、競合するジェスチャーに適切に対処する必要があります。詳しくは、ジェスチャー ナビゲーションのドキュメントをご覧ください。
NDK
Android 10 では、NDK が次のように変更されています。
共有オブジェクトにテキストの再配置を含めることはできません
Android 6.0(API レベル 23)において、共有オブジェクト内でのテキストの再配置の使用が禁止されました。コードは現状のまま読み込まれ、変更してはなりません。この制限により、アプリの読み込み時間とセキュリティが改善されます。
Android 10 以降をターゲットとするアプリでは、この制限は、SELinux によって適用します。これらのアプリがテキストの再配置を含む共有オブジェクトの使用を続けると、動作できなくなる可能性が高くなります。
Bionic ライブラリと動的リンカーのパスの変更
Android 10 以降、一部のパスがシンボリック リンクになっています。これは通常のファイルではありません。パスが通常のファイルであることを当てにしてきたアプリは、動作できなくなる可能性があります。
/system/lib/libc.so
->/apex/com.android.runtime/lib/bionic/libc.so
/system/lib/libm.so
->/apex/com.android.runtime/lib/bionic/libm.so
/system/lib/libdl.so
->/apex/com.android.runtime/lib/bionic/libdl.so
/system/bin/linker
->/apex/com.android.runtime/bin/linker
これらの変更は 64 ビット版のファイルにも適用されます(lib/
を lib64/
で置き換えてください)。
互換性を維持するために、シンボリック リンクは古いパスで提供されます。たとえば、/system/lib/libc.so
は /apex/com.android.runtime/lib/bionic/libc.so
へのシンボリック リンクです。そのため、dlopen(“/system/lib/libc.so”)
は引き続き機能しますが、アプリが /proc/self/maps
などを読み取って読み込まれたライブラリを実際に調べようとすると、違いが見つかります。これは通常ではありませんが、一部のアプリではハッキング対策の一環としてこのような処理を行っていることがわかっています。このような場合、/apex/…
パスを Bionic ファイル用の有効なパスとして追加する必要があります。
システムのバイナリやライブラリを実行専用メモリにマッピング
Android 10 では、コード再利用攻撃を阻止する強化技術として、システムが提供するバイナリやライブラリの実行可能セグメントを実行専用の(読み取り不可の)メモリにマッピングします。実行専用としてマークされたメモリ セグメントへの読み取りをアプリが実行すると、バグまたは脆弱性によるものでも、意図的なメモリ インスペクションでも、SIGSEGV
シグナルがそのアプリに送信されます。
この動作がクラッシュを発生させたかどうかを特定するには、/data/tombstones/
内の関連する tombstone ファイルを調べます。実行専用メモリに関するクラッシュには、以下の中止メッセージが含まれています。
Cause: execute-only (no-read) memory access error; likely due to data in .text.
この問題を回避してメモリ インスペクションなどの操作を実行するために、mprotect()
を呼び出して実行専用セグメントを read+execute としてマークできますが、ただし、その後で実行専用に戻すよう設定することを強く推奨します。このアクセス権限の設定によって、アプリとユーザーの保護が強化されるからです。
セキュリティ
Android 10 では、セキュリティが次のように変更されています。
TLS 1.3 はデフォルトで有効
Android 10 以降、すべての TLS 接続に対して TLS 1.3 がデフォルトで有効になっています。TLS 1.3 実装に関する主な重要事項は以下のとおりです。
- TLS 1.3 暗号スイートはカスタマイズできません。TLS 1.3 が有効な場合、サポート対象の TLS 1.3 暗号スイートは常に有効です。
setEnabledCipherSuites()
を呼び出して無効にしようとしても無視されます。 - TLS 1.3 がネゴシエートされると、セッションがセッション キャッシュに追加される前に、
HandshakeCompletedListener
オブジェクトが呼び出されます。(TLS 1.2 以前のバージョンでは、このオブジェクトは、セッションがセッション キャッシュに追加されてから呼び出されます)。 - 以前のバージョンの Android では
SSLEngine
インスタンスによりSSLHandshakeException
がスローされる状況において、Android 10 以降では代わりにSSLProtocolException
がスローされます。 - 0-RTT モードはサポートされていません。
必要に応じて、TLS 1.3 が無効になっている SSLContext
を取得するには、SSLContext.getInstance("TLSv1.2")
を呼び出します。また、対象オブジェクトに対して setEnabledProtocols()
を呼び出すことで、接続ごとにプロトコル バージョンの有効と無効を切り替えることもできます。
SHA-1 で署名された証明書は TLS では信頼されない
Android 10 では、SHA-1 ハッシュ アルゴリズムが使用されている証明書は、TLS 接続では信用されません。2016 年以降、このような証明書はルート CA によって発行されていないため、Chrome などの主要ブラウザでは信頼されなくなりました。
SHA-1 を使用している証明書を提示するサイトへの接続はすべて失敗します。
KeyChain の動作変更と機能強化
Google Chrome など一部のブラウザでは、TLS サーバーが TLS ハンドシェイクの一部として証明書リクエスト メッセージを送信するときに、ユーザーが証明書を選択できます。Android 10 では、KeyChain.choosePrivateKeyAlias()
を呼び出してユーザーに証明書の選択を促すプロンプトを表示するときに、KeyChain
オブジェクトによって発行者と鍵の仕様パラメータが考慮されます。このプロンプトにはサーバー仕様に準拠しない選択肢は含まれません。
サーバーの仕様に一致する証明書がない場合や、デバイスに証明書がインストールされていない場合など、ユーザーが選択できる証明書がない場合は、証明書の選択を促すプロンプトは表示されません。
さらに、Android 10 以降では、鍵または CA 証明書を KeyChain
オブジェクトに読み込むためのデバイス画面ロックが不要です。
TLS と暗号化に関するその他の変更
Android 10 では、TLS と暗号化に対する小さな変更がいくつか有効になっています。
- AES/GCM/NoPadding および ChaCha20/Poly1305/NoPadding 暗号は、
getOutputSize()
からより正確なバッファサイズを返します。 - TLS 1.2 以降の最大プロトコルを使用した接続試行では、
TLS_FALLBACK_SCSV
暗号スイートが省略されます。TLS サーバーの実装が強化されているため、TLS 外部のフォールバックを試みることはおすすめしません。代わりに、TLS バージョン ネゴシエーションを使用することをおすすめします。 - ChaCha20-Poly1305 は、ChaCha20/Poly1305/NoPadding のエイリアスとして機能します。
- 末尾にピリオドが付いたホスト名は、有効な SNI ホスト名とは見なされません。
- 証明書応答用の署名キーを選択するとき、
CertificateRequest
の supported_signature_algorithms 拡張機能が尊重されます。 - Android Keystore の署名鍵など、不透明な署名鍵は TLS の RSA-PSS 署名で使用できます。
Wi-Fi Direct ブロードキャスト
Android 10 では、Wi-Fi Direct に関する以下のブロードキャストはスティッキーではありません。
この情報がスティッキーであったために、登録時にアプリがこれらのブロードキャストを受信することに依存していた場合は、その代わりとして、初期化時に適切な get()
メソッドを使用して情報を取得してください。
Wi-Fi Aware 機能
Android 10 では、Wi-Fi Aware データパスを使用して TCP/UDP ソケットを簡単に作成するためのサポートが追加されています。ServerSocket
に接続する TCP/UDP ソケットを作成するには、クライアント デバイスがサーバーの IPv6 アドレスとポートを認識している必要があります。そのためには、BT や Wi-Fi Aware のレイヤ 2 メッセージングなどを使用した帯域外での通信、または mDNS などの他のプロトコルを使用した帯域内での検出が必要でした。Android 10 では、ネットワーク設定の一環としてこの情報をやり取りすることができます。
サーバーは次のいずれかを実行します。
ServerSocket
を初期化し、使用するポートを設定または取得する。- Wi-Fi Aware ネットワーク リクエストの一部としてポート情報を指定する。
次のコードサンプルは、ネットワーク リクエストの一部としてポート情報を指定する方法を示しています。
Kotlin
val ss = ServerSocket() val ns = WifiAwareNetworkSpecifier.Builder(discoverySession, peerHandle) .setPskPassphrase("some-password") .setPort(ss.localPort) .build() val myNetworkRequest = NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(ns) .build()
Java
ServerSocket ss = new ServerSocket(); WifiAwareNetworkSpecifier ns = new WifiAwareNetworkSpecifier .Builder(discoverySession, peerHandle) .setPskPassphrase(“some-password”) .setPort(ss.getLocalPort()) .build(); NetworkRequest myNetworkRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI_AWARE) .setNetworkSpecifier(ns) .build();
次に、クライアントは Wi-Fi Aware ネットワーク リクエストを実行して、サーバーが提供した IPv6 とポートを取得します。
Kotlin
val callback = object : ConnectivityManager.NetworkCallback() { override fun onAvailable(network: Network) { ... } override fun onLinkPropertiesChanged(network: Network, linkProperties: LinkProperties) { ... } override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) { ... val ti = networkCapabilities.transportInfo if (ti is WifiAwareNetworkInfo) { val peerAddress = ti.peerIpv6Addr val peerPort = ti.port } } override fun onLost(network: Network) { ... } }; connMgr.requestNetwork(networkRequest, callback)
Java
callback = new ConnectivityManager.NetworkCallback() { @Override public void onAvailable(Network network) { ... } @Override public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) { ... } @Override public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) { ... TransportInfo ti = networkCapabilities.getTransportInfo(); if (ti instanceof WifiAwareNetworkInfo) { WifiAwareNetworkInfo info = (WifiAwareNetworkInfo) ti; Inet6Address peerAddress = info.getPeerIpv6Addr(); int peerPort = info.getPort(); } } @Override public void onLost(Network network) { ... } }; connMgr.requestNetwork(networkRequest, callback);
Go デバイス上の SYSTEM_ALERT_WINDOW
Android 10(Go バージョン)デバイスで実行されているアプリに SYSTEM_ALERT_WINDOW
権限を付与することはできません。これは、オーバーレイ ウィンドウの描画に大量のメモリが使用されるためです。メモリの少ない Android デバイスのパフォーマンスに悪影響をもたらす可能性があります。
Android 9 以前が実行されている Go デバイス上のアプリに SYSTEM_ALERT_WINDOW
権限が付与されている場合、そのデバイスが Android 10 にアップグレードされてもアプリの権限は保持されます。ただし、アプリに権限がない場合は、デバイスのアップグレード後に権限を付与することはできません。
Go デバイス上のアプリがアクション ACTION_MANAGE_OVERLAY_PERMISSION
を含むインテントを送信すると、システムは自動的にリクエストを拒否し、デバイスの動作が遅くなるため権限が付与されないことを示す [設定] 画面にユーザーを移動させます。Go デバイス上のアプリで Settings.canDrawOverlays()
を呼び出した場合、このメソッドからは常に false が返されます。繰り返しになりますが、デバイスが 10 にアップグレードされる前に SYSTEM_ALERT_WINDOW
権限が付与されたアプリにはこの制限は適用されません。
古いバージョンの Android をターゲットにしているアプリに関する警告
Android 10 以降では、Android 5.1(API レベル 22)以前をターゲットにしているアプリを初めて実行したときに、ユーザーに警告が表示されます。ユーザーに権限の付与を求めるアプリの場合、ユーザーは、アプリの初回実行を許可する前にアプリの権限を調整することができます。
Google Play のターゲット API 要件により、最近更新されていないアプリを実行しようとした場合に限りこのような警告が表示されます。他のアプリストアを通じて配信されているアプリについては、同様のターゲット API 要件が 2019 年中に有効になります。この要件について詳しくは、2019 年のターゲット API レベル要件の拡張をご覧ください。
SHA-2 CBC 暗号スイートの削除
以下の SHA-2 CBC 暗号スイートがプラットフォームから削除されました。
TLS_RSA_WITH_AES_128_CBC_SHA256
TLS_RSA_WITH_AES_256_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
これらの暗号スイートは GCM を使用する同様の暗号スイートより安全性が低く、ほとんどのサーバーでこれらの暗号スイートの GCM と CBC の両方のバリエーションがサポートされているか、両方ともサポートされていないかのどちらかです。
アプリの使用
Android 10 では、アプリの利用に関して次のように動作が変更されました。
UsageStats アプリの使用統計情報の改善 - <0x0また、Android 10 では、Instant App の使用状況も正しくトラッキングできます。
アプリ単位のグレースケール表示 - <0x0
アプリ単位の distraction state - <0
停止と再生 - <0x0
HTTPS 接続の変更
Android 10 で実行しているアプリが null
を setSSLSocketFactory()
に渡すと、IllegalArgumentException
が発生します。以前のバージョンでは、setSSLSocketFactory()
に null
を渡した場合、現在のデフォルト ファクトリを渡す場合と同じ効果がありました。
android.preference ライブラリのサポート終了
Android 10 では、android.preference
ライブラリのサポートが終了しています。デベロッパーは、Android Jetpack の一部である AndroidX Preference ライブラリを代わりに利用する必要があります。移行と開発をサポートするための参考情報として、更新済みの設定ガイドと、公開されているサンプルアプリおよびリファレンス ドキュメントをご確認ください。
ZIP ファイルのユーティリティ ライブラリの変更
Android 10 では、ZIP ファイルを処理する java.util.zip
パッケージのクラスに対して以下の変更が行われています。これらの変更により、java.util.zip
を使用する Android プラットフォームとその他のプラットフォーム間のライブラリの動作の一貫性が向上しています。
Inflater
以前のバージョンでは、end()
の呼び出し後に呼び出された場合、Inflater
クラスの一部のメソッドが IllegalStateException
をスローしていました。Android 10 では、これらのメソッドから NullPointerException
がスローされます。
ZipFile
Android 10 以降では、File
、int
、Charset
型の引数を取る ZipFile
のコンストラクタは、指定された ZIP ファイルにファイルが含まれていない場合でも ZipException
をスローしません。
ZipOutputStream
Android 10 以降では、ファイルを含まない ZIP ファイルの出力ストリームを書き込もうとしても、ZipOutputStream
の finish()
メソッドは ZipException
をスローしません。
カメラに関する変更点
カメラを使用するアプリの多くは、デバイスが縦向きの構成である場合は、物理的にもデバイスが縦向きになっていると想定します(カメラの向きを参照)。以前はこの想定で問題ありませんでしたが、折りたたみ式など使用可能なフォーム ファクタの拡大に伴い変化しています。これらのデバイスで同様の想定が行われると、カメラのビューファインダーの表示が不適切に回転したり、拡大したりする原因になる可能性があります。
API レベル 24 以上をターゲットとするアプリでは、明示的に android:resizeableActivity
を設定して、マルチウィンドウ操作を処理するために必要な機能を提供する必要があります。
電池使用量のトラッキング
Android 10 以降、SystemHealthManager
は、大きな充電イベントの後にデバイスのプラグが抜かれるたびに、電池使用量の統計情報をリセットします。主要な充電イベントとはつまり、デバイスが完全に充電されること、またはほとんど電池残量がない状態からほぼ完全に充電された状態になることです。
Android 10 より前は、電池残量がほとんど変化していなくても、デバイスのプラグを抜くと電池使用量の統計情報がリセットされていました。
Android ビームを削除
Android 10 では、近距離無線通信(NFC)を介してデバイス間でデータ共有を開始するための古い機能、Android ビームが正式に終了します。また、関連する NFC API もいくつか終了します。必要に応じて、デバイス メーカー パートナーがオプションで Android ビームを使用し続けることはできますが、開発は行われていません。ただし、他の NFC 機能と API については Android で引き続きをサポートされます。また、タグからの読み取り、支払いなどのユースケースは想定どおりに動作し続けます。
java.math.BigDecimal.stripTrailingZeros() の動作の変更
BigDecimal.stripTrailingZeros()
は、入力値がゼロの場合に、末尾のゼロを特別なケースとして保持しなくなりました。
java.util.regex.Matcher と Pattern の動作の変更
入力の先頭にゼロ幅の一致がある場合、split()
の結果が空の String
(「」)で始まらないように変更されました。これは String.split()
にも影響します。たとえば、以前のバージョンの Android では {"", "x"}
を返していた "x".split("")
は、現在は {"x"}
を返します。"aardvark".split("(?=a)"
が {"", "a", "ardv", "ark"}
ではなく {"a", "ardv", "ark"}
を返すようになりました。
無効な引数に対する例外の動作も改善されました。
- 置き換え
String
が単独のバックスラッシュで終わる場合(これは無効です)、appendReplacement(StringBuffer, String)
がIndexOutOfBoundsException
ではなくIllegalArgumentException
をスローするようになりました。置換String
が$
で終わる場合、同じ例外がスローされるようになりました。以前は、このシナリオで例外はスローされませんでした。 Matcher
がNullPointerException
をスローした場合、replaceFirst(null)
はMatcher
でreset()
を呼び出さなくなりました。一致するものがない場合にもNullPointerException
がスローされるようになりました。以前は、一致した場合にのみスローされていました。- グループ インデックスが範囲外の場合、
start(int group)
、end(int group)
、group(int group)
はより一般的なIndexOutOfBoundsException
をスローするようになりました。以前は、これらのメソッドはArrayIndexOutOfBoundsException
をスローしていました。
GradientDrawable のデフォルトの角度が TOP_BOTTOM になりました
Android 10 では、XML で GradientDrawable
を定義し、角度の測定値を指定しない場合、グラデーションの向きはデフォルトで TOP_BOTTOM
になります。以前のバージョンの Android では、デフォルトは LEFT_RIGHT
でした。
回避策として、AAPT2 の最新バージョンに更新すると、角度測定が指定されていない場合、ツールはレガシーアプリの角度測定を 0 に設定します。
デフォルトの SUID を使用したシリアル化オブジェクトのロギング
Android 7.0(API レベル 24)以降、プラットフォームでは、シリアル化可能なオブジェクトのデフォルトの serialVersionUID
の修正が行われました。この修正は、API レベル 23 以前をターゲットとするアプリには影響しませんでした。
Android 10 以降では、アプリが API レベル 23 以下をターゲットとし、古い誤ったデフォルトの serialVersionUID
に依存している場合、システムは警告をログに記録し、コードの修正を提案します。
具体的には、次のすべての条件を満たす場合に、システムは警告をログに記録します。
- アプリが API レベル 23 以前をターゲットにしている。
- クラスがシリアル化されます。
- シリアル化されたクラスは、
serialVersionUID
を明示的に設定するのではなく、デフォルトのserialVersionUID
を使用します。 - デフォルトの
serialVersionUID
は、アプリが API レベル 24 以上をターゲットとする場合のserialVersionUID
とは異なります。
この警告は、影響を受けるクラスごとに 1 回記録されます。警告メッセージには、serialVersionUID
を、アプリが API レベル 24 以降をターゲットとしている場合に計算されるデフォルト値に明示的に設定するという、推奨される修正が含まれています。この修正を使用すると、API レベル 23 以下をターゲットとするアプリでそのクラスのオブジェクトがシリアル化された場合、24 以上をターゲットとするアプリでそのオブジェクトが正しく読み取られるようになります。また、その逆も同様です。
java.io.FileChannel.map() の変更点
Android 10 以降、FileChannel.map()
は /dev/zero
のような非標準ファイルではサポートされません。非標準ファイルのサイズを truncate()
を使って変更することはできません。Android の以前のバージョンは、truncate()
から返される errno をそのままにしていましたが、Android 10 は IOException をスローします。以前の動作が必要な場合は、ネイティブ コードを使用してください。