動作の変更点: Android 15 以降をターゲットとするアプリ

以前のリリースと同様に、Android 15 にはアプリに影響する可能性のある動作変更が含まれています。以下の動作変更は、Android 15 以降をターゲットとするアプリにのみ適用されます。Android 15 以降をターゲットとするアプリについては、必要に応じてアプリを修正し、下記の動作に適切に対応できるようにしてください。

アプリの targetSdkVersion にかかわらず、Android 15 で実行されるすべてのアプリに影響する動作変更のリストも必ずご確認ください。

コア機能

Android 15 では、Android システムのさまざまなコア機能を変更または拡張しています。

フォアグラウンド サービスの変更

Android 15 では、フォアグラウンド サービスに次の変更が加えられます。

データ同期フォアグラウンド サービスのタイムアウト動作

Android 15 では、Android 15 以降をターゲットとするアプリ向けに、dataSync に新しいタイムアウト動作が導入されています。この動作は、新しい mediaProcessing フォアグラウンド サービス タイプにも適用されます。

システムは、アプリの dataSync サービスを 24 時間で合計 6 時間実行することを許可し、その後、実行中のサービスの Service.onTimeout(int, int) メソッド(Android 15 で導入)を呼び出します。この時点で、サービスが Service.stopSelf() を呼び出すために数秒かかります。Service.onTimeout() が呼び出されると、サービスはフォアグラウンド サービスと見なされなくなります。サービスが Service.stopSelf() を呼び出さないと、「<fgs_type> のフォアグラウンド サービスがタイムアウト内に停止しませんでした: <component_name>」というエラー メッセージが表示され、エラーが発生します。ベータ版 2 では、失敗メッセージは ANR として表示されますが、今後のベータ版リリースでは、カスタム例外がスローされます。

この動作変更による問題を回避するには、次のいずれかを行います。

  1. サービスに新しい Service.onTimeout(int, int) メソッドを実装させます。アプリがコールバックを受信したら、必ず数秒以内に stopSelf() を呼び出します。(アプリをすぐに停止しないと、エラーが発生します)。
  2. アプリの dataSync サービスが 24 時間で合計 6 時間以上実行されないようにします(ユーザーがアプリを操作してタイマーをリセットする場合を除く)。
  3. dataSync フォアグラウンド サービスは、ユーザーの直接操作の結果としてのみ開始してください。サービスの開始時にアプリがフォアグラウンドにあるため、サービスはアプリがバックグラウンドに移動してから 6 時間かかります。
  4. dataSync フォアグラウンド サービスを使用する代わりに、代替 API を使用します。

アプリの dataSync フォアグラウンド サービスが過去 24 日間に 6 時間実行されている場合、ユーザーがアプリをフォアグラウンドに移動した場合(タイマーがリセットされる)でない限り、別の dataSync フォアグラウンド サービスを開始することはできません。別の dataSync フォアグラウンド サービスを開始しようとすると、システムは ForegroundServiceStartNotAllowedException をスローし、「DataSync タイプのフォアグラウンド サービスの制限時間はすでに上限に達しています」などのエラー メッセージを返します。

新しいメディア処理フォアグラウンド サービス タイプ

Android 15 では、新しいフォアグラウンド サービス タイプである mediaProcessing が導入されています。このサービスタイプは、メディア ファイルのコード変換などのオペレーションに適しています。たとえば、メディアアプリで音声ファイルをダウンロードした後、再生する前に別の形式に変換しなければならない場合があります。mediaProcessing フォアグラウンド サービスを使用すると、アプリがバックグラウンドで実行されている場合でも変換を続行できます。

システムは、アプリの mediaProcessing サービスを 24 時間で合計 6 時間実行することを許可し、その後、実行中のサービスの Service.onTimeout(int, int) メソッド(Android 15 で導入)を呼び出します。この時点で、サービスが Service.stopSelf() を呼び出すために数秒かかります。サービスが Service.stopSelf() を呼び出さないと、「<fgs_type> のフォアグラウンド サービスがタイムアウト内に停止しませんでした: <component_name>」というエラー メッセージが表示され、エラーが発生します。ベータ版 2 では、失敗メッセージは ANR として表示されますが、今後のベータ版リリースでは、カスタム例外がスローされます。

