Änderungen beim Verhalten: Apps, die auf Android 14 oder höher ausgerichtet sind

Wie in früheren Releases umfasst Android 14 Verhaltensänderungen, die sich auf deine App auswirken können. Die folgenden Verhaltensänderungen gelten ausschließlich für Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind. Wenn deine App auf Android 14 oder höher ausgerichtet ist, solltest du sie gegebenenfalls anpassen, um diese Verhaltensweisen zu unterstützen.

Sieh dir auch die Liste der Verhaltensänderungen an, die alle Apps unter Android 14 betreffen, unabhängig von targetSdkVersion der App.

Hauptfunktion

Typen von Diensten im Vordergrund sind erforderlich

Wenn deine App auf Android 14 (API-Level 34) oder höher ausgerichtet ist, muss mindestens ein Diensttyp im Vordergrund für jeden Dienst im Vordergrund innerhalb deiner App angegeben werden. Du solltest einen Typ auswählen, der den Anwendungsfall deiner App im Vordergrund repräsentiert. Das System erwartet Dienste im Vordergrund eines bestimmten Typs, die einem bestimmten Anwendungsfall entsprechen.

Wenn ein Anwendungsfall in Ihrer Anwendung keinem dieser Typen zugeordnet ist, sollten Sie Ihre Logik auf die Verwendung von WorkManager oder vom Nutzer initiierten Datenübertragungsjobs migrieren.

Erzwingung der Berechtigung BLUETOOTH_CONNECT im BluetoothAdapter

Unter Android 14 wird die Berechtigung BLUETOOTH_CONNECT beim Aufrufen der Methode BluetoothAdapter getProfileConnectionState() für Apps erzwungen, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind.

Für diese Methode war bereits die Berechtigung BLUETOOTH_CONNECT erforderlich, diese wurde aber nicht erzwungen. Achte darauf, dass deine App BLUETOOTH_CONNECT in der Datei AndroidManifest.xml deiner App deklariert, wie im folgenden Snippet gezeigt, und prüfe, ob ein Nutzer die Berechtigung erteilt hat, bevor du getProfileConnectionState aufrufst.

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

Updates zu OpenJDK 17

Unter Android 14 werden die Kernbibliotheken von Android fortlaufend aktualisiert, damit sie den Funktionen der neuesten OpenJDK-LTS-Releases entsprechen. Dazu gehören sowohl Bibliotheksupdates als auch die Java 17-Sprachunterstützung für App- und Plattformentwickler.

Einige dieser Änderungen können sich auf die Kompatibilität der App auswirken:

  • Änderungen an regulären Ausdrücken: Ungültige Gruppenverweise dürfen jetzt nicht mehr der Semantik von OpenJDK mehr entsprechen. Es kann vorkommen, dass ein IllegalArgumentException von der Klasse java.util.regex.Matcher ausgegeben wird. Testen Sie Ihre Anwendung daher auf Bereiche, in denen reguläre Ausdrücke verwendet werden. Wenn Sie diese Änderung beim Testen aktivieren oder deaktivieren möchten, aktivieren oder deaktivieren Sie das Flag DISALLOW_INVALID_GROUP_REFERENCE mit den Kompatibilitäts-Framework-Tools.
  • UUID-Verarbeitung: Die Methode java.util.UUID.fromString() führt jetzt bei der Validierung des Eingabearguments strengere Prüfungen durch. Daher wird während der Deserialisierung möglicherweise ein IllegalArgumentException angezeigt. Wenn Sie diese Änderung während des Tests aktivieren oder deaktivieren möchten, aktivieren oder deaktivieren Sie das Flag ENABLE_STRICT_VALIDATION mit den Kompatibilitäts-Framework-Tools.
  • ProGuard-Probleme: In einigen Fällen verursacht das Hinzufügen der Klasse java.lang.ClassValue ein Problem, wenn Sie versuchen, Ihre App mit ProGuard zu verkleinern, zu verschleiern und zu optimieren. Das Problem beruht auf einer Kotlin-Bibliothek, die das Laufzeitverhalten abhängig davon ändert, ob Class.forName("java.lang.ClassValue") eine Klasse zurückgibt oder nicht. Wenn Ihre App für eine ältere Version der Laufzeit ohne verfügbare java.lang.ClassValue-Klasse entwickelt wurde, wird durch diese Optimierungen möglicherweise die Methode computeValue aus Klassen entfernt, die von java.lang.ClassValue abgeleitet sind.

