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

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

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

ユーザー エクスペリエンス

オーバースクロール効果

Android 12 では、オーバースクロール イベントの動作が変更されています。詳しくは、オーバースクロール効果をご覧ください。

フォアグラウンド サービスの通知の UX の遅延

Android 12 では、短時間実行されるフォアグラウンド サービスのエクスペリエンスを簡素化するため、特定のフォアグラウンド サービスについて、システムはフォアグラウンド サービス通知の表示を 10 秒間遅らせることができます。この変更により、通知が表示される前に存続時間の短いタスクを完了する機会が与えられます。

フォアグラウンド サービスに次の特性の少なくとも 1 つがある場合、サービスが開始されるとすぐに、関連する通知が表示されます。

  • サービスがアクション ボタンを含む通知に関連付けられている。
  • サービスの foregroundServiceTypemediaPlaybackmediaProjection、または phoneCall である。
  • サービスが、通知の category 属性の定義に応じて、通話、ナビゲーション、またはメディア再生に関連するユースケースを提供している。
  • サービスが、通知の設定時に FOREGROUND_SERVICE_IMMEDIATEsetForegroundServiceBehavior() に渡すことで、動作変更をオプトアウトしている。

ジェスチャー ナビゲーションの没入モードの改善

Android 12 では、没入モードが簡素化されてジェスチャー ナビゲーションがより簡単になりました。また、動画の視聴や書籍の閲覧といった他のアクティビティのエクスペリエンスとの一貫性が向上しました。詳細については、機能のページで該当するエントリをご覧ください。

ウェブ インテントの解決

Android 12 では、ユーザーがウェブリンクを選択するときのエクスペリエンスを簡素化するために、特定のウェブ インテントに未承認のドメインが含まれている場合、そのインテントをユーザーのデフォルト ブラウザで開きます。アプリは次のいずれかの方法でドメインの承認を得られます。

  • Android アプリリンクを使用してドメインを検証する。
  • アプリをドメインに関連付けるようユーザーに依頼する。

アプリがウェブ インテントを呼び出す場合は、ユーザーにアクションの確認を求めるプロンプトまたはダイアログを追加することをご検討ください。

詳細については、ウェブ インテントの解決に対する変更点をご覧ください。

アプリ スタンバイ バケットの制限

アプリ スタンバイ バケットは、システムがアプリのリソース リクエストに対し、アプリの最終利用時刻と使用頻度に基づいて優先順位付けするために使用されます。

各バケットは優先度を表します。優先度が低いと、システムがアプリの実行に課す制限が多くなります。

Android 12 以降、制限付き(restricted)というバケットが追加されました。制限付きバケットは、すべてのバケットの中で、優先度が最も低い(かつ制限が最も多い)バケットです。バケットを優先度の高いものから低いものの順に示すと次のようになります。

  1. アクティブ(active): 現在使用されている、またはごく最近使用されたアプリ
  2. ワーキング セット(working set): 定期的に使用されているアプリ
  3. 高頻度(frequent): 毎日ではないが、よく使用されるアプリ
  4. 低頻度(rare): あまり使用されないアプリ
  5. 制限付き(restricted)

システムは、使用パターンだけでなくアプリの動作も考慮して、アプリを制限付きバケットに配置するかどうかを判断します。アプリがシステム リソースを厳重に使用するのであれば、制限付きバケットに配置される可能性は低くなります。

ユーザーがアプリを直接操作する場合、アプリは制限の少ないバケットに配置されます。

電源管理に関する制限

アプリが制限付きバケットに配置された場合、次の制限が適用されます。

  • 1 日に 1 回、10 分間のバッチ セッションでジョブを実行できます。このセッションでは、アプリのジョブが他のアプリのジョブとグループ化されます。
  • 制限の少ないバケットに配置された場合に比べて、アプリが実行できる優先ジョブが少なくなります。
  • アプリの不正確なアラームが 1 日に 1 回配信されます。set()setInexactRepeating()setAndAllowWhileIdle()、または setWindow() メソッドを呼び出すと、不正確なアラームが作成されます。
  • アプリは優先度の高い Firebase Cloud Messaging(FCM)メッセージを 1 日 5 回、適時に受け取ることができます。それ以降の FCM メッセージは標準の優先度で配信されるため、デバイスが省電力モードになっている場合はメッセージが遅れることがあります。

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

