Verhaltensänderungen: Apps, die auf Android 15 oder höher ausgerichtet sind

Wie bei früheren Releases enthält Android 15 Verhaltensänderungen, die sich auf Ihre App auswirken können. Die folgenden Verhaltensänderungen gelten ausschließlich für Apps, die auf Android 15 oder höher ausgerichtet sind. Wenn Ihre App auf Android 15 oder höher ausgerichtet ist, sollten Sie sie gegebenenfalls so ändern, dass sie diese Verhaltensweisen korrekt unterstützt.

Lesen Sie sich auch die Liste der Verhaltensänderungen durch, die sich auf alle Apps auswirken, die unter Android 15 ausgeführt werden, unabhängig von der targetSdkVersion Ihrer App.

Hauptfunktion

In Android 15 wurden verschiedene Kernfunktionen des Android-Systems geändert oder erweitert.

Änderungen an Diensten im Vordergrund

Wir nehmen unter Android 15 die folgenden Änderungen an Diensten im Vordergrund vor.

Verhalten bei Zeitüberschreitung bei der Datensynchronisierung im Vordergrund

Unter Android 15 wird für dataSync ein neues Zeitlimit für Apps eingeführt, die auf Android 15 (API-Level 35) oder höher ausgerichtet sind. Dies gilt auch für den neuen Diensttyp mediaProcessing im Vordergrund.

Das System erlaubt es den dataSync-Diensten einer App, innerhalb eines Zeitraums von 24 Stunden insgesamt 6 Stunden lang ausgeführt zu werden. Danach ruft das System die Methode Service.onTimeout(int, int) des laufenden Dienstes auf (in Android 15 eingeführt). In dieser Zeit hat der Dienst einige Sekunden Zeit, Service.stopSelf() aufzurufen. Wenn Service.onTimeout() aufgerufen wird, gilt der Dienst nicht mehr als Dienst im Vordergrund. Wenn der Dienst Service.stopSelf() nicht aufruft, löst das System eine interne Ausnahme aus. Die Ausnahme wird in Logcat mit der folgenden Meldung protokolliert:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

So vermeiden Sie Probleme mit dieser Verhaltensänderung:

  1. Lassen Sie Ihren Dienst die neue Service.onTimeout(int, int)-Methode implementieren. Wenn Ihre App den Callback empfängt, müssen Sie innerhalb weniger Sekunden stopSelf() anrufen. Wenn Sie die App nicht sofort beenden, generiert das System einen Fehler.
  2. Die dataSync-Dienste Ihrer App dürfen innerhalb eines 24-Stunden-Zeitraums nicht länger als insgesamt 6 Stunden ausgeführt werden, es sei denn, der Nutzer interagiert mit der App und setzt den Timer zurück.
  3. Starten Sie dataSync Dienste im Vordergrund nur als Folge einer direkten Nutzerinteraktion. Da sich Ihre App beim Start des Dienstes im Vordergrund befindet, hat Ihr Dienst die vollen sechs Stunden Zeit, nachdem die App in den Hintergrund gewechselt ist.
  4. Verwenden Sie stattdessen eine alternative API.dataSync

Wenn die dataSync-Dienste im Vordergrund Ihrer App in den letzten 24 Stunden sechs Stunden lang ausgeführt wurden, können Sie keinen weiteren dataSync-Dienst im Vordergrund starten, es sei denn, der Nutzer hat Ihre App in den Vordergrund gebracht (wodurch der Timer zurückgesetzt wird). Wenn Sie versuchen, einen weiteren dataSync-Vordergrunddienst zu starten, gibt das System ForegroundServiceStartNotAllowedException mit einer Fehlermeldung zurück, z. B. „Zeitlimit für den Typ ‚dataSync‘ des Vordergrunddienstes bereits überschritten“.

Testen

Sie können Zeitüberschreitungen für die Datensynchronisierung aktivieren, um das Verhalten Ihrer App zu testen, auch wenn Ihre App nicht auf Android 15 ausgerichtet ist, solange die App auf einem Android 15-Gerät ausgeführt wird. Führen Sie den folgenden Befehl adb aus, um Zeitüberschreitungen zu aktivieren:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

Sie können auch die Zeitüberschreitung anpassen, um das Verhalten Ihrer App nach Erreichen des Limits leichter zu testen. Führen Sie den folgenden adb-Befehl aus, um ein neues Zeitlimit festzulegen:

adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds

Neuer Typ von Dienst zur Medienverarbeitung im Vordergrund