ANR が発生しないようにするには、次のいずれかを行います。

  1. サービスに新しい Service.onTimeout(int, int) メソッドを実装させます。アプリがコールバックを受信したら、必ず数秒以内に stopSelf() を呼び出します。(アプリをすぐに停止しないと、エラーが発生します)。
  2. アプリの mediaProcessing サービスが 24 時間で合計 6 時間以上実行されないようにします(ユーザーがアプリを操作してタイマーをリセットする場合を除く)。
  3. mediaProcessing フォアグラウンド サービスは、ユーザーの直接操作の結果としてのみ開始してください。サービスの開始時にアプリがフォアグラウンドにあるため、サービスはアプリがバックグラウンドに移動してから 6 時間かかります。
  4. mediaProcessing フォアグラウンド サービスを使用する代わりに、WorkManager などの代替 API を使用します。

過去 24 日間にアプリの mediaProcessing フォアグラウンド サービスが 6 時間実行されている場合、ユーザーがアプリをフォアグラウンドに移動した場合(タイマーがリセットされる)でない限り、別の mediaProcessing フォアグラウンド サービスを開始することはできません。別の mediaProcessing フォアグラウンド サービスを開始しようとすると、システムは ForegroundServiceStartNotAllowedException をスローし、「フォアグラウンド サービス タイプ mediaProcessing の期限はすでに上限に達しています」などのエラー メッセージを返します。

mediaProcessing サービスタイプについて詳しくは、Android 15 のフォアグラウンド サービス タイプの変更: メディア処理をご覧ください。

フォアグラウンド サービスを起動する BOOT_COMPLETED ブロードキャスト レシーバに関する制限

フォアグラウンド サービスを起動する BOOT_COMPLETED ブロードキャスト レシーバに新しい制限が追加されました。BOOT_COMPLETED レシーバーは、次のタイプのフォアグラウンド サービスを起動できません。

BOOT_COMPLETED レシーバーがこの種のフォアグラウンド サービスを起動しようとすると、システムは ForegroundServiceStartNotAllowedException をスローします。

アプリが SYSTEM_ALERT_WINDOW 権限を保持しているときのフォアグラウンド サービスの起動に関する制限

以前は、アプリが SYSTEM_ALERT_WINDOW 権限を保持していた場合、アプリがバックグラウンドにあってもフォアグラウンド サービスを起動できました(バックグラウンド起動制限の除外を参照)。

Android 15 をターゲットとするアプリの場合、この除外の範囲は狭くなっています。アプリに SYSTEM_ALERT_WINDOW 権限が付与され、また、表示可能なオーバーレイ ウィンドウも必要です。つまり、アプリはまず TYPE_APPLICATION_OVERLAY ウィンドウを起動し、さらにフォアグラウンド サービスを開始する前にそのウィンドウを表示する必要があります。

アプリがこれらの新しい要件を満たさずにバックグラウンドからフォアグラウンド サービスを開始しようとした場合(かつ、その他の除外がない場合)、システムは ForegroundServiceStartNotAllowedException をスローします。

アプリが SYSTEM_ALERT_WINDOW 権限を宣言し、バックグラウンドからフォアグラウンド サービスを起動する場合、この変更の影響を受ける可能性があります。アプリが ForegroundServiceStartNotAllowedException を取得した場合、アプリのオペレーションの順序を確認し、アプリにすでにアクティブなオーバーレイ ウィンドウがあることを確認してから、バックグラウンドからフォアグラウンド サービスを開始します。オーバーレイ ウィンドウが現在表示されているかどうかを確認するには、View.getWindowVisibility() を呼び出すか、View.onWindowVisibilityChanged() をオーバーライドして、可視性が変化するたびに通知を受け取ることができます。

アプリがサイレント モードのグローバルな状態を変更できるタイミングの変更

Android 15 をターゲットとするアプリでは、ユーザー設定の変更や DND モードの無効化によって、デバイスのサイレント モード(DND)のグローバル状態またはポリシーを変更できなくなりました。代わりに、アプリは AutomaticZenRule をコントリビューションする必要があります。これにより、システムは既存の most-restrictive-policy-wins スキームとグローバル ポリシーを結合します。以前にグローバル状態(setInterruptionFiltersetNotificationPolicy)に影響した既存の API を呼び出すと、暗黙的な AutomaticZenRule の作成または更新が発生します。暗黙的な AutomaticZenRule は、それらの API 呼び出しの呼び出しサイクルに応じてオンとオフが切り替わります。

