Register now for Android Dev Summit 2019!

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

Android Q プラットフォームには、アプリに影響を与える可能性のある動作変更が含まれています。下記の動作変更は、targetSdkVersion に関係なく、Android Q 上で稼働するすべてのアプリに適用されます。該当する場合は、アプリをテストし、必要に応じて修正して、適切に対応する必要があります。

Android Q をターゲットにしているアプリにのみ影響する動作変更のリストについても必ずご確認ください。

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

アプリの安定性と互換性を確保するため、Android 9(API レベル 28)から、アプリで使用できる非 SDK インターフェースが制限されています。Android Q では、Android デベロッパーの協力や最新の内部テストに基づいて、制限対象となる非 SDK インターフェースのリストが更新されています。Google は、非 SDK インターフェースを制限する前に、その代わりとなる公開インターフェースを利用できるようにすることを目指しています。

Android Q をターゲットとしないアプリの場合、変更点によっては、すぐに影響が生じないこともあります。ただし、現時点ではグレーリストに記載されている非 SDK インターフェース(アプリの対象 API レベルによる)を利用できているとしても、そのまま非 SDK の手法やフィールドを使用し続けていると、将来的には高い確率でアプリが機能しなくなるおそれがあります。

アプリが非 SDK インターフェースを使用しているかどうか不明な場合は、アプリをテストして確認することができます。アプリが非 SDK インターフェースを使用している場合は、SDK インターフェースへの移行を計画するようにしてください。ただし Google も、一部のアプリには非 SDK インターフェースを使用する正当なユースケースがあると承知しています。現在のアプリの機能に使用している非 SDK インターフェースの代替となる SDK インターフェースが見つからない場合は、新しい公開 API をリクエストしてください。

詳しくは、非 SDK インターフェースの制限に関する Android Q での変更点非 SDK インターフェースの制限についての記事をご覧ください。

ジェスチャー ナビゲーション

Android Q 以降では、デバイス全体でジェスチャー ナビゲーションを有効にすることができます。ユーザーがジェスチャー ナビゲーションを有効にすると、アプリが Android Q をターゲットにしているかどうかに関係なく、デバイス上のすべてのアプリが影響を受けます。たとえば、ユーザーが画面の端から内側にスワイプすると、アプリが画面の一部に対してそのジェスチャーを特別にオーバーライドしている場合を除き、システムはそのジェスチャーを「戻る」の操作と解釈します。

アプリをジェスチャー ナビゲーションに対応させるには、アプリのコンテンツを画面全体に拡大し、競合するジェスチャーに適切に対処する必要があります。詳しくは、ジェスチャー ナビゲーションのドキュメントをご覧ください。

NDK

Android Q では、NDK に関して次のように変更されています。

共有オブジェクトにテキストの再配置を含めることはできません

Android 6.0(API レベル 23)において、共有オブジェクト内でのテキストの再配置の使用が禁止されました。コードは現状のまま読み込まれ、変更してはなりません。この制限により、アプリの読み込み時間とセキュリティが改善されます。

Android Q ベータ版の 1 と 2 では、Android 8.0(API レベル 26)以上をターゲットとするアプリに対して SELinux がこの制限を適用します。Android Q ベータ版 3 以降では、この制限が Android Q(API レベル 29)以上をターゲットとするアプリに適用されます。これらのアプリがテキストの再配置を含む共有オブジェクトの使用を続けると、動作できなくなる可能性が高くなります。

Bionic ライブラリと動的リンカーのパスの変更

Android Q 以降、一部のパスが通常のファイルではなくなり、シンボリック リンクになりました。パスが通常のファイルであることを当てにしてきたアプリは、動作できなくなる可能性があります。

  • /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 Q では、コード再利用攻撃を阻止する強化技術として、システムが提供するバイナリやライブラリの実行可能セグメントを、実行専用の(読み取り不可の)メモリにマッピングします。実行専用としてマークされたメモリ セグメントへの読み取りは、意図的かどうかを問わず、バグでも、脆弱性によるものでも、意図的なメモリ インストロペクションでも、SIGSEGV がスローされます。

クラッシュがこの変更によって発生したものかどうかを識別するには、/data/tombstones/ 内の関連する tombstone ファイルを調べます。実行専用メモリに関するクラッシュの場合、以下の中止メッセージが含まれています。

    Cause: execute-only (no-read) memory access error; likely due to data in .text.
    

この問題を回避するには、たとえばメモリ インスペクションを行うには、デベロッパーは mprotect() を呼び出して実行専用セグメントを read+execute にマークすることができます。ただし、その後で実行専用に戻すよう設定することを強く推奨します。この制限によってアプリとユーザーの保護が強化されるからです。

ptrace への呼び出しは影響を受けないので、ptrace デバッグには影響はありません。

セキュリティ

Android Q では、セキュリティに関する次の変更が行われています。

アプリのホーム ディレクトリに対する実行パーミッションの削除

Android Q をターゲットとする信頼できないアプリは、そのホーム ディレクトリ内のファイル上で exec() を呼び出せなくなりました。アプリの書き込み可能なホーム ディレクトリからファイルをこのように実行することは、W^X 違反です。アプリはその APK ファイル内に埋め込まれたバイナリコードのみ読み込むようにする必要があります。

さらに、Android Q をターゲットとするアプリは、dlopen() で読み込まれたファイルの実行可能コードをメモリ内で変更することはできません。これには、テキストの再配置を伴うすべての共有オブジェクト(.so)ファイルが含まれます。