In Android 15 wird der neue Diensttyp mediaProcessing eingeführt. Dieser Diensttyp eignet sich für Vorgänge wie das Transcodieren von Mediendateien. Eine Medien-App könnte beispielsweise eine Audiodatei herunterladen und sie vor der Wiedergabe in ein anderes Format konvertieren. Sie können einen mediaProcessing-Dienst im Vordergrund verwenden, damit die Conversion auch dann fortgesetzt wird, wenn die App im Hintergrund ausgeführt wird.

Das System lässt zu, dass die mediaProcessing-Dienste einer App insgesamt 6 Stunden innerhalb von 24 Stunden ausgeführt werden. Anschließend ruft das System die Service.onTimeout(int, int)-Methode des laufenden Dienstes auf (in Android 15 eingeführt). Derzeit hat der Dienst einige Sekunden Zeit, um Service.stopSelf() aufzurufen. Wenn der Dienst Service.stopSelf() nicht aufruft, löst das System eine interne Ausnahme aus. Die Ausnahme wird in Logcat mit der folgenden Meldung protokolliert:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

Sie können eine Ausnahme vermeiden, indem Sie einen der folgenden Schritte ausführen:

  1. Implementieren Sie in Ihrem Dienst die neue Service.onTimeout(int, int)-Methode. Wenn Ihre App den Callback empfängt, müssen Sie innerhalb weniger Sekunden stopSelf() anrufen. Wenn Sie die App nicht sofort beenden, generiert das System einen Fehler.
  2. Die mediaProcessing-Dienste Ihrer App dürfen innerhalb eines 24-Stunden-Zeitraums insgesamt nicht länger als 6 Stunden ausgeführt werden, es sei denn, der Nutzer interagiert mit der App und setzt den Timer zurück.
  3. Starten Sie mediaProcessing Dienste im Vordergrund nur als Folge einer direkten Nutzerinteraktion. Da sich Ihre App beim Start des Dienstes im Vordergrund befindet, hat Ihr Dienst die vollen sechs Stunden Zeit, nachdem die App in den Hintergrund gewechselt ist.
  4. Verwende anstelle eines mediaProcessing-Dienstes im Vordergrund eine alternative API wie WorkManager.

Wenn die mediaProcessing-Dienste im Vordergrund Ihrer App in den letzten 24 Stunden sechs Stunden lang ausgeführt wurden, können Sie keinen weiteren mediaProcessing-Dienst im Vordergrund starten, es sei denn, der Nutzer hat Ihre App in den Vordergrund gebracht (wodurch der Timer zurückgesetzt wird). Wenn Sie versuchen, einen weiteren mediaProcessing-Vordergrunddienst zu starten, löst das System ForegroundServiceStartNotAllowedException mit einer Fehlermeldung wie „Zeitlimit für den Typ „mediaProcessing“ des Dienstes im Vordergrund bereits überschritten“ aus.

Weitere Informationen zum Diensttyp mediaProcessing finden Sie unter Änderungen an Diensttypen im Vordergrund für Android 15: Medienverarbeitung.

Testen

Wenn du das Verhalten deiner App testen möchtest, kannst du Zeitüberschreitungen bei der Medienverarbeitung aktivieren, auch wenn deine App nicht auf Android 15 ausgerichtet ist, solange sie auf einem Android 15-Gerät ausgeführt wird. Führen Sie den folgenden Befehl adb aus, um Zeitüberschreitungen zu aktivieren:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

Sie können auch das Zeitlimit anpassen, um zu testen, wie sich Ihre Anwendung verhält, wenn das Limit erreicht ist. Führen Sie den folgenden adb-Befehl aus, um ein neues Zeitlimit festzulegen:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

Einschränkungen für BOOT_COMPLETED Übertragungsempfänger, die Dienste im Vordergrund starten

Es gelten neue Einschränkungen für die Einführung von BOOT_COMPLETED Übertragungsempfängern Dienste im Vordergrund. BOOT_COMPLETED Empfänger dürfen nicht Folgendes starten: folgende Arten von Diensten im Vordergrund:

Wenn ein BOOT_COMPLETED-Empfänger versucht, einen dieser Dienste im Vordergrund zu starten, löst das System ForegroundServiceStartNotAllowedException aus.

Testen

Um das Verhalten Ihrer App zu testen, können Sie diese neuen Einschränkungen auch dann aktivieren, wenn Ihre Die App ist nicht auf Android 15 ausgerichtet (solange die App auf einem Android 15 ausgeführt wird) Gerät). Führen Sie den folgenden adb-Befehl aus:

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

Wenn Sie eine BOOT_COMPLETED-Broadcastnachricht senden möchten, ohne das Gerät neu zu starten, führen Sie den folgenden Befehl adb aus:

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