この変更は、アプリが setInterruptionFilter(INTERRUPTION_FILTER_ALL) を呼び出し、その呼び出しによって以前に所有者によって有効化された AutomaticZenRule が無効化されることを想定している場合にのみ、オブザーバブルな動作に影響します。

OpenJDK 17 の変更

Android 15 では、最新の OpenJDK LTS リリースの機能に合わせて Android のコアライブラリを更新する取り組みが引き続き行われています。

次のいずれかの変更により、Android 15 をターゲットとするアプリの互換性に影響する可能性があります。

  • 文字列形式 API の変更: 次の String.format() API と Formatter.format() API を使用する場合、引数のインデックス、フラグ、幅、精度の検証がより厳格になりました。

    たとえば、引数のインデックスが 0(形式設定文字列の %0)の場合、次の例外がスローされます。

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    この場合、引数インデックス 1(形式文字列の %1)を使用することで問題を解決できます。

  • Arrays.asList(...).toArray() のコンポーネント タイプの変更: Arrays.asList(...).toArray() を使用する場合、生成される配列のコンポーネント タイプは、基になる配列の要素の型ではなく、Object になりました。そのため、次のコードは ClassCastException をスローします。

    String[] elements = (String[]) Arrays.asList("one", "two").toArray();
    

    この場合、結果の配列のコンポーネント タイプとして String を保持するには、代わりに Collection.toArray(Object[]) を使用します。

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • 言語コード処理の変更: Locale API の使用時に、ヘブライ語、イディッシュ語、インドネシア語の言語コードが古い形式に変換されなくなりました(ヘブライ語: iw、イディッシュ語: ji、インドネシア語: in)。これらの言語 / 地域のいずれかで言語コードを指定する場合は、ISO 639: 1: he と、{イブライ語: 1} のコードを使用してください。yiid

  • ランダムな int シーケンスの変更: https://bugs.openjdk.org/browse/JDK-8301574 で行われた変更に従い、次の Random.ints() メソッドは、Random.nextInt() メソッドとは異なる番号シーケンスを返すようになりました。

    一般的に、この変更によってアプリの互換性が損なわれることはありませんが、Random.ints() メソッドから生成されたシーケンスが Random.nextInt() と一致することをコードでは想定しないでください。

セキュリティ

Android 15 では、悪意のあるアプリからアプリとユーザーを保護するために、システム セキュリティが強化されています。

保護されたバックグラウンド アクティビティの起動

Android 15 では、悪意のあるバックグラウンド アプリによる他のアプリのフォアグラウンドへの移動、権限の昇格、ユーザー操作の不正使用を防ぐ変更を追加することで、悪意のあるアプリからユーザーを保護し、デバイスをより細かく制御できるようにします。Android 10(API レベル 29)以降、バックグラウンド アクティビティの起動が制限されています。

スタック上の最上位の UID と一致しないアプリがアクティビティを起動できないようにする

悪意のあるアプリは、同じタスク内で別のアプリのアクティビティを起動し、その上に重ねて、そのアプリであるかのように見せかけることができます。この「タスク ハイジャック」攻撃は、すべてが同じ表示タスク内で発生するため、現在のバックグラウンド起動制限をすり抜けます。このリスクを軽減するため、Android 15 では、スタックの最上位の UID と一致しないアプリがアクティビティを起動しないようブロックするフラグが追加されています。アプリのすべてのアクティビティをオプトインするには、アプリの AndroidManifest.xml ファイルの allowCrossUidActivitySwitchFromBelow 属性を更新します。

<application android:allowCrossUidActivitySwitchFromBelow="false" >

新しいセキュリティ対策は、次の条件がすべて当てはまる場合に有効になります。

  • リリースを実行するアプリは Android 15 をターゲットとしています。
  • タスクスタックの一番上にあるアプリは、Android 15 をターゲットとしています。
  • 表示されるアクティビティはすべて新しい保護設定にオプトインしています

セキュリティ対策が有効になっている場合、アプリが自身のタスクを完了したときに、最後に表示されたアプリではなく、ホームに戻ることがあります。

その他の変更点