Wi-Fi Direct ブロードキャスト

Android Q では Wi-Fi Direct に関する以下のブロードキャストがスティッキーではなくなりました。

これらのブロードキャストがスティッキーである前提で、登録時にこれらのブロードキャストを受信する仕様のアプリは、代わりに初期化時に適切な get() メソッドを使用して情報を取得するようにしてください。

Wi-Fi Aware 機能

Android Q では、Wi-Fi Aware データパスを使用して TCP / UDP ソケットを簡単に作成できるようにサポートが追加されています。ServerSocket に接続する TCP / UDP ソケットを作成するには、クライアント デバイスがサーバーの IPv6 アドレスとポートを認識している必要があります。そのためには、BT や Wi-Fi Aware のレイヤ 2 メッセージングなどを使用した帯域外での通信、または mDNS などの他のプロトコルを使用した帯域内での検出が必要でした。Android Q では、ネットワーク設定の一環としてこの情報をやり取りすることができます。

サーバーは次のいずれかを実行します。

  • 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 Q(Go バージョン)デバイス上で稼働するアプリに SYSTEM_ALERT_WINDOW 権限を付与することはできません。これは、オーバーレイ ウィンドウの描画に大量のメモリが使用されるためです。メモリの少ない Android デバイスのパフォーマンスに悪影響をもたらす可能性があります。

Android 9 以下を実行する Go デバイス上のアプリに SYSTEM_ALERT_WINDOW 権限が付与される場合、デバイスが Android Q にアップグレードされても、アプリはその権限を保持します。ただし、その権限をまだ持たないアプリには、デバイスのアップグレード後にその権限を付与することはできません。

Go デバイス上のアプリが ACTION_MANAGE_OVERLAY_PERMISSION アクションを含むインテントを送信しても、リクエストは自動的に拒否されます。ユーザーには [設定] 画面が表示され、デバイスの動作が遅くなるため、その権限は許可されないことが表示されます。Go デバイス上のアプリが Settings.canDrawOverlays() を呼び出した場合、このメソッドは常に false を返します。繰り返しになりますが、デバイスが Q にアップグレードされる前に SYSTEM_ALERT_WINDOW 権限が付与されたアプリには、この制限は適用されません。

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

Android Q では、Android 6.0(API レベル 23)以前のプラットフォーム バージョンをターゲットにしているアプリを初めて実行したときに、ユーザーに警告が表示されます。ユーザーに権限の付与を求めるアプリの場合、ユーザーは、アプリの初回実行を許可する前に、アプリの権限を調整することができます。

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 Q では、アプリの利用に関して次のように動作が変更されました。

  • UsageStats アプリの使用統計情報の改善 -- Android Q では、アプリが分割画面モードやピクチャー イン ピクチャー モードで使用された場合でも、UsageStats により、アプリの使用状況を正確にトラッキングできるようになりました。また、Android Q では、Instant App の使用状況もトラッキングできるようになりました。

  • アプリ単位のグレースケール表示 -- Android Q では、アプリをグレースケール表示モードに設定できるようになりました。

  • アプリ単位の distraction state -- Android Q ではアプリごとに "distraction state" に設定できるようになりました。この状態のアプリの通知は抑制され、おすすめのアプリとしてアプリが表示されることはなくなります。

  • 停止と再生 -- Android Q では、停止中のアプリはオーディオを再生できなくなりました。

HTTPS 接続の変更

Android Q で実行中のアプリが nullsetSSLSocketFactory() に渡す場合、IllegalArgumentException が発生するようになりました。以前のバージョンでは nullsetSSLSocketFactory() に渡すと、現在の出荷時のデフォルトを渡す場合と同じ結果になっていました。

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

android.preference ライブラリは現在サポートが終了しています。代わりにデベロッパーは Android Jetpack の一部である AndroidX Preference ライブラリをご利用ください。移行と開発をサポートする参考情報として、更新された設定ガイドのほか、公開されているサンプルアプリリファレンス ドキュメントもご確認ください。

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

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

Inflater

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

ZipFile

FileintCharset の各型の引数を受け取る ZipFile のコンストラクタが、提供された ZIP ファイルにファイルが含まれていなくても、ZipException をスローしなくなりました。

ZipOutputStream

ZipOutputStreamfinish() メソッドが、ファイルが含まれていない ZIP ファイルの出力ストリームを書き込もうとしても、ZipException をスローしなくなりました。

カメラに関する変更点

カメラを使用するアプリの多くは、デバイスが縦向きの構成である場合は、物理的にもデバイスが縦向きになっていると想定します(カメラの向きを参照)。以前はこの想定で問題ありませんでしたが、折りたたみ式などの新しいフォーム ファクタの導入によって変化しています。これらのデバイスで同様の想定が行われると、カメラのビューファインダーの表示が不適切に回転したり、拡大したりする原因になる可能性があります。

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

電池使用量の追跡

Android Q 以降では、主要な充電イベント後にデバイスのプラグを抜くと、SystemHealthManager によって電池使用量の統計情報がリセットされます。大まかに言うと、主要な充電イベントとはデバイスが完全に充電されること、またはほとんど電池残量がない状態からほぼ完全に充電された状態になることです。

Android Q より前は、電池残量がほとんど変化していなくても、デバイスのプラグを抜くと電池使用量の統計情報がリセットされていました。