Wie bei früheren Versionen 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 anpassen, dass sie diese Verhaltensweisen richtig unterstützt.
Sehen Sie sich auch die Liste der Verhaltensänderungen an, die sich auf alle Apps auswirken, die unter Android 14 ausgeführt werden, unabhängig vom targetSdkVersion der App.
Hauptfunktion
Typen von Diensten im Vordergrund sind erforderlich
如果您的应用以 Android 14(API 级别 34)或更高版本为目标平台,则必须为应用中的每个前台服务至少指定一项前台服务类型。您应选择一个能代表应用用例的前台服务类型。系统需要特定类型的前台服务满足特定用例。
如果应用中的用例与这些类型均不相关,强烈建议您迁移逻辑以使用 WorkManager 或用户发起的数据传输作业。
Erzwingen der BLUETOOTH_CONNECT-Berechtigung in BluetoothAdapter
Unter Android 14 wird die Berechtigung BLUETOOTH_CONNECT erzwungen, wenn die Methode BluetoothAdapter getProfileConnectionState() für Apps aufgerufen wird, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind.
Für diese Methode war bereits die Berechtigung BLUETOOTH_CONNECT erforderlich, sie wurde jedoch nicht erzwungen. Deklarieren Sie BLUETOOTH_CONNECT in der Datei AndroidManifest.xml Ihrer App wie im folgenden Snippet gezeigt und prüfen Sie, ob ein Nutzer die Berechtigung erteilt hat, bevor Sie getProfileConnectionState aufrufen.
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
OpenJDK 17-Updates
Android 14 将继续更新 Android 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致,包括适合应用和平台开发者的库更新和 Java 17 语言支持。
以下变更可能会影响应用兼容性:
- 对正则表达式的更改:现在,为了更严格地遵循 OpenJDK 的语义,不允许无效的组引用。您可能会看到
java.util.regex.Matcher类抛出IllegalArgumentException的新情况,因此请务必测试应用中使用正则表达式的情形。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换DISALLOW_INVALID_GROUP_REFERENCE标志。 - UUID 处理:现在,验证输入参数时,
java.util.UUID.fromString()方法会执行更严格的检查,因此您可能会在反序列化期间看到IllegalArgumentException。如需在测试期间启用或停用此变更,请使用兼容性框架工具切换ENABLE_STRICT_VALIDATION标志。 - ProGuard 问题:有时,在您尝试使用 ProGuard 缩减、混淆和优化应用时,添加
java.lang.ClassValue类会导致问题。问题源自 Kotlin 库,该库会根据Class.forName("java.lang.ClassValue")是否会返回类更改运行时行为。如果您的应用是根据没有java.lang.ClassValue类的旧版运行时开发的,则这些优化可能会将computeValue方法从派生自java.lang.ClassValue的类中移除。
JobScheduler erzwingt Callback- 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.
API zum Starten von Kacheln
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
Full-Screen Intent-Benachrichtigungen schützen
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 zur Laufzeit registrierte Übertragungsempfänger muss das Exportverhalten angegeben werden
Bei Apps und Diensten, die auf Android 14 (API-Level 34) oder höher ausgerichtet sind und kontextregistrierte Empfänger verwenden, muss ein Flag angegeben werden, um anzugeben, ob der Empfänger in alle anderen Apps auf dem Gerät exportiert werden soll: entweder RECEIVER_EXPORTED oder RECEIVER_NOT_EXPORTED.
Diese Anforderung trägt dazu bei, Apps vor Sicherheitslücken zu schützen, indem die in Android 13 eingeführten Funktionen für diese Empfänger genutzt werden.
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
如果您的应用以 Android 14(API 级别 34)或更高版本为目标平台并使用动态代码 正在加载 (DCL),所有动态加载的文件都必须标记为只读。 否则,系统会抛出异常。我们建议应用尽可能避免动态加载代码,因为这样做会大大增加应用因代码注入或代码篡改而遭到入侵的风险。
如果必须动态加载代码,请使用以下方法,在动态文件(例如 DEX、JAR 或 APK 文件)打开并写入任何内容之前立即将其设为只读:
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);
处理已存在的动态加载文件
为防止系统对现有动态加载的文件抛出异常,我们建议您先删除并重新创建文件,然后再尝试在应用中重新动态加载这些文件。重新创建文件时,请按照上述指南在写入时将文件标记为只读。或者,您可以将现有文件重新标记为只读,但在这种情况下,我们强烈建议您先验证文件的完整性(例如,对照可信值检查文件的签名)以保护应用免遭恶意操作的影响。
Zusätzliche Einschränkungen beim Starten von Aktivitäten im Hintergrund
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,系统会进一步限制允许应用在后台启动 activity 的时间:
- 现在,当应用使用
PendingIntent#send()或类似方法发送PendingIntent时,如果它想要授予自己的后台 activity 启动待处理 intent 的启动特权,则必须选择启用。如需选择启用,应用应通过setPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)传递ActivityOptions软件包。 - 当可见应用使用
bindService()方法绑定其他在后台应用的服务时,如果可见应用想要授予自己的后台 activity 对绑定服务的启动特权,则必须选择启用。如需选择启用,应用应在调用bindService()方法时包含BIND_ALLOW_ACTIVITY_STARTS标志。
这些更改扩大了一组现有限制条件的范围,目的是防止恶意应用滥用 API 以在后台启动干扰性活动,从而保护用户。
Zip Path Traversal
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,Android 会通过以下方式防止 Zip 路径遍历漏洞:如果 Zip 文件条目名称包含“..”或以“/”开头,ZipFile(String) 和 ZipInputStream.getNextEntry() 会抛出 ZipException。
应用可以通过调用 dalvik.system.ZipPathValidator.clearCallback() 选择停用此验证。
Nutzereinwilligung für jede MediaProjection-Aufnahmesitzung erforderlich
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,在以下任一情况下,MediaProjection#createVirtualDisplay 都会抛出 SecurityException:
- 您的应用会缓存从
MediaProjectionManager#createScreenCaptureIntent返回的Intent,并多次将其传递给MediaProjectionManager#getMediaProjection。 - 您的应用在同一
MediaProjection实例上多次调用MediaProjection#createVirtualDisplay。
您的应用必须在每次捕获会话之前征求用户同意。单次捕获会话是对 MediaProjection#createVirtualDisplay 的单次调用,并且每个 MediaProjection 实例只能使用一次。
处理配置变更
如果您的应用需要调用 MediaProjection#createVirtualDisplay 来处理配置更改(例如屏幕方向或屏幕大小更改),您可以按照以下步骤更新现有 MediaProjection 实例的 VirtualDisplay:
- 使用新的宽度和高度调用
VirtualDisplay#resize。 - 向
VirtualDisplay#setSurface提供新的Surface,并为其指定新的宽度和高度。
注册回调
您的应用应注册回调,以处理用户不同意继续拍摄会话的情况。为此,请实现 Callback#onStop,并让应用释放所有相关资源(例如 VirtualDisplay 和 Surface)。
如果您的应用未注册此回调,当您的应用调用它时,MediaProjection#createVirtualDisplay 会抛出 IllegalStateException。
Aktualisierte Einschränkungen für Nicht-SDKs
Android 14 enthält aktualisierte Listen eingeschränkter Nicht-SDK-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 zwar einige Nicht-SDK-Schnittstellen verwenden (abhängig vom Ziel-API-Level Ihrer App), die Verwendung einer Nicht-SDK-Methode oder eines Nicht-SDK-Felds 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 das herauszufinden. Wenn Ihre App auf Nicht-SDK-Schnittstellen basiert, sollten Sie mit der Planung einer Migration zu SDK-Alternativen beginnen. Wir verstehen jedoch, dass einige Apps gültige Anwendungsfälle für die Verwendung von Nicht-SDK-Schnittstellen haben. Wenn Sie für eine Funktion 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 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.