UID マッチングの制限に加えて、次のような変更も含まれています。

  • デフォルトでバックグラウンド アクティビティの起動をブロックするように、PendingIntent 作成者を変更します。これにより、悪意のある人物が悪用するおそれのある PendingIntent をアプリが誤って作成するのを防ぐことができます。
  • PendingIntent 送信者が許可しない限り、アプリをフォアグラウンドにしない。この変更は、悪意のあるアプリがバックグラウンドでアクティビティを開始する機能を悪用するのを防ぐことを目的としています。デフォルトでは、作成者がバックグラウンド アクティビティの起動権限を許可しているか、送信者がバックグラウンド アクティビティの起動権限を持っていない限り、アプリはタスクスタックをフォアグラウンドにできません。
  • タスクスタックのトップ アクティビティがタスクを終了する方法を制御する。最上位のアクティビティがタスクを終了すると、Android は最後にアクティブだったタスクに戻ります。さらに、トップ以外のアクティビティがタスクを終了すると、Android はホーム画面に戻ります。このトップ以外のアクティビティの終了はブロックされません。
  • 他のアプリから自分のタスクに任意のアクティビティが起動しないようにする。この変更により、他のアプリからのものと思われるアクティビティを作成することで、悪意のあるアプリがユーザーをフィッシングすることを防止できます。
  • 非表示のウィンドウがバックグラウンド アクティビティの起動で考慮されないようにブロックする。これにより、悪意のあるアプリがバックグラウンド アクティビティの起動を悪用して、望ましくないコンテンツや悪意のあるコンテンツを表示することを防止できます。

より安全なインテント

Android 15 では、インテントの安全性と堅牢性を高めるため、新しいセキュリティ対策が導入されています。これらの変更は、悪意のあるアプリによって悪用される可能性があるインテントの潜在的な脆弱性と不正使用を防ぐことを目的としています。Android 15 では、インテントのセキュリティに関して、主に 2 つの点が改善されています。

  • ターゲットのインテント フィルタと一致する: 特定のコンポーネントをターゲットとするインテントは、ターゲットのインテント フィルタの仕様に正確に一致している必要があります。インテントを送信して別のアプリのアクティビティを起動する場合、ターゲット インテント コンポーネントは、受信側のアクティビティの宣言されたインテント フィルタと一致している必要があります。
  • インテントにはアクションが必要: アクションのないインテントは、どのインテント フィルタにも一致しなくなります。つまり、アクティビティやサービスを開始するために使用されるインテントには、明確に定義されたアクションが必要です。

Kotlin


fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java


public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

ユーザー エクスペリエンスとシステム UI

Android 15 では、より一貫性のある直感的なユーザー エクスペリエンスを実現するために、いくつかの変更が行われています。

ウィンドウ インセットの変更

Android 15 のウィンドウ インセットに関連する変更点は 2 つあります。エッジ ツー エッジがデフォルトで適用されます。もう 1 つは、システムバーのデフォルト構成などの構成の変更です。

エッジ ツー エッジの適用

アプリが Android 15 をターゲットにしている場合、Android 15 を搭載したデバイスでは、アプリはデフォルトでエッジ ツー エッジになります。

Android 14 をターゲットとし、Android 15 デバイスのエッジ ツー エッジではないアプリ。


Android 15 をターゲットとし、Android 15 デバイス上でエッジ ツー エッジのアプリ。このアプリは主に、インセットを自動的に適用するマテリアル 3 Compose コンポーネントを使用しています。この画面は、Android 15 のエッジツーエッジの適用によって悪影響を受けることはありません。

