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
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
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
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
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
在 Android 11(API 级别 30)中,任何应用都可以在手机处于锁定状态时使用 Notification.Builder.setFullScreenIntent
发送全屏 intent。您可以通过在 AndroidManifest 中声明 USE_FULL_SCREEN_INTENT
权限,在应用安装时自动授予此权限。
全屏 intent 通知适用于需要用户立即注意的极高优先级通知,例如用户来电或用户配置的闹钟设置。对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,获准使用此权限的应用仅限于提供通话和闹钟的应用。对于不适合此情况的任何应用,Google Play 商店会撤消其默认的 USE_FULL_SCREEN_INTENT
权限。这些政策变更的截止日期为 2024 年 5 月 31 日。
在用户更新到 Android 14 之前,在手机上安装的应用仍拥有此权限。用户可以开启和关闭此权限。
您可以使用新 API NotificationManager.canUseFullScreenIntent
检查应用是否具有该权限;如果没有,应用可以使用新 intent ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT
启动设置页面,在该页面中,用户可以授予权限。
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
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 dynamischen Codes
如果您的应用以 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 ist für jede Aufnahmesitzung von MediaProjection 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-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.
如需详细了解此 Android 版本中的变更,请参阅 Android 14 中有关限制非 SDK 接口的更新。如需全面了解有关非 SDK 接口的详细信息,请参阅对非 SDK 接口的限制。