Come nelle release precedenti, Android 14 include modifiche del comportamento che potrebbero interessare la tua app. Le seguenti modifiche del comportamento si applicano esclusivamente alle app destinate ad Android 14 (livello API 34) o versioni successive. Se la tua app ha come target Android 14 o versioni successive, devi modificarla per supportare correttamente questi comportamenti ove applicabile.
Assicurati di esaminare anche l'elenco delle modifiche del comportamento che interessano tutte le app
in esecuzione su Android 14, indipendentemente
dalla targetSdkVersion
dell'app.
Funzionalità di base
I tipi di servizio in primo piano sono obbligatori
If your app targets Android 14 (API level 34) or higher, it must specify at least one foreground service type for each foreground service within your app. You should choose a foreground service type that represents your app's use case. The system expects foreground services that have a particular type to satisfy a particular use case.
If a use case in your app isn't associated with any of these types, it's strongly recommended that you migrate your logic to use WorkManager or user-initiated data transfer jobs.
Applicazione dell'autorizzazione BLUETOOTH_CONNECT in BluetoothAdapter
Android 14 applica l'autorizzazione BLUETOOTH_CONNECT
quando chiami il metodo
BluetoothAdapter
getProfileConnectionState()
per le app che hanno come target
Android 14 (livello API 34) o versioni successive.
Questo metodo richiede già l'autorizzazione BLUETOOTH_CONNECT
, ma non è stata applicata. Assicurati che la tua app dichiari BLUETOOTH_CONNECT
nel file
AndroidManifest.xml
dell'app come mostrato nello snippet seguente e verifica che
un utente abbia concesso l'autorizzazione prima di chiamare
getProfileConnectionState
.
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
Aggiornamenti di OpenJDK 17
Android 14 continues the work of refreshing Android's core libraries to align with the features in the latest OpenJDK LTS releases, including both library updates and Java 17 language support for app and platform developers.
A few of these changes can affect app compatibility:
- Changes to regular expressions: Invalid group references are now
disallowed to more closely follow the semantics of OpenJDK. You might see
new cases where an
IllegalArgumentException
is thrown by thejava.util.regex.Matcher
class, so make sure to test your app for areas that use regular expressions. To enable or disable this change while testing, toggle theDISALLOW_INVALID_GROUP_REFERENCE
flag using the compatibility framework tools. - UUID handling: The
java.util.UUID.fromString()
method now does more strict checks when validating the input argument, so you might see anIllegalArgumentException
during deserialization. To enable or disable this change while testing, toggle theENABLE_STRICT_VALIDATION
flag using the compatibility framework tools. - ProGuard issues: In some cases, the addition of the
java.lang.ClassValue
class causes an issue if you try to shrink, obfuscate, and optimize your app using ProGuard. The problem originates with a Kotlin library that changes runtime behaviour based on whetherClass.forName("java.lang.ClassValue")
returns a class or not. If your app was developed against an older version of the runtime without thejava.lang.ClassValue
class available, then these optimizations might remove thecomputeValue
method from classes derived fromjava.lang.ClassValue
.
JobScheduler rafforza il callback e il comportamento di rete
自引入以来,JobScheduler 会预期您的应用在几秒内从 onStartJob
或 onStopJob
返回。在 Android 14 之前,如果作业运行时间太长,则会静默停止并失败。如果您的应用以 Android 14(API 级别 34)或更高版本为目标平台且在主线程上超出了授权的时间,应用会触发 ANR,并显示错误消息“对 onStartJob
没有响应”或“对 onStopJob
没有响应”。请考虑迁移到 WorkManager,该版本可支持异步处理,或将所有繁重工作迁移到后台线程。
JobScheduler
还引入了,如果使用 setRequiredNetworkType
或 setRequiredNetwork
约束条件,则需要声明 ACCESS_NETWORK_STATE
权限。如果应用在调度作业时未声明 ACCESS_NETWORK_STATE
权限,并且以 Android 14 或更高版本为目标平台,则会导致 SecurityException
。
API Tiles lancio
对于以 14 及更高版本为目标平台的应用,TileService#startActivityAndCollapse(Intent)
已废弃,现在会在调用时抛出异常。如果您的应用从功能块启动 activity,请改用 TileService#startActivityAndCollapse(PendingIntent)
。
Privacy
Accesso parziale a foto e video
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.
Esperienza utente
Notifiche sicure di intent a schermo intero
在 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
启动设置页面,在该页面中,用户可以授予权限。
Sicurezza
Restrizioni agli intent impliciti e in attesa
对于以 Android 14(API 级别 34)或更高版本为目标平台的应用,Android 会通过以下方式限制应用向内部应用组件发送隐式 intent:
- 隐式 intent 只能传送到导出的组件。应用必须使用显式 intent 传送到未导出的组件,或将该组件标记为已导出。
- 如果应用通过未指定组件或软件包的 intent 创建可变待处理 intent,系统会抛出异常。
这些变更可防止恶意应用拦截意在供应用内部组件使用的隐式 intent。
例如,下面是可以在应用的清单文件中声明的 intent 过滤器:
<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>
如果应用尝试使用隐式 intent 启动此 activity,则系统会抛出异常:
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"));
如需启动非导出的 activity,应用应改用显式 intent:
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);
I ricevitori di broadcast registrati in runtime devono specificare il comportamento di esportazione
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.
Caricamento del codice dinamico più sicuro
Se la tua app ha come target Android 14 (livello API 34) o versioni successive e utilizza il caricamento dinamico del codice (DCL), tutti i file caricati dinamicamente devono essere contrassegnati come di sola lettura. In caso contrario, il sistema genera un'eccezione. Consigliamo alle app di evitare il caricamento dinamico del codice ogni volta che è possibile, in quanto ciò aumenta notevolmente il rischio che un'app venga compromessa a causa dell'inserimento o della manomissione del codice.
Se devi caricare il codice in modo dinamico, utilizza il seguente approccio per impostare il file caricato dinamicamente (ad esempio un file DEX, JAR o APK) come di sola lettura non appena il file viene aperto e prima che venga scritto un contenuto:
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);
Gestire i file caricati dinamicamente già esistenti
Per evitare che vengano generate eccezioni per i file esistenti caricati dinamicamente, ti consigliamo di eliminarli e ricrearli prima di provare a caricarli di nuovo nell'app in modo dinamico. Quando ricrei i file, segui le linee guida precedenti per contrassegnare i file come di sola lettura al momento della scrittura. In alternativa, puoi rietichettare i file esistenti come di sola lettura, ma in questo caso ti consigliamo vivamente di verificare prima l'integrità dei file (ad esempio, controllando la firma del file con un valore attendibile), per proteggere la tua app da azioni dannose.
Ulteriori limitazioni relative all'avvio di attività in background
Per le app che hanno come target Android 14 (livello API 34) o versioni successive, il sistema limita ulteriormente i casi in cui alle app è consentito avviare attività in background:
- Quando un'app invia un elemento
PendingIntent
utilizzandoPendingIntent#send()
o metodi simili, l'app deve eseguire l'attivazione se vuole concedere i propri privilegi di avvio per l'attività in background per avviare l'intent in sospeso. Per l'attivazione, l'app deve trasmettere un bundleActivityOptions
consetPendingIntentBackgroundActivityStartMode(MODE_BACKGROUND_ACTIVITY_START_ALLOWED)
. - Quando un'app visibile associa un servizio di un'altra app in background
con il metodo
bindService()
, ora l'app visibile deve essere attivata se vuole concedere i propri privilegi di avvio delle attività in background al servizio associato. Per l'attivazione, l'app deve includere il flagBIND_ALLOW_ACTIVITY_STARTS
quando chiami il metodobindService()
.
Queste modifiche ampliano l'insieme di limitazioni esistenti per proteggere gli utenti impedendo alle app dannose di utilizzare in modo illecito le API di avviare attività di disturbo in background.
Attraversamento percorso zip
Per le app che hanno come target Android 14 (livello API 34) o versioni successive, Android impedisce la vulnerabilità Zip Path Traversal nel seguente modo:
ZipFile(String)
e
ZipInputStream.getNextEntry()
generano un
ZipException
se i nomi delle voci del file ZIP contengono ".." o iniziano con "/".
Le app possono disattivare questa convalida chiamando
dalvik.system.ZipPathValidator.clearCallback()
.
Consenso degli utenti richiesto per ogni sessione di acquisizione MediaProjection
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.
Limitazioni non SDK aggiornate
Android 14 include elenchi aggiornati di interfacce non SDK limitate in base alla collaborazione con gli sviluppatori Android e agli ultimi test interni. Quando possibile, ci assicuriamo che siano disponibili alternative pubbliche prima di limitare le interfacce non SDK.
Se la tua app non è destinata ad Android 14, alcune di queste modifiche potrebbero non essere applicate immediatamente. Tuttavia, anche se al momento puoi utilizzare alcune interfacce non SDK (a seconda del livello API target della tua app), l'utilizzo di metodi o campi non SDK comporta sempre un rischio elevato di danneggiare la tua app.
Se non hai la certezza che la tua app utilizzi interfacce non SDK, puoi testare l'app per scoprirlo. Se la tua app si basa su interfacce non SDK, devi iniziare a pianificare una migrazione alle alternative SDK. Ciononostante, siamo consapevoli che alcune app hanno casi d'uso validi per l'utilizzo di interfacce non SDK. Se non riesci a trovare un'alternativa all'utilizzo di un'interfaccia non SDK per una funzionalità nella tua app, devi richiedere una nuova API pubblica.
如需详细了解此 Android 版本中的变更,请参阅 Android 14 中有关限制非 SDK 接口的更新。如需全面了解有关非 SDK 接口的详细信息,请参阅对非 SDK 接口的限制。