これは互換性を破る変更であり、アプリの UI に悪影響を及ぼす可能性があります。この変更は、次の UI 領域に影響します。

  • ジェスチャー ハンドルのナビゲーション バー
    • デフォルトで透明になります。
    • ボトム オフセットは無効になっているため、インセットを適用しない限り、コンテンツはシステム ナビゲーション バーの背後に描画されます。
    • setNavigationBarColorR.attr#navigationBarColor は非推奨であり、ジェスチャー ナビゲーションには影響しません。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced は、引き続きジェスチャー ナビゲーションに影響しません。
  • 3 ボタン ナビゲーション
    • 不透明度はデフォルトで 80% に設定されています。色はウィンドウの背景と一致する可能性があります。
    • 下オフセットが無効になるため、インセットが適用されていない限り、コンテンツはシステム ナビゲーション バーの背後に描画されます。
    • setNavigationBarColorR.attr#navigationBarColor は、デフォルトでウィンドウの背景に合わせて設定されています。このデフォルトを適用するには、ウィンドウの背景をカラー ドローアブルにする必要があります。この API は非推奨になりましたが、3 ボタン ナビゲーションには引き続き影響します。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced はデフォルトで true です。これにより、3 ボタン ナビゲーション全体に 80% の不透明な背景が追加されます。
  • ステータスバー
    • デフォルトで透明になります。
    • 上オフセットが無効になっているため、インセットを適用しない限り、コンテンツはステータスバーの背後に描画されます。
    • setStatusBarColorR.attr#statusBarColor はサポートが終了しており、Android 15 には影響しません。
    • setStatusBarContrastEnforcedR.attr#statusBarContrastEnforced は非推奨になりましたが、Android 15 では引き続き影響を受けます。
  • ディスプレイ カットアウト
    • 非フローティング ウィンドウの layoutInDisplayCutoutModeLAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS にする必要があります。SHORT_EDGESNEVERDEFAULTALWAYS として解釈されるため、ユーザーにはディスプレイ カットアウトによる黒いバーが表示されず、端から端まで表示されます。

次の例は、Android 15 をターゲットとする前と後、およびインセットを適用する前後のアプリを示しています。

Android 14 をターゲットとし、Android 15 デバイスのエッジ ツー エッジではないアプリ。
Android 15 をターゲットとし、Android 15 デバイス上でエッジ ツー エッジのアプリ。しかし、Android 15 のエッジ ツー エッジの適用により、多くの要素がステータスバー、3 ボタン ナビゲーション バー、ディスプレイ カットアウトによって遮られるようになりました。隠れた UI には、マテリアル 2 のトップ アプリバー、フローティング アクション ボタン、リストアイテムが含まれます。
Android 15 をターゲットとするアプリは、Android 15 デバイスのエッジ ツー エッジで、UI が遮られないようにインセットを適用します。
アプリがすでにエッジ ツー エッジ対応かどうかを確認する方法

アプリがすでにエッジ ツー エッジでインセットを適用している場合、次のシナリオを除き、ほとんど影響はありません。ただし、影響がないと思われる場合でも、アプリをテストすることをおすすめします。

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS ではなく SHORT_EDGESNEVER、または DEFAULT を使用する Activity などの非フローティング ウィンドウがある。アプリが起動時にクラッシュする場合は、スプラッシュ画面が原因である可能性があります。コア スプラッシュ画面の依存関係を 1.2.0-alpha01 以降にアップグレードするか、window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always を設定できます。
  • トラフィックの少ない画面で UI が遮断されている場合があります。こうしたアクセス頻度の低い画面で UI が遮られていないことを確認します。トラフィックの少ない画面には、次のものがあります。
    • オンボーディング画面またはログイン画面
    • 設定ページ
アプリがまだエッジ ツー エッジになっていない場合の確認方法

アプリがエッジ ツー エッジ対応でない場合は、この問題の影響を受ける可能性があります。すでにエッジ ツー エッジのアプリ向けのシナリオに加えて、次の点を考慮する必要があります。

  • アプリが Compose でマテリアル 3 コンポーネント(androidx.compose.material3)(TopAppBarBottomAppBarNavigationBar など)を使用している場合、これらのコンポーネントはインセットを自動的に処理するため、影響を受けない可能性が高くなります。
  • アプリが Compose でマテリアル 2 コンポーネント(androidx.compose.material)を使用している場合、これらのコンポーネントはインセットを自動的に処理しません。ただし、インセットにアクセスして、手動で適用できます。androidx.compose.material 1.6.0 以降では、windowInsets パラメータを使用して、BottomAppBarTopAppBarBottomNavigationNavigationRail のインセットを手動で適用します。同様に、ScaffoldcontentWindowInsets パラメータを使用します。
  • アプリでビューとマテリアル コンポーネント(com.google.android.material)を使用している場合、ビューベースのマテリアル コンポーネント(BottomNavigationViewBottomAppBarNavigationRailViewNavigationView など)のほとんどはインセットを処理するため、追加の作業は必要ありません。ただし、AppBarLayout を使用する場合は android:fitsSystemWindows="true" を追加する必要があります。
  • カスタム コンポーザブルの場合は、インセットをパディングとして手動で適用します。コンテンツが Scaffold 内にある場合は、Scaffold パディング値を使用してインセットを使用できます。それ以外の場合は、WindowInsets のいずれかを使用してパディングを適用します。
  • アプリでビューと BottomSheetSideSheet、またはカスタム コンテナを使用している場合は、ViewCompat.setOnApplyWindowInsetsListener を使用してパディングを適用します。RecyclerView の場合は、このリスナーを使用してパディングを適用し、clipToPadding="false" も追加します。