制限付きバケットに配置されても、アプリは引き続きフォアグラウンド サービスを実行できます。ただし、アプリが Android 12 をターゲットとしている場合は、引き続きフォアグラウンド サービスの起動に関する制限の影響を受けます。

アプリが制限付きバケットに配置されているかどうかを確認する

アプリが制限付きバケットに配置されているかどうかを確認するには、getAppStandbyBucket() を呼び出します。このメソッドの戻り値が STANDBY_BUCKET_RESTRICTED の場合、アプリは制限付きバケットに配置されています。

制限付きバケットの動作をテストする

アプリが制限付きバケットに配置されたときの動作をテストする場合は、アプリをそのバケットに手動で移動できます。そのためには、ターミナル ウィンドウで次のコマンドを実行します。

adb shell am set-standby-bucket PACKAGE_NAME restricted

Display#getRealSize と getRealMetrics: 非推奨とサンドボックス化

Android デバイスには、大画面、タブレット、折りたたみ式など、さまざまなフォーム ファクタがあります。各デバイスでコンテンツを適切にレンダリングするには、アプリで画面またはディスプレイのサイズを判断する必要があります。Android では、この情報を取得するためのさまざまな API が提供されてきました。Android 11 では WindowMetrics API が導入され、以下のメソッドが非推奨となりました。

Android 12 では引き続き WindowMetrics の使用を推奨し、以下のメソッドが非推奨となっています。

Display API を使用してアプリの境界を取得する動作を軽減するために、Android 12 ではこうした API から返される情報を修正する新しいサンドボックス メカニズムが追加されました。これにより、MediaProjection でこの情報を使用しているアプリに影響が出る可能性があります。

アプリは、WindowMetrics API を使用してウィンドウの境界をクエリし、Configuration.densityDpi を使用して現在の密度をクエリする必要があります。

旧バージョンの Android との互換性を高めるために、Android 4.0(API レベル 14)以降をサポートする WindowMetrics クラスが含まれる、Jetpack WindowManager ライブラリを使用できます。

WindowMetrics の使用方法の例

まず、アプリのアクティビティが完全にサイズ変更可能であることを確認します。

アクティビティは、UI 関連の処理(特に WindowManager.getCurrentWindowMetrics())では、アクティビティ コンテキストの WindowMetrics に依存する必要があります。

アプリで MediaProjection を作成する場合は、プロジェクションがディスプレイをキャプチャするため、境界を正しいサイズにする必要があります。アプリが完全にサイズ変更可能な場合、アクティビティ コンテキストは次のように正しい境界を返します。

WindowMetrics projectionMetrics = activityContext
        .getSystemService(WindowManager.class).getMaximumWindowMetrics();

アプリが完全にサイズ変更可能ではない場合は、WindowContext インスタンスから境界をクエリし、WindowManager.getMaximumWindowMetrics() を使用してアプリで利用可能な最大表示領域の WindowMetrics を取得する必要があります。

Context windowContext = mContext.createWindowContext(mContext.getDisplay(),
        TYPE_APPLICATION, null /* options */);
WindowMetrics projectionMetrics = windowContext.getWindowManager()
        .getMaximumWindowMetrics();

グラフィックと画像

リフレッシュ レートの切り替えの改善

Android 12 では、ディスプレイが新しいリフレッシュ レートへのシームレスな移行をサポートするかどうかにかかわらず、setFrameRate() を使用してリフレッシュ レートを変更できます。シームレスな移行とは、画面が 1~2 秒黒くなるなどの視覚的な中断がないことを指します。これまでは、ディスプレイがシームレスな移行をサポートしていない場合、setFrameRate() が呼び出された後も通常は同じリフレッシュ レートを使用し続けていました。getAlternativeRefreshRates() を呼び出すことで新しいリフレッシュ レートへの移行がシームレスに行われるかどうかを事前に判断できます。一般に、コールバック onDisplayChanged() はリフレッシュ レートの切り替えが終わった後に呼び出されますが、一部の外部接続ディスプレイでは、シームレスでない移行の間に呼び出されます。

実装例を次に示します。

Kotlin

// Determine whether the transition will be seamless.
// Non-seamless transitions may cause a 1-2 second black screen.
val refreshRates = this.display?.mode?.alternativeRefreshRates
        val willbeSeamless = Arrays.asList<FloatArray>(refreshRates).contains(newRefreshRate)

// Set the frame rate even if the transition will not be seamless.
surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS)

Java