Einschränkungen beim Starten von Diensten im Vordergrund, während eine App die Berechtigung „SYSTEM_ALERT_WINDOW“ enthält

Bisher konnte eine App mit der Berechtigung SYSTEM_ALERT_WINDOW einen Dienst im Vordergrund starten, auch wenn sie sich gerade im Hintergrund befand (wie unter Ausnahmen von Einschränkungen beim Starten im Hintergrund beschrieben).

Wenn eine App auf Android 15 ausgerichtet ist, ist diese Ausnahme jetzt eingeschränkter. Die App benötigt jetzt die Berechtigung SYSTEM_ALERT_WINDOW und auch ein sichtbares Overlay-Fenster. Das bedeutet, dass die App zuerst ein TYPE_APPLICATION_OVERLAY-Fenster öffnen und das Fenster sichtbar sein muss, bevor Sie einen Dienst im Vordergrund starten.

Wenn Ihre App versucht, einen Dienst im Vordergrund aus dem Hintergrund zu starten, ohne diese neuen Anforderungen zu erfüllen (und keine andere Ausnahme vorliegt), löst das System ForegroundServiceStartNotAllowedException aus.

Wenn Ihre App die Berechtigung SYSTEM_ALERT_WINDOW deklariert und Dienste im Vordergrund aus dem Hintergrund startet, kann sich diese Änderung auf Ihre App auswirken. Wenn deine App eine ForegroundServiceStartNotAllowedException erhält, prüfe die Reihenfolge der Vorgänge in deiner App und achte darauf, dass deine App bereits ein aktives Overlay-Fenster hat, bevor sie versucht, einen Dienst im Vordergrund im Hintergrund zu starten. Du kannst mit View.getWindowVisibility() prüfen, ob dein Overlay-Fenster gerade sichtbar ist. Du kannst auch View.onWindowVisibilityChanged() überschreiben, um benachrichtigt zu werden, wenn sich die Sichtbarkeit ändert.

Testen

Um das Verhalten deiner App zu testen, kannst du diese neuen Einschränkungen auch dann aktivieren, wenn deine App nicht auf Android 15 ausgerichtet ist, solange sie auf einem Android 15-Gerät ausgeführt wird. Wenn Sie diese neuen Einschränkungen für den Start von Diensten im Vordergrund aus dem Hintergrund aktivieren möchten, führen Sie den folgenden adb-Befehl aus:

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

Änderungen bei der Möglichkeit von Apps, den globalen Status des Modus „Bitte nicht stören“ zu ändern

Apps, die auf Android 15 ausgerichtet sind, können den globalen Status oder die Richtlinie für „Bitte nicht stören“ auf einem Gerät nicht mehr ändern (entweder durch Ändern der Nutzereinstellungen oder durch Deaktivieren des Modus „Nicht stören“). Stattdessen müssen Apps ein AutomaticZenRule-Element bereitstellen, das vom System zu einer globalen Richtlinie mit dem bestehenden „most-restrictive-policy-wins“-Schema kombiniert wird. Aufrufe an vorhandene APIs, die sich zuvor auf den globalen Status (setInterruptionFilter, setNotificationPolicy) ausgewirkt haben, führen zur Erstellung oder Aktualisierung einer impliziten AutomaticZenRule, die je nach Aufrufzyklus dieser API-Aufrufe ein- und ausgeschaltet wird.

Diese Änderung wirkt sich nur dann auf das beobachtbare Verhalten aus, wenn die App setInterruptionFilter(INTERRUPTION_FILTER_ALL) aufruft und erwartet, dass durch diesen Aufruf ein AutomaticZenRule deaktiviert wird, das zuvor von ihren Inhabern aktiviert wurde.

Änderungen an der OpenJDK API

In Android 15 werden die Kernbibliotheken von Android weiter aktualisiert, um sie an die Funktionen der neuesten OpenJDK-LTS-Releases anzupassen.