アプリがカスタムのバックグラウンド保護を提供する必要があるかどうかを確認する方法

アプリで 3 ボタン ナビゲーションまたはステータスバーにカスタムのバックグラウンド保護を提供する必要がある場合は、WindowInsets.Type#tappableElement() を使用してコンポーザブルまたはビューをシステムバーの背後に配置して、3 ボタン ナビゲーション バーの高さまたは WindowInsets.Type#statusBars を取得する必要があります。

その他のエッジ ツー エッジのリソース

インセットの適用に関するその他の考慮事項については、Edge to Edge ビューEdge to Edge Compose ガイドをご覧ください。

サポート終了 API

次の API は非推奨になりました。

安定した構成

Android 15 以降をターゲットとするアプリの場合、Configuration はシステムバーを除外しなくなりました。レイアウト計算に Configuration クラスの画面サイズを使用する場合は、必要に応じて適切な ViewGroupWindowInsetsWindowMetricsCalculator などの適切な代替手段に置き換える必要があります。

Configuration は API 1 以降で使用できます。通常、Activity.onConfigurationChanged から取得されます。ウィンドウ密度、向き、サイズなどの情報を提供します。Configuration から返されるウィンドウ サイズに関する重要な特徴の 1 つは、以前はシステムバーを除外していたことです。

構成サイズは通常、/res/layout-h500dp などのリソース選択に使用されますが、これは有効なユースケースです。ただし、これをレイアウト計算に使用することは常に推奨されていません。もしそうならば、今はそれから離れる必要があります。Configuration の使用は、ユースケースに応じてより適切なものに置き換える必要があります。

これを使用してレイアウトを計算する場合は、CoordinatorLayoutConstraintLayout などの適切な ViewGroup を使用します。これを使用してシステム ナビゲーション バーの高さを決定する場合は、WindowInsets を使用します。アプリ ウィンドウの現在のサイズを確認するには、computeCurrentWindowMetrics を使用します。

この変更の影響を受けるフィールドは次のとおりです。

  • Configuration.screenWidthDpscreenHeightDp のサイズでシステムバーが除外されなくなりました。
  • Configuration.smallestScreenWidthDp は、screenWidthDpscreenHeightDp への変更によって間接的に影響を受けます。
  • Configuration.orientation は、正方形に近いデバイスで screenWidthDpscreenHeightDp を変更すると、間接的に影響を受けます。
  • Display.getSize(Point) は、Configuration の変更によって間接的に影響を受けます。これは、API レベル 30 以降で非推奨になりました。
  • Display.getMetrics() は、API レベル 33 以降ですでにこのように動作しています。

emojiTextHeight 属性のデフォルトを true に設定

Android 15 をターゲットとするアプリの場合、elegantTextHeight TextView 属性はデフォルトで true になり、デフォルトで使用されるコンパクト フォントが、大きな垂直指標を持つ一部のスクリプトに置き換えられ、より読みやすいものに置き換えられます。コンパクト フォントはレイアウトの破損を防ぐために導入されました。Android 13(API レベル 33)では、テキスト レイアウトで fallbackLineSpacing 属性を使用して垂直方向の高さを拡大できるようにすることで、こうした破損の多くを回避しています。

Android 15 では、コンパクト フォントがまだシステムに残っているため、アプリで elegantTextHeightfalse に設定して以前と同じ動作を得ることができますが、今後のリリースではサポートされない見込みです。そのため、アラビア語、ラオ語、ミャンマー、タミル語、グジャラート語、カンナダ語、マラヤーラム語、オディア語、テルグ語、タイ語のスクリプトをアプリがサポートしている場合は、elegantTextHeighttrue に設定してアプリをテストします。

Android 14(API レベル 34)以下をターゲットとするアプリの elegantTextHeight の動作。
Android 15 をターゲットとするアプリの elegantTextHeight の動作。