// Determine whether the transition will be seamless.
// Non-seamless transitions may cause a 1-2 second black screen.
Display display = context.getDisplay(); // API 30+
Display.Mode mode = display.getMode();
float[] refreshRates = mode.getAlternativeRefreshRates();
boolean willbeSeamless = Arrays.asList(refreshRates).contains(newRefreshRate);

// Set the frame rate even if the transition will not be seamless.
surface.setFrameRate(newRefreshRate, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, CHANGE_FRAME_RATE_ALWAYS);

セキュリティとプライバシー

マイクとカメラの切り替え

「カメラへのアクセス」、「マイクへのアクセス」というラベルが付いたクイック設定タイル。
図 1. クイック設定でのマイクとカメラの切り替え

Android 12 では、サポートされているデバイスで切り替えオプションを 1 回押すだけで、デバイス上のすべてのアプリに対してカメラとマイクへのアクセスを有効または無効にできます。ユーザーは図 1 に示すように、クイック設定から、またはシステム設定の [プライバシー] 画面から、切り替えオプションにアクセスできます。

カメラとマイクの切り替えは、デバイス上のすべてのアプリに影響します。

  • ユーザーがカメラへのアクセスをオフにすると、アプリは空のカメラフィードを受け取ります。
  • ユーザーがマイクへのアクセスをオフにすると、アプリはサイレント オーディオを受け取ります。また、HIGH_SAMPLING_RATE_SENSORS 権限を宣言しているかどうかにかかわらず、モーション センサーはレート制限されます。

ユーザーがカメラまたはマイクへのアクセスをオフにしてから、カメラまたはマイクの情報にアクセスする必要があるアプリを起動すると、システムからユーザーに対し、デバイス全体の切り替えがオフになっていることが通知されます。

特定のデバイスがマイクとカメラの切り替えをサポートしているかどうかを確認する

デバイスがマイクとカメラの切り替えをサポートしているかどうかを確認するには、次のコード スニペットに示すロジックを追加します。

Kotlin

val sensorPrivacyManager = applicationContext
        .getSystemService(SensorPrivacyManager::class.java)
        as SensorPrivacyManager
val supportsMicrophoneToggle = sensorPrivacyManager
        .supportsSensorToggle(Sensors.MICROPHONE)
val supportsCameraToggle = sensorPrivacyManager
        .supportsSensorToggle(Sensors.CAMERA)

Java

SensorPrivacyManager sensorPrivacyManager = getApplicationContext()
        .getSystemService(SensorPrivacyManager.class);
boolean supportsMicrophoneToggle = sensorPrivacyManager
        .supportsSensorToggle(Sensors.MICROPHONE);
boolean supportsCameraToggle = sensorPrivacyManager
        .supportsSensorToggle(Sensors.CAMERA);

マイクとカメラの切り替えに応じてアプリの動作を確認する

マイクとカメラの切り替えは、Android の権限に関するおすすめの方法に沿っている限り、アプリが CAMERARECORD_AUDIO の権限を処理する方法に影響しません。

具体的には、次のようにしてください。

  • ユーザーがアプリに CAMERA 権限を付与するまで、デバイスのカメラにアクセスしない。
  • ユーザーがアプリに RECORD_AUDIO 権限を付与するまで、デバイスのマイクにアクセスしない。

マイクとカメラのインジケーター

右上隅に角の丸い長方形があり、その中にカメラアイコンとマイクアイコンがある
図 2. 最近のデータアクセスが表示されるマイクとカメラのインジケーター。

Android 12 を搭載しているデバイスでは、アプリがマイクまたはカメラにアクセスすると、ステータスバーにアイコンが表示されます。アプリが没入モードの場合は、画面の右上にアイコンが表示されます。ユーザーはクイック設定を開き、アイコンを選択することで、現在どのアプリがマイクまたはカメラを使用しているのかを確認できます。図 2 に、アイコンを含むスクリーンショットの例を示します。

ユーザー エクスペリエンスを向上させるために、ユーザーがアプリに対して明示的に権限を付与するまで、マイクまたはカメラにアクセスしないでください。

アプリからシステム ダイアログを閉じるアクションが不可に