JobScheduler verstärkt Rückruf- und Netzwerkverhalten

Since its introduction, JobScheduler expects your app to return from onStartJob or onStopJob within a few seconds. Prior to Android 14, if a job runs too long, it stops and fails silently. If your app targets Android 14 (API level 34) or higher and exceeds the granted time on the main thread, the app triggers an ANR with the error message "No response to onStartJob" or "No response to onStopJob". Consider migrating to WorkManager, which provides support for asynchronous processing or migrating any heavy work into a background thread.

JobScheduler also introduces a requirement to declare the ACCESS_NETWORK_STATE permission if using setRequiredNetworkType or setRequiredNetwork constraint. If your app does not declare the ACCESS_NETWORK_STATE permission when scheduling the job and is targeting Android 14 or higher, it will result in a SecurityException.

Tiles Launch API

Für Apps, die auf 14 und höher ausgerichtet sind, wurde TileService#startActivityAndCollapse(Intent) verworfen und löst beim Aufruf eine Ausnahme aus. Wenn Ihre App Aktivitäten über Kacheln startet, verwenden Sie stattdessen TileService#startActivityAndCollapse(PendingIntent).

Datenschutz

Teilzugriff auf Fotos und Videos

Android 14 introduces Selected Photos Access, which allows users to grant apps access to specific images and videos in their library, rather than granting access to all media of a given type.

This change is only enabled if your app targets Android 14 (API level 34) or higher. If you don't use the photo picker yet, we recommend implementing it in your app to provide a consistent experience for selecting images and videos that also enhances user privacy without having to request any storage permissions.

If you maintain your own gallery picker using storage permissions and need to maintain full control over your implementation, adapt your implementation to use the new READ_MEDIA_VISUAL_USER_SELECTED permission. If your app doesn't use the new permission, the system runs your app in a compatibility mode.

Nutzererfahrung

Sichere Vollbild-Intent-Benachrichtigungen

With Android 11 (API level 30), it was possible for any app to use Notification.Builder.setFullScreenIntent to send full-screen intents while the phone is locked. You could auto-grant this on app install by declaring USE_FULL_SCREEN_INTENT permission in the AndroidManifest.

Full-screen intent notifications are designed for extremely high-priority notifications demanding the user's immediate attention, such as an incoming phone call or alarm clock settings configured by the user. For apps targeting Android 14 (API level 34) or higher, apps that are allowed to use this permission are limited to those that provide calling and alarms only. The Google Play Store revokes default USE_FULL_SCREEN_INTENT permissions for any apps that don't fit this profile. The deadline for these policy changes is May 31, 2024.

This permission remains enabled for apps installed on the phone before the user updates to Android 14. Users can turn this permission on and off.

You can use the new API NotificationManager.canUseFullScreenIntent to check if your app has the permission; if not, your app can use the new intent ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT to launch the settings page where users can grant the permission.

Sicherheit

Einschränkungen für implizite und ausstehende Intents

For apps targeting Android 14 (API level 34) or higher, Android restricts apps from sending implicit intents to internal app components in the following ways:

  • Implicit intents are only delivered to exported components. Apps must either use an explicit intent to deliver to unexported components, or mark the component as exported.
  • If an app creates a mutable pending intent with an intent that doesn't specify a component or package, the system throws an exception.

These changes prevent malicious apps from intercepting implicit intents that are intended for use by an app's internal components.

For example, here is an intent filter that could be declared in your app's manifest file:

<activity
    android:name=".AppActivity"
    android:exported="false">
    <intent-filter>
        <action android:name="com.example.action.APP_ACTION" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

If your app tried to launch this activity using an implicit intent, an exception would be thrown:

Kotlin

// Throws an exception when targeting Android 14.
context.startActivity(Intent("com.example.action.APP_ACTION"))

Java

// Throws an exception when targeting Android 14.
context.startActivity(new Intent("com.example.action.APP_ACTION"));

