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
Android 14 erzwingt die Berechtigung BLUETOOTH_CONNECT
beim Aufrufen der
BluetoothAdapter
-Methode getProfileConnectionState()
für App-Targeting
Android 14 (API-Level 34) oder höher
Für diese Methode war bereits die Berechtigung BLUETOOTH_CONNECT
erforderlich, was aber nicht der Fall war
durchgesetzt wird. Achten Sie darauf, dass Ihre App BLUETOOTH_CONNECT
in der
AndroidManifest.xml
wie im folgenden Snippet gezeigt, und prüfen Sie, ob
Ein Nutzer hat die Berechtigung erteilt, bevor er aufgerufen wird.
getProfileConnectionState
<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 Klassejava.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 FlagDISALLOW_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 einIllegalArgumentException
angezeigt. Wenn Sie diese Änderung während des Tests aktivieren oder deaktivieren möchten, aktivieren oder deaktivieren Sie das FlagENABLE_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, obClass.forName("java.lang.ClassValue")
eine Klasse zurückgibt oder nicht. Wenn Ihre App für eine ältere Version der Laufzeit ohne verfügbarejava.lang.ClassValue
-Klasse entwickelt wurde, wird durch diese Optimierungen möglicherweise die MethodecomputeValue
aus Klassen entfernt, die vonjava.lang.ClassValue
abgeleitet sind.
JobScheduler verstärkt Rückruf- und Netzwerkverhalten
Seit der Einführung von JobScheduler wird von Ihrer App erwartet, dass sie innerhalb weniger Sekunden von onStartJob
oder onStopJob
zurückkehrt. Unter Android 14 wird ein Job, der zu lange läuft, angehalten und kehrt geräuschlos zum Status „Fehlgeschlagen“ zurück.
Wenn Ihre App auf Android 14 (API-Level 34) oder höher ausgerichtet ist und
die im Hauptthread gewährte Zeit überschreitet, löst die App einen ANR-Fehler aus
mit der Fehlermeldung „Keine Antwort auf onStartJob
“ oder
„Keine Antwort auf onStopJob
“.
Dieser ANR kann auf zwei Szenarien zurückzuführen sein:
Es gibt eine Aufgabe, die den Haupt-Thread blockiert und verhindert, dass die Rückrufe onStartJob
oder onStopJob
innerhalb des erwarteten Zeitlimits ausgeführt und abgeschlossen werden.
2. Der Entwickler führt Blockierungsarbeiten in JobScheduler aus
Callback onStartJob
oder onStopJob
, wodurch der Callback verhindert wird
die Sie innerhalb der erwarteten Frist abschließen.
Um das Problem mit Nr. 1 zu lösen, müssen Sie weiter untersuchen, was den Hauptthread blockiert.
wenn der ANR-Fehler auftritt, können Sie dies mit
ApplicationExitInfo#getTraceInputStream()
, um den Grabstein zu erhalten
wenn der ANR-Fehler auftritt. Wenn Sie den ANR manuell reproduzieren können, können Sie einen System-Trace aufzeichnen und mit Android Studio oder Perfetto untersuchen, was im Haupt-Thread ausgeführt wird, wenn der ANR auftritt.
Dies kann passieren, wenn Sie die JobScheduler API direkt oder die androidx-Bibliothek WorkManager verwenden.
Um Problem 2 zu beheben, sollten Sie zu WorkManager migrieren. Dieser Dienst unterstützt das Einbetten von Verarbeitungen in onStartJob
oder onStopJob
in einen asynchronen Thread.
Mit JobScheduler
wird außerdem die Anforderung eingeführt, die Berechtigung ACCESS_NETWORK_STATE
anzugeben, wenn die Einschränkung setRequiredNetworkType
oder setRequiredNetwork
verwendet wird. Wenn Ihre App die Berechtigung ACCESS_NETWORK_STATE
beim Planen des Jobs nicht deklariert und auf Android 14 oder höher ausgerichtet ist, führt dies zu einer 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
Teilzugriff auf Fotos und Videos
Mit Android 14 wird der Zugriff auf ausgewählte Fotos eingeführt. Damit können Nutzer Apps Zugriff auf bestimmte Bilder und Videos in ihrer Fotogalerie gewähren, anstatt Zugriff auf alle Medien eines bestimmten Typs zu gewähren.
Diese Änderung ist nur aktiviert, wenn deine App auf Android 14 (API-Level 34) oder höher ausgerichtet ist. Wenn Sie die Bildauswahl noch nicht verwenden, empfehlen wir, sie in Ihrer App zu implementieren. So können Sie Bilder und Videos einheitlich auswählen und die Privatsphäre der Nutzer verbessern, ohne Speicherberechtigungen anfordern zu müssen.
Wenn Sie eine eigene Galerieauswahl mit Speicherberechtigungen verwenden und die volle Kontrolle über Ihre Implementierung haben müssen, 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 die App im Kompatibilitätsmodus aus.
Nutzererfahrung
Sichere Vollbild-Intent-Benachrichtigungen
Mit Android 11 (API-Level 30) konnte jede App Notification.Builder.setFullScreenIntent
verwenden, um Vollbild-Intents zu senden, während das Smartphone gesperrt ist. Sie können dies 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. eingehende Anrufe oder vom Nutzer konfigurierte Weckereinstellungen. Bei Apps, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind, dürfen diese Berechtigungen nur für Apps verwendet werden, die nur Anrufe und Alarme anbieten. Im Google Play Store werden die USE_FULL_SCREEN_INTENT
-Standardberechtigungen für alle Apps widerrufen, die diesem Profil nicht entsprechen. Die Frist für diese Richtlinienänderungen endet am 31. Mai 2024.
Diese Berechtigung bleibt für Apps aktiviert, die auf dem Smartphone installiert wurden, bevor der Nutzer ein Update auf Android 14 durchführt. Nutzer können diese Berechtigung aktivieren oder deaktivieren.
Mit der neuen API NotificationManager.canUseFullScreenIntent
kannst du prüfen, ob deine App die Berechtigung hat. Falls nicht, kann deine App mit dem neuen Intent ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
die Seite mit den Einstellungen öffnen, auf der Nutzer die Berechtigung erteilen 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 Apps ein wie folgt implizite Intents an interne App-Komponenten gesendet werden:
- Implizite Intents werden nur an exportierte Komponenten gesendet. Apps müssen entweder einen expliziten Intent für die Lieferung an nicht exportierte Komponenten verwenden oder Komponente wie exportiert.
- Wenn eine App einen änderbaren ausstehenden Intent mit einem Intent erstellt, der keine eine Komponente oder ein Paket angeben, löst das System eine Ausnahme aus.
Diese Änderungen verhindern, dass schädliche Apps implizite Intents abfangen, die die für die Verwendung durch die internen Komponenten einer App vorgesehen sind.
Hier ist beispielsweise ein Intent Filter, der im in die Manifestdatei Ihrer App ein:
<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 deine App versucht hat, diese Aktivität mit einem impliziten Intent zu starten, ist eine Ausnahme ausgegeben:
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"));
Um die nicht exportierte Aktivität zu starten, sollte Ihre App einen expliziten Intent verwenden stattdessen:
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 und Dienste, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind und kontextregistrierte Empfänger verwenden, müssen mit einem Flag angeben, ob der Empfänger in alle anderen Apps auf dem Gerät exportiert werden soll: entweder RECEIVER_EXPORTED
bzw. RECEIVER_NOT_EXPORTED
.
Diese Anforderung trägt durch die Funktionen für diese Empfänger in Android 13 zum Schutz von Apps vor Sicherheitslücken bei.
Ausnahme für Empfänger, die nur System-Broadcasts empfangen
Wenn Ihre App einen Empfänger nur für System-Broadcasts über Context#registerReceiver
-Methoden wie Context#registerReceiver()
registriert, sollte bei der Registrierung des Empfängers kein Flag angegeben werden.
Sichereres Laden von dynamischem Code
Wenn Ihre App auf Android 14 (API-Level 34) oder höher ausgerichtet ist und dynamischen Code verwendet wird Wird geladen (DCL) müssen alle dynamisch geladenen Dateien als schreibgeschützt markiert sein. Andernfalls gibt das System eine Ausnahme aus. Wir empfehlen, in Apps Code wird dynamisch geladen wenn möglich, da dadurch das Risiko, dass eine App durch Einschleusung oder Manipulation von Code gefährdet ist.
Wenn Sie Code dynamisch laden müssen, verwenden Sie den folgenden Ansatz, um den Parameter dynamisch geladene Datei (z. B. eine DEX-, JAR- oder APK-Datei) sofort schreibgeschützt wenn die Datei geöffnet wird 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 verarbeiten, die bereits vorhanden sind
Um zu verhindern, dass Ausnahmen für vorhandene dynamisch geladene Dateien ausgelöst werden, empfehlen wir, die Dateien zu löschen und neu zu erstellen, bevor Sie versuchen, laden Sie sie erneut in Ihrer App. Befolgen Sie beim Neuerstellen der Dateien wie Sie die Dateien beim Schreiben als schreibgeschützt markieren. Alternativ können Sie beschriften die vorhandenen Dateien als schreibgeschützt. In diesem Fall sollten Sie jedoch unbedingt empfiehlt es sich, zuerst die Integrität der Dateien zu überprüfen (z. B. durch die Signatur der Datei auf einen vertrauenswürdigen Wert prüft), um Ihre App zu schützen vor bösartigen Handlungen.
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, schränkt das System weiter ein, wann Apps Aktivitäten im Hintergrund starten dürfen:
- Wenn eine App eine
PendingIntent
mitPendingIntent#send()
oder ähnlichen Methoden sendet, muss sie die Option aktivieren, wenn sie Berechtigungen zum Starten von Hintergrundaktivitäten gewähren möchte, um den ausstehenden Intent zu starten. Wenn Sie die Funktion aktivieren möchten, muss die App einActivityOptions
-Bundle mitsetPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
übergeben. - Wenn eine sichtbare App einen Dienst einer anderen App bindet, die im Hintergrund ausgeführt wird
bindService()
-Methode aktiviert, muss die sichtbare App wenn er dem Nutzer eigene Berechtigungen zum Starten von Hintergrundaktivitäten erteilen möchte. gebundenen Dienst. Wenn Sie die Funktion aktivieren möchten, muss die App das FlagBIND_ALLOW_ACTIVITY_STARTS
beim Aufrufen der MethodebindService()
enthalten.
Durch diese Änderungen werden die bestehenden Einschränkungen erweitert, indem Sie verhindern, dass schädliche Apps APIs missbrauchen und dadurch Unterbrechungen verursachen. Aktivitäten im Hintergrund.
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.
Nutzereinwilligung für jede MediaProjection-Erfassungssitzung erforderlich
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:
- Ihre App speichert das von
MediaProjectionManager#createScreenCaptureIntent
zurückgegebeneIntent
im Cache und übergibt es mehrmals anMediaProjectionManager#getMediaProjection
. - Ihre Anwendung ruft
MediaProjection#createVirtualDisplay
mehrmals auf derselbenMediaProjection
-Instanz auf.
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:
- Rufen Sie
VirtualDisplay#resize
mit der neuen Breite und Höhe auf. - Geben Sie einen neuen
Surface
mit der neuen Breite und Höhe fürVirtualDisplay#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 mit eingeschränktem Nicht-SDK Benutzeroberflächen basierend auf der Zusammenarbeit mit Android-Entwicklern internen Tests. 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. Obwohl Sie derzeit einige Nicht-SDK-Schnittstellen (abhängig von der Ziel-API Ihrer App Level) die Verwendung einer Nicht-SDK-Methode oder eines Nicht-SDK-Felds birgt immer ein hohes Risiko, dass Ihre
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 benötigt, sollten Sie mit der Planung eine Migration zu SDK-Alternativen. 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 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.