アプリとシステムを操作しているときのユーザー制御を改善するため、Android 12 では ACTION_CLOSE_SYSTEM_DIALOGS インテント アクションのサポートが終了しました。少数の特殊なケースを除いて、アプリがこのアクションを含むインテントの呼び出しを試みると、アプリのターゲット SDK バージョンに応じてシステムは次のいずれかを行います。

  • Android 12 をターゲットとするアプリの場合は、SecurityException をスローします。
  • Android 11(API レベル 30)以下をターゲットとするアプリの場合は、インテントを実行しません。logcat には次のメッセージが表示されます。

    E ActivityTaskManager Permission Denial: \
    android.intent.action.CLOSE_SYSTEM_DIALOGS broadcast from \
    com.package.name requires android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS, \
    dropping broadcast.
    

例外

次の場合、アプリは Android 12 で引き続きシステム ダイアログを閉じることができます。

  • アプリがインストルメンテーション テストを実行している。
  • アプリが Android 11 以下をターゲットとしており、通知ドロワーの上にウィンドウを表示している。

  • アプリが Android 11 以下をターゲットとしている。さらに、ユーザーが(おそらく通知のアクション ボタンを使用して)通知を操作し、アプリがそのユーザー アクションに応じてサービスまたはブロードキャスト レシーバを処理している。

  • アプリが Android 11 以前をターゲットとしており、ユーザー補助サービスが有効になっている。アプリが Android 12 をターゲットとし、通知バーを閉じる場合は、代わりに GLOBAL_ACTION_DISMISS_NOTIFICATION_SHADE ユーザー補助アクションを使用します。

信頼できないタッチイベントはブロックされる

システム セキュリティと優れたユーザー エクスペリエンスを維持するため、Android 12 は、オーバーレイが安全でない方法でアプリを覆い隠している場合にタッチイベントをアプリが使用することを許しません。つまり、少数の例外を除いて、特定のウィンドウをパススルーするタッチはシステムによってブロックされます。

影響を受けるアプリ

この変更は、たとえば FLAG_NOT_TOUCHABLE フラグを使用してタッチにウィンドウをパススルーさせているアプリに影響します。具体例の一部を以下に示します。

  • TYPE_APPLICATION_OVERLAY を使用し、FLAG_NOT_TOUCHABLE フラグを使用するウィンドウなど、SYSTEM_ALERT_WINDOW 権限を必要とするオーバーレイ。
  • FLAG_NOT_TOUCHABLE フラグを使用するアクティビティ ウィンドウ。

例外

次の場合は「パススルー」タッチが許可されます。

  • アプリ内の操作: アプリがオーバーレイを表示し、ユーザーがアプリを操作しているときにのみオーバーレイが表示されます。
  • 信頼済みのウィンドウ: 信頼済みのウィンドウの例の一部を次に示します。

  • 不可視のウィンドウ: ルートビューが GONE または INVISIBLE のウィンドウ。

  • 完全に透明なウィンドウ: alpha プロパティが 0.0 のウィンドウ。

  • 十分に透明なシステム アラート ウィンドウ: 不透明度の組み合わせの総和がタッチに対するシステムの最大隠蔽不透明度以下である場合、一連のシステム アラート ウィンドウは十分に透明であると見なされます。Android 12 ベータ版では、この最大不透明度は 0.8 です。この値は、今後のベータ版リリースで変更される可能性があります。

信頼できないタッチがブロックされたときに検出する

タッチ アクションがシステムによってブロックされると、logcat は次のメッセージを記録します。

Untrusted touch due to occlusion by PACKAGE_NAME

変更をテストする

Android 12 デベロッパー プレビュー 3 を搭載したデバイスでは、信頼できないタッチはデフォルトでブロックされます。信頼できないタッチを許可するには、ターミナル ウィンドウで次の adb コマンドを実行します。

# A specific app
adb shell am compat disable BLOCK_UNTRUSTED_TOUCHES com.example.app

# All apps
# If you'd still like to see a Logcat message warning when a touch would be
# blocked, use 1 instead of 0.
adb shell settings put global block_untrusted_touches 0

動作をデフォルト(信頼できないタッチがブロックされる)に戻すには、次のコマンドを実行します。

# A specific app
adb shell am compat reset BLOCK_UNTRUSTED_TOUCHES com.example.app

# All apps
adb shell settings put global block_untrusted_touches 2

権限パッケージの公開設定

Android 12 を搭載したデバイスでは、Android 11(API レベル 30)以降をターゲットとし、以下のいずれかのメソッドを呼び出すアプリは、他のアプリに対するアプリのパッケージの公開設定に基づいてフィルタされた結果セットを受け取ります。

Bouncy Castle の実装を削除