複雑な文字図形に合わせて TextView の幅を変更する

以前のバージョンの Android では、一部の手書きフォントや複雑な形状の言語では、前後の文字の領域に文字が描画されることがありました。一部の文字は、先頭または末尾で切り取られていました。Android 15 以降では、TextView により、このような文字が描画される十分なスペースを描画するための幅が割り当てられ、クリッピングを防ぐためにアプリが左側の追加のパディングをリクエストできるようになります。

この変更は TextView による幅の決定方法に影響するため、アプリが Android 15 以降をターゲットとする場合、TextView はデフォルトでより多くの幅を割り当てます。この動作を有効または無効にするには、TextView に対して setUseBoundsForWidth API を呼び出します。

左にパディングを追加すると、既存のレイアウトの配置がずれる可能性があるため、Android 15 以降をターゲットとするアプリであっても、デフォルトではパディングは追加されません。ただし、setShiftDrawingOffsetForStartOverhang を呼び出して、クリッピングを防ぐためにパディングを追加できます。

次の例は、これらの変更によって一部のフォントと言語のテキスト レイアウトがどのように改善されるかを示しています。

手書きフォントの英語テキストの標準レイアウト。一部の文字は切り詰められています。対応する XML は次のとおりです。

<TextView
    android:fontFamily="cursive"
    android:text="java" />
同じ英語テキストのレイアウトで、幅とパディングが追加されています。対応する XML は次のとおりです。

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
タイ語テキストの標準レイアウト。文字の一部が切り捨てられています。 対応する XML は次のとおりです。

<TextView
    android:text="คอมพิวเตอร์" />
幅とパディングを追加した同じタイ語テキストのレイアウト。対応する XML は次のとおりです。

<TextView
    android:text="คอมพิวเตอร์"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

EditText の言語 / 地域対応のデフォルト行の高さ

以前のバージョンの Android では、テキスト レイアウトは、現在の言語 / 地域に一致するフォントの行の高さに合わせて、テキストの高さを拡大していました。たとえば、コンテンツが日本語の場合、日本語フォントの行の高さがラテン文字フォントの行の高さよりも若干大きいため、テキストの高さは少し大きくなります。ただし、このような行の高さの違いにもかかわらず、次の図に示すように、使用されている言語 / 地域に関係なく、EditText 要素のサイズは均一に設定されました。

EditText 要素を表す 3 つのボックス。英語(en)、日本語(ja)、ビルマ語(my)のテキストを含めることができます。これらの言語の行の高さは異なりますが、EditText の高さは同じです。

Android 15 をターゲットとするアプリでは、次の図に示すように、指定された言語 / 地域の参照フォントと一致するように、EditText の最小行の高さが予約されています。

EditText 要素を表す 3 つのボックス。英語(en)、日本語(ja)、ビルマ語(my)のテキストを含めることができます。EditText の高さには、これらの言語のフォントのデフォルトの行の高さに対応するスペースが含まれています。

必要に応じて、useLocalePreferredLineHeightForMinimum 属性を false に指定することで以前の動作を復元できます。また、Kotlin と Java で setMinimumFontMetrics API を使用してカスタムの最小業種指標を設定できます。

カメラとメディア

Android 15 では、Android 15 以降をターゲットとするアプリのカメラとメディアの動作が次のように変更されています。

音声フォーカスのリクエストに関する制限

Android 15 をターゲットとするアプリが音声フォーカスをリクエストするには、トップアプリであるか、オーディオ関連のフォアグラウンド サービスを実行している必要があります。これらの要件をいずれも満たさないときにアプリがフォーカスをリクエストしようとすると、呼び出しは AUDIOFOCUS_REQUEST_FAILED を返します。

フォアグラウンド サービスは、タイプが mediaPlaybackcameramicrophone、または phoneCall の場合、音声関連とみなされます。

音声フォーカスについて詳しくは、音声フォーカスを管理するをご覧ください。

非 SDK の制限の更新

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

Android 15 をターゲットとしないアプリの場合、この変更の一部はすぐには影響しない可能性があります。ただし、アプリの対象 API レベルによっては、アプリから一部の非 SDK インターフェースにアクセスできる可能性がありますが、非 SDK のメソッドまたはフィールドを使用すると、常にアプリが機能しなくなるリスクが高くなります。

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

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