Einige dieser Änderungen können sich auf die App-Kompatibilität für Apps auswirken, die auf Android 15 (API-Level 35) ausgerichtet sind:

  • Änderungen an APIs für die Stringformatierung: Die Validierung von Argumentindex, Flags, Breite und Genauigkeit ist jetzt bei der Verwendung der folgenden String.format()- und Formatter.format()-APIs strenger:

    Beispielsweise wird die folgende Ausnahme geworfen, wenn der Argumentindex 0 verwendet wird (%0 im Formatstring):

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    In diesem Fall kann das Problem durch Verwendung eines Argumentindexes von 1 (%1 im Formatstring) behoben werden.

  • Änderungen am Komponententyp von Arrays.asList(...).toArray(): Bei Verwendung von Arrays.asList(...).toArray() ist der Komponententyp des resultierenden Arrays jetzt ein Object – nicht der Typ der Elemente des zugrunde liegenden Arrays. Der folgende Code führt daher zu einem ClassCastException:

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

    Wenn Sie in diesem Fall String als Komponententyp im resultierenden Array beibehalten möchten, können Sie stattdessen Collection.toArray(Object[]) verwenden:

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • Änderungen bei der Verarbeitung von Sprachcodes: Bei der Verwendung der Locale API werden Sprachcodes für Hebräisch, Jiddisch und Indonesisch nicht mehr in ihre veralteten Formen umgewandelt (Hebräisch: iw, Jiddisch: ji und Indonesisch: in). Geben Sie den Sprachcode für eine dieser Sprachen stattdessen mit den Codes aus ISO 639-1 an (Hebräisch: he, Jiddisch: yi und Indonesisch: id).

  • Änderungen an Zufallszahlenfolgen: Aufgrund der Änderungen unter https://bugs.openjdk.org/browse/JDK-8301574 geben die folgenden Random.ints()-Methoden jetzt eine andere Zahlenfolge zurück als die Random.nextInt()-Methoden:

    Im Allgemeinen sollte diese Änderung nicht zu einem Absturz der App führen. Ihr Code sollte jedoch nicht davon ausgehen, dass die von Random.ints()-Methoden generierte Sequenz mit Random.nextInt() übereinstimmt.