To launch the non-exported activity, your app should use an explicit intent instead:

Kotlin

// This makes the intent explicit.
val explicitIntent =
        Intent("com.example.action.APP_ACTION")
explicitIntent.apply {
    package = context.packageName
}
context.startActivity(explicitIntent)

Java

// This makes the intent explicit.
Intent explicitIntent =
        new Intent("com.example.action.APP_ACTION")
explicitIntent.setPackage(context.getPackageName());
context.startActivity(explicitIntent);

Empfänger von laufzeitregistrierten Broadcasts müssen das Exportverhalten festlegen

Apps and services that target Android 14 (API level 34) or higher and use context-registered receivers are required to specify a flag to indicate whether or not the receiver should be exported to all other apps on the device: either RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED, respectively. This requirement helps protect apps from security vulnerabilities by leveraging the features for these receivers introduced in Android 13.

Exception for receivers that receive only system broadcasts

If your app is registering a receiver only for system broadcasts through Context#registerReceiver methods, such as Context#registerReceiver(), then it shouldn't specify a flag when registering the receiver.

Sichereres Laden von dynamischem Code

Wenn Ihre App auf Android 14 (API-Level 34) oder höher ausgerichtet ist und Dynamic Code Loading (DCL) verwendet, müssen alle dynamisch geladenen Dateien als schreibgeschützt markiert werden. Andernfalls gibt das System eine Ausnahme aus. Wir empfehlen, dass Apps Code möglichst nicht dynamisch laden, da sich so das Risiko erheblich erhöht, dass eine App durch Codeinjektion oder Codemanipulation manipuliert werden kann.

Wenn Sie Code dynamisch laden müssen, verwenden Sie den folgenden Ansatz, um die dynamisch geladene Datei (z. B. eine DEX-, JAR- oder APK-Datei) als schreibgeschützt festzulegen, sobald die Datei geöffnet und bevor Inhalte geschrieben werden:

Kotlin

val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
    // Set the file to read-only first to prevent race conditions
    jar.setReadOnly()
    // Then write the actual file content
}
val cl = PathClassLoader(jar, parentClassLoader)

Java

File jar = new File("DYNAMICALLY_LOADED_FILE.jar");
try (FileOutputStream os = new FileOutputStream(jar)) {
    // Set the file to read-only first to prevent race conditions
    jar.setReadOnly();
    // Then write the actual file content
} catch (IOException e) { ... }
PathClassLoader cl = new PathClassLoader(jar, parentClassLoader);

Dynamisch geladene Dateien bearbeiten, die bereits vorhanden sind

Damit für vorhandene dynamisch geladene Dateien keine Ausnahmen ausgelöst werden, empfehlen wir, die Dateien zu löschen und neu zu erstellen, bevor Sie versuchen, sie wieder dynamisch in Ihre App zu laden. Folgen Sie beim Neuerstellen der Dateien der Anleitung oben, um die Dateien beim Schreiben als schreibgeschützt zu markieren. Alternativ können Sie die vorhandenen Dateien als schreibgeschützt kennzeichnen. In diesem Fall empfehlen wir jedoch dringend, zuerst die Integrität der Dateien zu prüfen (z. B. indem Sie die Signatur der Datei mit einem vertrauenswürdigen Wert vergleichen), um Ihre Anwendung vor schädlichen Aktionen zu schützen.

Zusätzliche Einschränkungen beim Starten von Aktivitäten im Hintergrund

Bei Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, wird durch das System weiter eingeschränkt, wann Apps Aktivitäten im Hintergrund starten dürfen:

  • Wenn eine App eine PendingIntent mit PendingIntent#send() oder ähnlichen Methoden sendet, muss die App zustimmen, wenn sie ihre eigenen Berechtigungen zum Starten von Hintergrundaktivitäten gewähren möchte, um den ausstehenden Intent zu starten. Zur Aktivierung muss die App ein ActivityOptions-Bundle mit setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED) übergeben.
  • Wenn eine sichtbare Anwendung einen Dienst einer anderen Anwendung, die sich im Hintergrund mit der Methode bindService() befindet, bindet, muss die sichtbare Anwendung jetzt aktivieren, wenn sie dem gebundenen Dienst ihre eigenen Berechtigungen zum Starten von Hintergrundaktivitäten gewähren möchte. Zum Aktivieren muss die App beim Aufrufen der Methode bindService() das Flag BIND_ALLOW_ACTIVITY_STARTS enthalten.

