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

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)では、共有オブジェクト内でのテキストの再配置の使用が禁止されました。コードはそのまま読み込む必要があり、変更しないでください。この制限により、アプリの読み込み時間とセキュリティが改善されます。

SELinux は、Android 10 以降をターゲットとするアプリにこの制限を適用します。これらのアプリがテキストの再配置を含む共有オブジェクトを引き続き使用すると、動作しなくなる可能性が高くなります。

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 モードはサポートされていません。

必要に応じて、SSLContext.getInstance("TLSv1.2") を呼び出すことで、TLS 1.3 が無効になっている SSLContext を取得できます。適切なオブジェクトに対して setEnabledProtocols() を呼び出すことで、接続ごとにプロトコル バージョンを有効または無効にすることもできます。

SHA-1 で署名された証明書は TLS では信頼されない

Android 10 では、SHA-1 ハッシュ アルゴリズムを使用する証明書は TLS 接続では信頼されません。2016 年以降、このような証明書はルート CA が発行していないため、Chrome などの主要なブラウザでは信頼されなくなりました。

SHA-1 を使用する証明書を提示するサイトへの接続はすべて失敗します。

KeyChain の動作変更と機能強化

Google Chrome などの一部のブラウザでは、TLS サーバーが TLS handshake の一環として証明書リクエスト メッセージを送信するときに、ユーザーが証明書を選択できます。Android 10 以降、KeyChain オブジェクトは、KeyChain.choosePrivateKeyAlias() を呼び出してユーザーに証明書の選択を促す際に、発行者と鍵仕様パラメータを尊重します。このプロンプトにはサーバー仕様に準拠しない選択肢は含まれません。

サーバー仕様に一致する証明書がない場合や、デバイスに証明書がインストールされていない場合など、ユーザーが選択できる証明書がない場合は、証明書の選択を促すメッセージは表示されません。

また、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 を返します。この場合も、デバイスが Android 10 にアップグレードされる前に SYSTEM_ALERT_WINDOW 権限が付与されたアプリにはこの制限は適用されません。

古いバージョンの Android をターゲットにしているアプリに関する警告

Android 10 以降を搭載したデバイスでは、Android 5.1(API レベル 22)以下をターゲットとするアプリを初めて実行したときに、ユーザーに警告が表示されます。ユーザーに権限を付与してもらう必要があるアプリでは、アプリの初回実行を許可する前に、ユーザーにアプリの権限を調整することもできます。

Google Play の対象 API 要件により、最近更新されていないアプリを実行したときにのみ、この警告が表示されます。他のストアを通じて配布されるアプリについても、2019 年にも同様の対象 API 要件が適用されます。これらの要件について詳しくは、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 アプリの使用状況の改善 - また、Android 10 では Instant App の使用状況が正しくトラッキングされます。

  • アプリごとのグレースケール -

  • アプリが

  • 一時停止と再生

HTTPS 接続の変更

Android 10 を実行するアプリが nullsetSSLSocketFactory() に渡すと、IllegalArgumentException が発生します。以前のバージョンでは、nullsetSSLSocketFactory() に渡した場合、現在のデフォルト ファクトリを渡す場合と同じ効果がありました。

android.preference ライブラリのサポート終了

android.preference ライブラリは Android 10 で非推奨になりました。代わりに、Android Jetpack の一部である AndroidX Preferences Library を使用してください。移行と開発に役立つ追加リソースについては、更新された設定ガイド公開されているサンプルアプリリファレンス ドキュメントをご覧ください。

ZIP ファイルのユーティリティ ライブラリの変更

Android 10 では、ZIP ファイルを処理する java.util.zip パッケージのクラスに次の変更が行われています。これらの変更により、Android と java.util.zip を使用する他のプラットフォームとの間で、ライブラリの動作の一貫性が保たれます。

Inflater

以前のバージョンでは、Inflater クラスの一部のメソッドが end() の呼び出し後に呼び出された場合、IllegalStateException をスローしていました。Android 10 では、これらのメソッドは代わりに NullPointerException をスローします。

ZipFile

Android 10 以降では、FileintCharset 型の引数を取る ZipFile のコンストラクタは、提供された ZIP ファイルにファイルが含まれていない場合、ZipException をスローしません。

ZipOutputStream

Android 10 以降では、ZipOutputStreamfinish() メソッドは、ファイルを含まない ZIP ファイルの出力ストリームを書き込もうとしても、ZipException をスローしません。

カメラに関する変更点

カメラを使用するアプリの多くは、カメラの向きで説明されているように、デバイスが縦向きになっている場合、物理デバイスも縦向きになっていると想定します。以前は安全な想定でしたが、折りたたみ式デバイスなどの使用可能なフォーム ファクタの拡大に伴い、この状況は変わりました。このようなデバイスでカメラのビューファインダーの表示が不適切に回転したり、拡大されたりすることがあります。

API レベル 24 以降をターゲットとするアプリでは、android:resizeableActivity を明示的に設定し、マルチウィンドウ オペレーションを処理するために必要な機能を提供する必要があります。

電池使用量のトラッキング

Android 10 以降では、SystemHealthManager大規模な充電イベントの後、デバイスを電源から外すたびにバッテリー使用量の統計情報をリセットします。大まかに言うと、主要な充電イベントは、デバイスがフル充電された、またはデバイスのほぼ充電された状態からほぼ充電された状態になった場合に発生します。

Android 10 より前では、電池残量がほとんど変化していなくても、デバイスを電源から外すたびに電池使用量の統計情報がリセットされていました。

Android ビームを削除

Android 10 では、近距離無線通信(NFC)を使用してデバイス間でデータ共有を開始する古い機能である Android ビームが正式に非推奨となります。また、関連する NFC API のいくつかも非推奨になります。Android ビームの使用を希望するデバイス メーカー パートナーは、引き続きオプションとして Android ビームを利用できますが、開発は終了しています。Android は他の NFC 機能と API を引き続きサポートし、タグからの読み取りや支払いなどのユースケースは引き続き想定どおりに機能します。

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$ で終了する場合、同じ例外がスローされるようになりました。以前は、このようなシナリオで例外はスローされませんでした。
  • replaceFirst(null)NullPointerException をスローした場合、Matcherreset() を呼び出さなくなりました。一致するものがない場合も、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 回記録されます。警告メッセージには推奨される修正が含まれています。これは、アプリが API レベル 24 以降をターゲットとしている場合に計算されるデフォルト値に serialVersionUID を明示的に設定するものです。この修正により、API レベル 23 以前をターゲットとするアプリでそのクラスのオブジェクトがシリアル化されている場合、API レベル 24 以上をターゲットとするアプリでオブジェクトが正しく読み取られるようになります(逆も同様です)。

java.io.FileChannel.map() の変更

Android 10 以降では、FileChannel.map()/dev/zero などの非標準ファイルではサポートされていません。非標準ファイルは truncate() を使用してサイズを変更できません。以前のバージョンの Android では、truncate() から返される errno を誤飲していましたが、Android 10 では IOException がスローされます。以前の動作が必要な場合は、ネイティブ コードを使用する必要があります。