Wie bei früheren Releases enthält Android 14 Verhaltensänderungen, die sich auf Ihre 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 Ihre App auf Android 14 oder höher ausgerichtet ist, sollten Sie sie gegebenenfalls so ändern, dass sie diese Verhaltensweisen korrekt unterstützt.
Sehen Sie sich auch die Liste der Verhaltensänderungen an, die sich auf alle Apps auswirken, die auf Android 14 ausgeführt werden, unabhängig von der targetSdkVersion
der App.
Hauptfunktion
Arten von Diensten im Vordergrund sind erforderlich
Wenn Ihre App auf Android 14 (API-Level 34) oder höher ausgerichtet ist, muss für jeden Dienst im Vordergrund in Ihrer App mindestens ein Typ von Dienst im Vordergrund angegeben werden. Wählen Sie einen Typ von Dienst im Vordergrund aus, der den Anwendungsfall Ihrer App darstellt. Das System erwartet, dass Dienste im Vordergrund mit einem bestimmten Typ einen bestimmten Anwendungsfall erfüllen.
Wenn ein Anwendungsfall in Ihrer App mit keinem dieser Typen verknüpft ist, sollten Sie Ihre Logik unbedingt auf WorkManager oder vom Nutzer initiierte Datenübertragungsjobs umstellen.
Erzwingung der Berechtigung BLUETOOTH_CONNECT in BluetoothAdapter
Android 14 enforces the BLUETOOTH_CONNECT
permission when calling the
BluetoothAdapter
getProfileConnectionState()
method for apps targeting
Android 14 (API level 34) or higher.
This method already required the BLUETOOTH_CONNECT
permission, but it was not
enforced. Make sure your app declares BLUETOOTH_CONNECT
in your app's
AndroidManifest.xml
file as shown in the following snippet and check that
a user has granted the permission before calling
getProfileConnectionState
.
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
OpenJDK 17-Updates
Mit Android 14 werden die Kernbibliotheken von Android weiter aktualisiert, um sie an die Funktionen der neuesten OpenJDK LTS-Releases anzupassen. 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 App-Kompatibilität auswirken:
- Änderungen an regulären Ausdrücken: Ungültige Gruppenreferenzen sind jetzt nicht mehr zulässig, um der Semantik von OpenJDK besser zu entsprechen. Es kann vorkommen, dass die Klasse
java.util.regex.Matcher
eineIllegalArgumentException
auslöst. Testen Sie Ihre App daher auf Bereiche, in denen reguläre Ausdrücke verwendet werden. Wenn Sie diese Änderung während des Tests aktivieren oder deaktivieren möchten, können Sie das FlagDISALLOW_INVALID_GROUP_REFERENCE
mit den Tools des Compatibility Framework umschalten. - UUID-Verarbeitung: Bei der
java.util.UUID.fromString()
-Methode werden jetzt strengere Prüfungen bei der Validierung des Eingabearguments durchgeführt. Daher wird bei der Deserialisierung möglicherweise eineIllegalArgumentException
angezeigt. Wenn Sie diese Änderung während des Tests aktivieren oder deaktivieren möchten, können Sie das FlagENABLE_STRICT_VALIDATION
mit den Tools des Compatibility Framework umschalten. - ProGuard-Probleme: In einigen Fällen führt das Hinzufügen der Klasse
java.lang.ClassValue
zu Problemen, wenn Sie versuchen, Ihre App mit ProGuard zu verkleinern, zu verschleiern und zu optimieren. Das Problem stammt aus einer Kotlin-Bibliothek, die das Laufzeitverhalten ändert, je nachdem, obClass.forName("java.lang.ClassValue")
eine Klasse zurückgibt oder nicht. Wenn Ihre App für eine ältere Version der Laufzeit entwickelt wurde, für die die Klassejava.lang.ClassValue
nicht verfügbar ist, wird durch diese Optimierungen möglicherweise die MethodecomputeValue
aus Klassen entfernt, die vonjava.lang.ClassValue
abgeleitet sind.
JobScheduler verstärkt Callback- 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, the job is stopped 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
".
This ANR may be a result of 2 scenarios:
1. There is work blocking the main thread, preventing the callbacks onStartJob
or onStopJob
from executing and completing within the expected time limit.
2. The developer is running blocking work within the JobScheduler
callback onStartJob
or onStopJob
, preventing the callback from
completing within the expected time limit.
To address #1, you will need to further debug what is blocking the main thread
when the ANR occurs, you can do this using
ApplicationExitInfo#getTraceInputStream()
to get the tombstone
trace when the ANR occurs. If you're able to manually reproduce the ANR,
you can record a system trace and inspect the trace using either
Android Studio or Perfetto to better understand what is running on
the main thread when the ANR occurs.
Note that this can happen when using JobScheduler API directly
or using the androidx library WorkManager.
To address #2, consider migrating to WorkManager, which provides
support for wrapping any processing in onStartJob
or onStopJob
in an asynchronous 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
Bei Apps, die auf Android 14 und höher ausgerichtet sind, wird TileService#startActivityAndCollapse(Intent)
nicht mehr unterstützt und löst beim Aufruf eine Ausnahme aus. Wenn deine App Aktivitäten von Kacheln aus startet, verwende
TileService#startActivityAndCollapse(PendingIntent)
.
Datenschutz
Teilweiser Zugriff auf Fotos und Videos
Mit Android 14 wird der Zugriff auf ausgewählte Fotos eingeführt. Nutzer können Apps so Zugriff auf bestimmte Bilder und Videos in ihrer Mediathek gewähren, anstatt Zugriff auf alle Medien eines bestimmten Typs zu gewähren.
Diese Änderung ist nur aktiviert, wenn Ihre App auf Android 14 (API-Level 34) oder höher ausgerichtet ist. Wenn Sie die Bildauswahl noch nicht verwenden, empfehlen wir Ihnen, sie in Ihrer App zu implementieren. So können Sie Bilder und Videos einheitlich auswählen und gleichzeitig den Datenschutz für Nutzer verbessern, ohne Speicherberechtigungen anfordern zu müssen.
Wenn Sie Ihre eigene Galerieauswahl mit Speicherberechtigungen verwalten und die vollständige Kontrolle über Ihre Implementierung behalten möchten, passen Sie Ihre Implementierung an, um die neue Berechtigung READ_MEDIA_VISUAL_USER_SELECTED
zu verwenden. Wenn Ihre App die neue Berechtigung nicht verwendet, führt das System Ihre App im Kompatibilitätsmodus aus.
Nutzererfahrung
Sichere Vollbild-Intent-Benachrichtigungen
Unter Android 11 (API-Level 30) konnte jede App mit Notification.Builder.setFullScreenIntent
Vollbild-Intents senden, während das Smartphone gesperrt war. Sie können diese Berechtigung bei der App-Installation automatisch gewähren, indem Sie die Berechtigung USE_FULL_SCREEN_INTENT
im AndroidManifest deklarieren.
Full-Screen-Intent-Benachrichtigungen sind für Benachrichtigungen mit extrem hoher Priorität gedacht, die die sofortige Aufmerksamkeit des Nutzers erfordern, z. B. ein eingehender Anruf oder vom Nutzer konfigurierte Weckereinstellungen. Bei Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, dürfen diese Berechtigung nur von Apps verwendet werden, die nur Anrufe und Wecker bereitstellen. Der Google Play Store widerruft die standardmäßigen USE_FULL_SCREEN_INTENT
-Berechtigungen für alle Apps, die nicht zu diesem Profil passen. Der Termin für die Umsetzung dieser Richtlinienänderungen ist der 31. Mai 2024.
Diese Berechtigung bleibt für Apps aktiviert, die auf dem Smartphone installiert wurden, bevor der Nutzer auf Android 14 aktualisiert hat. Nutzer können diese Berechtigung aktivieren und deaktivieren.
Mit der neuen API NotificationManager.canUseFullScreenIntent
können Sie prüfen, ob Ihre App die Berechtigung hat. Andernfalls kann Ihre App die neue Intent-Funktion ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
verwenden, um die Seite mit den Einstellungen aufzurufen, auf der Nutzer die Berechtigung gewähren können.
Sicherheit
Einschränkungen für implizite und ausstehende Intents
Bei Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, schränkt Android so ein, dass Apps implizite Intents an interne App-Komponenten senden:
- Implizite Intents werden nur an exportierte Komponenten gesendet. Anwendungen müssen entweder einen expliziten Intent für die Übermittlung an nicht exportierte Komponenten verwenden oder die Komponente als exportiert markieren.
- Wenn eine App ein veränderliches ausstehendes Intent mit einem Intent erstellt, in dem keine Komponente oder kein Paket angegeben ist, löst das System eine Ausnahme aus.
Diese Änderungen verhindern, dass schädliche Anwendungen implizite Intents abfangen, die von den internen Komponenten einer Anwendung verwendet werden sollen.
Hier sehen Sie beispielsweise einen Intent-Filter, der in der Manifestdatei Ihrer App deklariert werden könnte:
<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>
Wenn Ihre App versucht, diese Aktivität mit einem impliziten Intent zu starten, wird eine ActivityNotFoundException
-Ausnahme geworfen:
Kotlin
// Throws an ActivityNotFoundException exception when targeting Android 14. context.startActivity(Intent("com.example.action.APP_ACTION"))
Java
// Throws an ActivityNotFoundException exception when targeting Android 14. context.startActivity(new Intent("com.example.action.APP_ACTION"));
Um die nicht exportierte Aktivität zu starten, sollte Ihre App stattdessen einen expliziten Intent verwenden:
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);
Für Laufzeit registrierte Übertragungsempfänger muss das Exportverhalten angegeben werden
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 dynamischen Codes
If your app targets Android 14 (API level 34) or higher and uses Dynamic Code Loading (DCL), all dynamically-loaded files must be marked as read-only. Otherwise, the system throws an exception. We recommend that apps avoid dynamically loading code whenever possible, as doing so greatly increases the risk that an app can be compromised by code injection or code tampering.
If you must dynamically load code, use the following approach to set the dynamically-loaded file (such as a DEX, JAR, or APK file) as read-only as soon as the file is opened and before any content is written:
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);
Handle dynamically-loaded files that already exist
To prevent exceptions from being thrown for existing dynamically-loaded files, we recommend deleting and recreating the files before you try to dynamically load them again in your app. As you recreate the files, follow the preceding guidance for marking the files read-only at write time. Alternatively, you can re-label the existing files as read-only, but in this case, we strongly recommend that you verify the integrity of the files first (for example, by checking the file's signature against a trusted value), to help protect your app from malicious actions.
Zusätzliche Einschränkungen beim Starten von Aktivitäten im Hintergrund
For apps targeting Android 14 (API level 34) or higher, the system further restricts when apps are allowed to start activities from the background:
- When an app sends a
PendingIntent
usingPendingIntent#send()
or similar methods, the app must opt in if it wants to grant its own background activity launch privileges to start the pending intent. To opt in, the app should pass anActivityOptions
bundle withsetPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
. - When a visible app binds a service of another app that's in the background
using the
bindService()
method, the visible app must now opt in if it wants to grant its own background activity launch privileges to the bound service. To opt in, the app should include theBIND_ALLOW_ACTIVITY_STARTS
flag when calling thebindService()
method.
These changes expand the existing set of restrictions to protect users by preventing malicious apps from abusing APIs to start disruptive activities from the background.
Zip Path Traversal
Bei Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, verhindert Android die ZIP-Path Traversal-Sicherheitslücke auf folgende Weise: ZipFile(String)
und ZipInputStream.getNextEntry()
werfen eine ZipException
aus, wenn die Namen von ZIP-Dateieinträgen „..“ enthalten oder mit „/“ beginnen.
Apps können diese Bestätigung deaktivieren, indem sie dalvik.system.ZipPathValidator.clearCallback()
aufrufen.
Nutzereinwilligung ist für jede Aufnahmesitzung von MediaProjection erforderlich
For apps targeting Android 14 (API level 34) or higher, a SecurityException
is
thrown by MediaProjection#createVirtualDisplay
in either of the following
scenarios:
- Your app caches the
Intent
that is returned fromMediaProjectionManager#createScreenCaptureIntent
, and passes it multiple times toMediaProjectionManager#getMediaProjection
. - Your app invokes
MediaProjection#createVirtualDisplay
multiple times on the sameMediaProjection
instance.
Your app must ask the user to give consent before each capture session. A single
capture session is a single invocation on
MediaProjection#createVirtualDisplay
, and each MediaProjection
instance must
be used only once.
Handle configuration changes
If your app needs to invoke MediaProjection#createVirtualDisplay
to handle
configuration changes (such as the screen orientation or screen size changing),
you can follow these steps to update the VirtualDisplay
for the existing
MediaProjection
instance:
- Invoke
VirtualDisplay#resize
with the new width and height. - Provide a new
Surface
with the new width and height toVirtualDisplay#setSurface
.
Register a callback
Your app should register a callback to handle cases where the user doesn't grant
consent to continue a capture session. To do this, implement
Callback#onStop
and have your app release any related resources (such as
the VirtualDisplay
and Surface
).
If your app doesn't register this callback,
MediaProjection#createVirtualDisplay
throws an IllegalStateException
when your app invokes it.
Aktualisierte Einschränkungen für Nicht-SDKs
Android 14 enthält aktualisierte Listen eingeschränkter nicht SDK-basierter Schnittstellen, die auf der Zusammenarbeit mit Android-Entwicklern und den neuesten internen Tests basieren. Wir sorgen nach Möglichkeit dafür, dass öffentliche Alternativen verfügbar sind, bevor wir Nicht-SDK-Schnittstellen einschränken.
Wenn Ihre App nicht auf Android 14 ausgerichtet ist, wirken sich einige dieser Änderungen möglicherweise nicht sofort auf Sie aus. Derzeit können Sie jedoch einige Nicht-SDK-Schnittstellen verwenden (je nach Ziel-API-Level Ihrer App). Die Verwendung von Nicht-SDK-Methoden oder ‑Feldern birgt jedoch immer ein hohes Risiko, dass Ihre App nicht mehr funktioniert.
Wenn Sie nicht sicher sind, ob Ihre App Nicht-SDK-Schnittstellen verwendet, können Sie Ihre App testen, um das herauszufinden. Wenn Ihre App Nicht-SDK-Schnittstellen verwendet, 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-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-Schnittstellen in Android 14. Weitere Informationen zu Nicht-SDK-Schnittstellen finden Sie unter Einschränkungen für Nicht-SDK-Schnittstellen.