Durch diese Änderungen werden die bestehenden Einschränkungen erweitert, um Nutzer zu schützen. Es wird verhindert, dass schädliche Anwendungen APIs missbrauchen und störende Aktivitäten im Hintergrund auslösen.

Zip Path Traversal (Pfaddurchlauf mit ZIP-Datei)

Bei Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, verhindert Android die Sicherheitslücke beim ZIP-Pfaddurchlauf auf folgende Weise: ZipFile(String) und ZipInputStream.getNextEntry() gibt ZipException aus, wenn die Namen der ZIP-Dateieinträge „..“ enthalten oder mit „/“ beginnen.

Apps können diese Überprüfung durch Aufrufen von dalvik.system.ZipPathValidator.clearCallback() deaktivieren.

Für Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, wird in einem der folgenden Szenarien von MediaProjection#createVirtualDisplay ein SecurityException ausgelöst:

In Ihrer App muss der Nutzer vor jeder Aufnahme um seine Einwilligung gebeten werden. Eine einzelne Erfassungssitzung ist ein einzelner Aufruf von MediaProjection#createVirtualDisplay. Jede MediaProjection-Instanz darf nur einmal verwendet werden.

Umgang mit Konfigurationsänderungen

Wenn Ihre Anwendung MediaProjection#createVirtualDisplay aufrufen muss, um Konfigurationsänderungen wie Änderungen der Bildschirmausrichtung oder der Bildschirmgröße zu verarbeiten, können Sie die folgenden Schritte ausführen, um VirtualDisplay für die vorhandene MediaProjection-Instanz zu aktualisieren:

  1. Rufen Sie VirtualDisplay#resize mit der neuen Breite und Höhe auf.
  2. Geben Sie einen neuen Surface mit der neuen Breite und Höhe für VirtualDisplay#setSurface an.

Rückruf registrieren

Ihre App sollte einen Callback für den Fall registrieren, in dem der Nutzer keine Einwilligung zum Fortsetzen einer Erfassungssitzung erteilt. Implementieren Sie dazu Callback#onStop und lassen Sie Ihre App alle zugehörigen Ressourcen wie VirtualDisplay und Surface veröffentlichen.

Wenn deine App diesen Callback nicht registriert, MediaProjection#createVirtualDisplay gibt ein IllegalStateException aus, wenn deine App ihn aufruft.

Nicht-SDK-Einschränkungen aktualisiert

Android 14 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 deine App nicht auf Android 14 ausgerichtet ist, betreffen dich einige dieser Änderungen möglicherweise nicht sofort. Derzeit können Sie zwar einige Nicht-SDK-Schnittstellen verwenden (je nach Ziel-API-Level Ihrer App), aber bei Verwendung von Nicht-SDK-Methoden und -Feldern besteht immer ein hohes Risiko, dass Ihre App nicht mehr funktioniert.

Wenn du nicht sicher bist, ob deine App Nicht-SDK-Schnittstellen verwendet, kannst du die App testen, um es herauszufinden. Wenn Ihre App Nicht-SDK-Schnittstellen benötigt, sollten Sie eine Migration zu SDK-Alternativen planen. Uns ist aber bewusst, dass es bei einigen Apps gültige Anwendungsfälle für die Verwendung von Nicht-SDK-Schnittstellen gibt. Wenn Sie für ein Feature in Ihrer App keine Alternative zur Verwendung einer Nicht-SDK-Schnittstelle finden, sollten Sie eine neue öffentliche API anfordern.

Weitere Informationen zu den Änderungen in diesem Android-Release finden Sie unter Aktualisierungen der Einschränkungen für Schnittstellen, die nicht auf SDK basieren, unter Android 14. Allgemeine Informationen zu Nicht-SDK-Schnittstellen finden Sie unter Einschränkungen für Nicht-SDK-Schnittstellen.