Android 12 では、すべての AES アルゴリズムを含め、これまで非推奨となっていた多数の暗号アルゴリズムの BouncyCastle 実装が削除されました。代わりに、システムはこれらのアルゴリズムの Conscrypt 実装を使用します。

次のいずれかに該当する場合、この変更はアプリに影響します。

  • アプリが 512 ビットの鍵サイズを使用する。Conscrypt はこの鍵サイズをサポートしていません。必要に応じて、異なる鍵サイズを使用するよう、アプリの暗号ロジックを更新します。
  • アプリが KeyGenerator で無効な鍵サイズを使用する。Conscrypt の KeyGenerator の実装では、BouncyCastle と比較して、鍵パラメータに対して追加の検証が行われます。たとえば、AES は 128 ビット、192 ビット、256 ビットの鍵しかサポートしていないため、Conscrypt では 64 ビットの AES 鍵を生成できません。

    BouncyCastle では無効なサイズの鍵を生成できますが、その鍵を Cipher で使用すると後で失敗します。Conscrypt は先に失敗します。

  • 12 バイト以外のサイズを使用して Galois/Counter Mode(GCM)暗号を初期化する。Conscrypt の GcmParameterSpec の実装では、NIST が推奨する 12 バイトの初期化が必要です。

クリップボードへのアクセスの通知

Android 12 では、アプリが getPrimaryClip() を呼び出して別のアプリから初めて ClipData にアクセスすると、トースト メッセージでユーザーにこのクリップボードへのアクセスを通知します。

トースト メッセージ内のテキストには、APP pasted from your clipboard. の形式が含まれます。

クリップの説明を取得するときメッセージが表示されない

アプリは、クリップボードにある現在のデータに関する情報を受け取るために、getPrimaryClipDescription() を呼び出すことがあります。アプリがこのメソッドを呼び出したとき、トースト メッセージは表示されません。

Android 12 では、このメソッドが強化され、次の詳細情報が検出されます。

接続

Passpoint の更新

Android 12 では、次の API が追加されています。

  • isPasspointTermsAndConditionsSupported(): 利用規約Passpoint 機能であり、ネットワーク デプロイにおいて、オープン ネットワークを使用する安全でないキャプティブ ポータルを安全な Passpoint ネットワークに置き換えることができます。利用規約への同意が必要な場合は、通知が表示されます。利用規約によって制限される Passpoint ネットワークを提案するアプリでは、まずこの API を呼び出して、デバイスが機能をサポートしていることを確認する必要があります。デバイスが機能をサポートしていない場合、このネットワークには接続できず、代替ネットワークまたはレガシー ネットワークを提案する必要があります。
  • isDecoratedIdentitySupported(): プレフィックス装飾でネットワークの認証を行う場合、装飾された ID プレフィックスにより、ネットワーク事業者はネットワーク アクセス識別子(NAI)を更新して、AAA ネットワーク内の複数のプロキシを経由して明示的なルーティングを行えます(詳細については RFC 7542 をご覧ください)。

    Android 12 では、PPS-MO 拡張の WBA 仕様に適合するようにこの機能が実装されています。装飾された ID を必要とする Passpoint ネットワークを提案するアプリでは、まずこの API を呼び出して、デバイスが機能をサポートしていることを確認する必要があります。デバイスが機能をサポートしていない場合、ID が装飾されず、ネットワークの認証が失敗する可能性があります。

Passpoint の提案を作成するには、アプリで PasspointConfigurationCredentialHomeSp クラスを使用する必要があります。これらのクラスは、Wi-Fi Alliance Passpoint 仕様で定義されている Passpoint プロファイルを記述します。

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

Android 12 では、Android デベロッパーの協力と直近の内部テストに基づいて、制限を受ける非 SDK インターフェースのリストが更新されています。Google は、非 SDK インターフェースを制限する前に、可能な限り、その代わりとなる公開インターフェースを利用可能にしています。

Android 12 をターゲットとしないアプリでは、この変更の一部はすぐには影響しない可能性があります。ただし、現時点で(アプリのターゲット API レベルに応じて)一部の非 SDK インターフェースを利用できていても、非 SDK のメソッドまたはフィールドをそのまま使用し続けると、将来的にアプリが機能しなくなるリスクが高くなります。

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

Android の今回のリリースの変更について詳しくは、非 SDK インターフェースの制限に関する Android 12 での変更点をご覧ください。非 SDK インターフェース全般について詳しくは、非 SDK インターフェースの制限をご覧ください。