Die neue SequencedCollection API kann sich auf die Kompatibilität Ihrer App auswirken, nachdem Sie compileSdk in der Build-Konfiguration Ihrer App auf Android 15 (API-Level 35) aktualisiert haben:

  • Überschneidung mit den Erweiterungsfunktionen MutableList.removeFirst() und MutableList.removeLast() in kotlin-stdlib

    Der Typ List in Java wird dem Typ MutableList in Kotlin zugeordnet. Da die APIs List.removeFirst() und List.removeLast() in Android 15 (API-Ebene 35) eingeführt wurden, löst der Kotlin-Compiler Funktionsaufrufe wie list.removeFirst() statisch auf die neuen List APIs statt auf die Erweiterungsfunktionen in kotlin-stdlib auf.

    Wenn eine App neu kompiliert wird, wobei compileSdk auf 35 und minSdk auf 34 oder niedriger festgelegt ist, und dann auf Android 14 oder niedriger ausgeführt wird, wird ein Laufzeitfehler ausgegeben:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    Mit der vorhandenen NewApi-Lint-Option im Android Gradle-Plug-in können diese neuen API-Nutzungen erkannt werden.

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    Um die Laufzeitausnahme und die Lint-Fehler zu beheben, können die Funktionsaufrufe removeFirst() und removeLast() in Kotlin durch removeAt(0) und removeAt(list.lastIndex) ersetzt werden. Wenn Sie Android Studio Ladybug | 2024.1.3 oder höher verwenden, gibt es auch eine Option zur Schnellkorrektur dieser Fehler.

    Entfernen Sie @SuppressLint("NewApi") und lintOptions { disable 'NewApi' }, wenn die Lint-Option deaktiviert wurde.

  • Überschneidung mit anderen Methoden in Java

    Den vorhandenen Typen wurden neue Methoden hinzugefügt, z. B. List und Deque. Diese neuen Methoden sind möglicherweise nicht mit den Methoden mit demselben Namen und denselben Argumenttypen in anderen Schnittstellen und Klassen kompatibel. Bei einer Kollision der Methodensignatur mit Inkompatibilität gibt der javac-Compiler einen Buildzeitfehler aus. Beispiel:

    Beispiel für Fehler 1:

    javac MyList.java
    
    MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List
      public void removeLast() {
                  ^
      return type void is not compatible with Object
      where E is a type-variable:
        E extends Object declared in interface List
    

    Beispiel für Fehlermeldung 2:

    javac MyList.java
    
    MyList.java:7: error: types Deque<Object> and List<Object> are incompatible;
    public class MyList implements  List<Object>, Deque<Object> {
      both define reversed(), but with unrelated return types
    1 error
    

    Beispiel für Fehler 3:

    javac MyList.java
    
    MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible;
    public static class MyList implements List<Object>, MyInterface<Object> {
      class MyList inherits unrelated defaults for getFirst() from types List and MyInterface
      where E#1,E#2 are type-variables:
        E#1 extends Object declared in interface List
        E#2 extends Object declared in interface MyInterface
    1 error
    

    Um diese Buildfehler zu beheben, sollte die Klasse, die diese Schnittstellen implementiert, die Methode mit einem kompatiblen Rückgabetyp überschreiben. Beispiel:

    @Override
    public Object getFirst() {
        return List.super.getFirst();
    }
    

Sicherheit

Android 15 enthält Änderungen, die die Systemsicherheit verbessern und Apps und Nutzer vor schädlichen Apps schützen sollen.

Start von sicheren Hintergrundaktivitäten

Android 15 schützt Nutzer vor schädlichen Apps und gibt ihnen mehr Kontrolle über indem sie Änderungen hinzufügen, die verhindern, das Hervorheben anderer Apps im Vordergrund, Erhöhen ihrer Berechtigungen und Missbrauch der Nutzerinteraktion. Das Starten von Hintergrundaktivitäten wurde seitdem eingeschränkt Android 10 (API-Level 29)

Starten von Aktivitäten für Apps, die nicht mit der obersten UID im Stapel übereinstimmen, blockieren

Schädliche Apps können die Aktivitäten einer anderen App innerhalb derselben Aufgabe starten. überlagern sich und erzeugen den Eindruck, diese App zu sein. Diese „Aufgabe Kontodiebstahl“ die aktuellen Einschränkungen beim Start im Hintergrund innerhalb derselben sichtbaren Aufgabe auftritt. Um dieses Risiko zu mindern, wird Android 15 Flag, das den Start von Apps blockiert, die nicht mit der obersten UID im Stack übereinstimmen Aktivitäten. Wenn du alle Aktivitäten deiner App aktivieren möchtest, aktualisiere die allowCrossUidActivitySwitchFromBelow Attribut in der AndroidManifest.xml-Datei Ihrer App:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

Die neuen Sicherheitsmaßnahmen sind aktiv, wenn alle der folgenden Bedingungen erfüllt sind:

  • Die App, mit der die Markteinführung durchgeführt wird, ist auf Android 15 ausgerichtet.
  • Die App, die dem Aufgabenstapel übergeht, ist auf Android 15 ausgerichtet.
  • Die neuen Schutzmaßnahmen wurden für alle sichtbaren Aktivitäten aktiviert

Wenn die Sicherheitsmaßnahmen aktiviert sind, werden Apps möglicherweise wieder zu Hause angezeigt, der letzten sichtbaren App, wenn sie ihre eigene Aufgabe beendet.

Sonstige Änderungen

Neben der Einschränkung des UID-Abgleichs enthalten:

  • PendingIntent Creator so ändern, dass Starten von Hintergrundaktivitäten blockiert werden, indem Standardeinstellung. So wird verhindert, dass Apps versehentlich ein PendingIntent, die von böswilligen Akteuren missbraucht werden könnten.
  • Bringe eine App nur dann in den Vordergrund, wenn der Absender PendingIntent . Mit dieser Änderung soll verhindert werden, dass schädliche Apps den Aktivitäten im Hintergrund starten können. Standardmäßig werden Apps nicht Sie dürfen den Aufgabenstapel in den Vordergrund holen, es sei denn, der Ersteller erlaubt Berechtigungen zum Starten von Hintergrundaktivitäten oder der Absender hat Hintergrundaktivitäten Startberechtigungen.
  • Steuern, wie die oberste Aktivität eines Aufgabenstapels ihre Aufgabe beenden kann. Wenn die häufigste Aktivität eine Aufgabe beendet, wechselt Android zu der Aufgabe zurück, Zuletzt aktiv. Wenn eine Aktivität, die nicht am wichtigsten ist, ihre Aufgabe beendet, wird Android kehren zum Startbildschirm zurück. wird das Ende dieser nicht oben stehenden Seite Aktivitäten.
  • Starten beliebiger Aktivitäten von anderen Apps in Ihre eigene App verhindern Aufgabe. Durch diese Änderung werden schädliche Apps vor Phishing-Nutzern geschützt, indem Aktivitäten, die offenbar aus anderen Apps stammen.
  • Verhindern, dass nicht sichtbare Fenster für Hintergrundaktivitäten berücksichtigt werden Markteinführungen. So wird verhindert, dass schädliche Apps den Hintergrund missbrauchen um Nutzern unerwünschte oder schädliche Inhalte anzuzeigen.

Sicherere Intents

Android 15 引入了新的可选安全措施,以提高 intent 的安全性和稳健性。这些变更旨在防止潜在的漏洞以及恶意应用可能利用的 intent 滥用行为。Android 15 对 intent 的安全性进行了两项主要改进:

  • 与目标 intent 过滤器匹配:定位到特定组件的 intent 必须与目标的 intent 过滤器规范完全匹配。如果您发送 intent 来启动其他应用的 activity,目标 intent 组件需要与接收 activity 声明的 intent 过滤器保持一致。
  • intent 必须具有操作:没有操作的 intent 将不再与任何 intent 过滤器匹配。这意味着,用于启动 activity 或服务的 intent 必须具有明确定义的操作。

如需检查您的应用对这些更改的响应方式,请在应用中使用 StrictMode。如需查看有关 Intent 使用违规行为的详细日志,请添加以下方法:

Kotlin


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

Java


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

Nutzererfahrung und System-UI

Android 15 enthält einige Änderungen, die für eine einheitlichere und intuitivere Nutzererfahrung sorgen sollen.

Änderungen am Fenstereinsatz

In Android 15 gibt es zwei Änderungen im Zusammenhang mit Fenstereinsätzen: Edge-to-Edge-Änderungen werden standardmäßig erzwungen. Außerdem gibt es Konfigurationsänderungen, z. B. die Standardkonfiguration von Systemleisten.

Edge-to-Edge-Erzwingung

默认情况下,如果应用以 Android 15(API 级别 35)为目标平台,在搭载 Android 15 的设备上,应用默认采用全屏。

目标平台为 Android 14 且在 Android 15 设备上未采用边到边设计的应用。


以 Android 15(API 级别 35)为目标平台且在 Android 15 设备上全屏显示的应用。此应用主要使用会自动应用边衬区的 Material 3 Compose 组件。此屏幕不受 Android 15 强制执行的无边框措施的影响。

这是一项可能会对应用的界面产生负面影响的破坏性更改。这些变更会影响以下界面区域:

  • 手势处理程序导航栏
    • 默认透明。
    • 底部偏移量处于停用状态,因此除非应用边衬区,否则内容会在系统导航栏后面绘制。
    • setNavigationBarColorR.attr#navigationBarColor 已废弃,不会影响手势导航。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced 对手势导航的影响仍然不变。
  • “三按钮”导航
    • 默认情况下,不透明度设置为 80%,颜色可能与窗口背景相匹配。
    • 底部偏移量处于停用状态,因此除非应用了边衬区,否则内容会在系统导航栏后面绘制。
    • 默认情况下,setNavigationBarColorR.attr#navigationBarColor 会设置为与窗口背景相匹配。窗口背景必须是彩色可绘制对象,此默认值才能应用。此 API 已废弃,但仍会影响三按钮导航。
    • setNavigationBarContrastEnforcedR.attr#navigationBarContrastEnforced 默认为 true,这会在“三按钮”导航中添加 80% 的不透明背景。
  • 状态栏
    • 默认透明。
    • 顶部偏移量已停用,因此除非应用边衬区,否则内容绘制在状态栏后面。
    • setStatusBarColorR.attr#statusBarColor 已废弃,对 Android 15 没有任何影响。
    • setStatusBarContrastEnforcedR.attr#statusBarContrastEnforced 已废弃,但对 Android 15 仍有影响。
  • 刘海屏
    • 非浮动窗口的 layoutInDisplayCutoutMode 必须为 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYSSHORT_EDGESNEVERDEFAULT 会被解读为 ALWAYS,这样用户就不会看到由刘海屏导致的黑条,从而显示为无边框。

以下示例展示了应用在以 Android 15(API 级别 35)为目标平台之前和之后,以及应用在应用内嵌之前和之后的效果。

目标平台为 Android 14 且在 Android 15 设备上未采用边到边设计的应用。
以 Android 15(API 级别 35)为目标平台且在 Android 15 设备上全屏显示的应用。不过,由于 Android 15 强制执行边到边显示,许多元素现在都被状态栏、三按钮导航栏或显示屏缺口遮挡。隐藏的界面包括 Material 2 顶部应用栏、悬浮操作按钮和列表项。
以 Android 15(API 级别 35)为目标平台的应用,在 Android 15 设备上从边到边,并应用内嵌,以免界面被隐藏。
如何检查应用是否已采用边到边设计

如果您的应用已采用边到边设计并应用了内边距,则除以下情况外,您大多不会受到影响。不过,即使您认为自己未受到影响,我们仍建议您测试自己的应用。

  • 您有一个非浮动窗口,例如使用 SHORT_EDGESNEVERDEFAULT(而非 LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS)的 Activity。如果您的应用在启动时崩溃,这可能是启动画面造成的。您可以将核心启动画面依赖项升级到 1.2.0-alpha01 或更高版本,也可以设置 window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always
  • 可能会有流量较低的屏幕显示被遮挡的界面。验证这些访问次数较少的屏幕是否存在遮挡的界面。流量较低的屏幕包括:
    • 初始配置或登录屏幕
    • “设置”页面
如果您的应用尚未采用边到边设计,应检查哪些方面

如果您的应用尚未采用边到边设计,您很可能受到影响。除了已经采用边到边设计的应用的场景之外,您还应考虑以下情况:

  • 如果您的应用在 Compose 中使用 Material 3 组件 (androidx.compose.material3),例如 TopAppBarBottomAppBarNavigationBar,这些组件可能不会受到影响,因为它们会自动处理边衬区。
  • 如果应用使用的是 Compose 中的 Material 2 组件 (androidx.compose.material),这些组件本身并不会自动处理边衬区。不过,您可以获得边衬区的访问权限,然后手动应用边衬区。在 androidx.compose.material 1.6.0 及更高版本中,使用 windowInsets 参数为 BottomAppBarTopAppBarBottomNavigationNavigationRail 手动应用边衬区。同样,请为 Scaffold 使用 contentWindowInsets 参数。
  • 如果应用使用了 View 和 Material 组件 (com.google.android.material),则大多数基于 View 的 Material 组件(例如 BottomNavigationViewBottomAppBarNavigationRailViewNavigationView)都会处理边衬区,因此不需要执行额外的操作。不过,如果使用 AppBarLayout,则需要添加 android:fitsSystemWindows="true"
  • 对于自定义可组合项,请手动将边衬区应用为内边距。如果您的内容位于 Scaffold 中,您可以使用 Scaffold 内边距值使用内边距。否则,请使用 WindowInsets 之一应用内边距。
  • 如果应用使用的是 View 和 BottomSheetSideSheet 或自定义容器,请使用 ViewCompat.setOnApplyWindowInsetsListener 应用内边距。对于 RecyclerView,请使用此监听器应用内边距,并添加 clipToPadding="false"
如果您的应用必须提供自定义后台保护,应检查哪些方面

如果您的应用必须为三按钮导航栏或状态栏提供自定义背景保护,则应使用 WindowInsets.Type#tappableElement() 获取三按钮导航栏高度或 WindowInsets.Type#statusBars,将可组合项或视图放置在系统栏后面。

其他端到端资源

如需了解有关应用内边距的其他注意事项,请参阅边到边视图边到边 Compose 指南。

已弃用的 API

以下 API 已废弃,但并未停用:

以下 API 已弃用和停用:

Stabile Konfiguration

如果您的应用以 Android 15(API 级别 35)或更高版本为目标平台,Configuration 不再排除系统栏。如果您使用 Configuration 类中的屏幕尺寸进行布局计算,应根据需要将其替换为合适的 ViewGroupWindowInsetsWindowMetricsCalculator 等更好的替代方案。

Configuration 从 API 1 开始提供。它通常从 Activity.onConfigurationChanged 中获取。它提供窗口密度、屏幕方向和尺寸等信息。从 Configuration 返回的窗口大小的一个重要特征是,它之前会排除系统栏。

配置大小通常用于资源选择(例如 /res/layout-h500dp),这仍然是一个有效的用例。不过,我们一直不建议将其用于布局计算。如果确实如此,您应暂时放弃。您应根据自己的用例,将 Configuration 的使用替换为更合适的用法。

如果您使用它来计算布局,请使用适当的 ViewGroup,例如 CoordinatorLayoutConstraintLayout。如果您使用它来确定系统侧边栏的高度,请使用 WindowInsets。如果您想知道应用窗口的当前大小,请使用 computeCurrentWindowMetrics

以下列表介绍了受此变更影响的字段:

Das Attribut „elegantTextHeight“ hat standardmäßig den Wert „true“.

Bei Apps, die auf Android 15 ausgerichtet sind, wird das elegantTextHeight-TextView-Attribut standardmäßig auf true gesetzt. Dabei wird die standardmäßig verwendete kompakte Schriftart durch einige Skripts mit großen vertikalen Messwerten durch eine Schriftart ersetzt, die viel besser lesbar ist. Die kompakte Schriftart wurde eingeführt, um fehlerhafte Layouts zu verhindern. Android 13 (API-Level 33) verhindert viele dieser Fehler, da das Textlayout mithilfe des Attributs fallbackLineSpacing die vertikale Höhe erweitert.

In Android 15 ist die kompakte Schriftart weiterhin im System vorhanden. Daher kann deine App elegantTextHeight auf false setzen, um dasselbe Verhalten wie zuvor zu erzielen, wird aber in zukünftigen Releases wahrscheinlich nicht unterstützt. Wenn deine App also die folgenden Skripts unterstützt: Arabisch, Laotisch, Myanmar, Tamil, Gujarati, Kannada, Malayalam, Ordia, Telugu oder Thai, teste deine App, indem du elegantTextHeight auf true setzt.

elegantTextHeight-Verhalten für Apps, die auf Android 14 (API-Level 34) und niedriger ausgerichtet sind.
elegantTextHeight Verhalten für Apps, die auf Android 15 ausgerichtet sind.

Breite des TextViews ändert sich bei komplexen Buchstabenformen

在以前的 Android 版本中,某些具有复杂形状的手写字体或语言可能会在上一个或下一个字符的区域绘制字母。在某些情况下,此类字母会在开头或结尾处被剪裁。从 Android 15 开始,TextView 会分配宽度,以便为此类字母绘制足够的空间,并允许应用请求向左额外添加内边距以防止剪裁。

由于此更改会影响 TextView 确定宽度的方式,因此如果应用以 Android 15(API 级别 35)或更高版本为目标平台,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" />

Localespezifische Standardzeilenhöhe für EditText

在以前的 Android 版本中,文本布局拉伸了文本的高度,使其适应与当前语言区域匹配的字体的行高。例如,如果内容是日语,由于日语字体的行高比拉丁字体的行高略大,因此文本的高度就略大了。不过,尽管行高存在这些差异,但无论使用何种语言区域,EditText 元素的大小都是一致的,如下图所示:

三个表示 EditText 元素的框,这些框可以包含英语 (en)、日语 (ja) 和缅甸语 (my) 的文本。EditText 的高度相同,即使这两种语言的行高不同。

对于以 Android 15 为目标平台的应用,系统现在会为 EditText 预留最小行高,以匹配指定语言区域的参考字体,如下图所示:

三个表示 EditText 元素的框,这些框可以包含英语 (en)、日语 (ja) 和缅甸语 (my) 的文本。EditText 的高度现在包含空间,可适应这些语言字体的默认行高。

如果需要,您的应用可以通过将 useLocalePreferredLineHeightForMinimum 属性设置为 false 来恢复之前的行为,并且可以通过 Kotlin 和 Java 中的 setMinimumFontMetrics API 设置自定义最小行业指标。

Kamera und Medien

Unter Android 15 werden die folgenden Änderungen am Kamera- und Medienverhalten für Apps vorgenommen, die auf Android 15 oder höher ausgerichtet sind.

Einschränkungen beim Anfordern des Audiofokus

Apps, die auf Android 15 ausgerichtet sind, müssen die Top-App sein oder einen Dienst im Vordergrund ausführen, damit der Audiofokus angefordert werden kann. Wenn eine App versucht, den Fokus anzufordern, obwohl sie eine dieser Anforderungen nicht erfüllt, gibt der Aufruf AUDIOFOCUS_REQUEST_FAILED zurück.

Weitere Informationen zum Audiofokus finden Sie unter Audiofokus verwalten.

Aktualisierte Einschränkungen für Nicht-SDKs

Android 15 enthält aktualisierte Listen eingeschränkter Nicht-SDK-Schnittstellen, die auf der Zusammenarbeit mit Android-Entwicklern und den neuesten internen Tests basieren. Wann immer möglich, achten wir darauf, dass öffentliche Alternativen verfügbar sind, bevor wir Nicht-SDK-Schnittstellen einschränken.

Wenn Ihre App nicht auf Android 15 ausgerichtet ist, wirken sich einige dieser Änderungen möglicherweise nicht sofort auf Sie aus. Es ist zwar möglich, dass Ihre App je nach Ziel-API-Level Ihrer App auf einige Nicht-SDK-Schnittstellen zugreift, die Verwendung von Nicht-SDK-Methoden oder ‑Feldern birgt jedoch immer ein hohes Risiko, dass Ihre App nicht mehr funktioniert.

Wenn Sie sich nicht sicher sind, ob Ihre App Nicht-SDK-Schnittstellen verwendet, können Sie Ihre App testen, um es herauszufinden. Wenn Ihre App nicht auf SDK-Schnittstellen basiert, sollten Sie mit der Planung einer Migration zu SDK-Alternativen beginnen. Uns ist jedoch bewusst, dass es für einige Apps gültige Anwendungsfälle für die Verwendung von Nicht-SDK-Schnittstellen gibt. Wenn Sie keine Alternative zur Verwendung einer nicht SDK-basierten Benutzeroberfläche für eine Funktion in Ihrer App finden, sollten Sie eine neue öffentliche API anfordern.

Weitere Informationen zu den Änderungen in dieser Android-Version finden Sie unter Änderungen an den Einschränkungen für nicht SDK-spezifische Oberflächen in Android 15. Weitere Informationen zu Nicht-SDK-Schnittstellen finden Sie unter Einschränkungen für Nicht-SDK-Schnittstellen.