Modifiche al comportamento: tutte le app

La piattaforma Android 16 include modifiche al comportamento che potrebbero influire sulla tua app. Le seguenti modifiche al comportamento si applicano a tutte le app quando vengono eseguite su Android 16, indipendentemente da targetSdkVersion. Dovresti testare l'app e poi modificarla come necessario per supportare queste modifiche, se applicabili.

Assicurati di esaminare anche l'elenco delle modifiche al comportamento che interessano solo le app con target Android 16.

Funzionalità di base

Android 16 include le seguenti modifiche che modificano o ampliano varie funzionalità di base del sistema Android.

Ottimizzazioni delle quote di JobScheduler

A partire da Android 16, stiamo modificando la quota di tempo di esecuzione per l'esecuzione di job regolari e accelerati in base ai seguenti fattori:

  • Il bucket di app in standby in cui si trova l'applicazione: in Android 16, i bucket di app in standby attivi inizieranno a essere applicati da una quota di runtime generosa.
  • Se il job inizia l'esecuzione mentre l'app è in uno stato superiore: in Android 16, i job avviati mentre l'app è visibile all'utente e continuano dopo che l'app diventa invisibile, rispetteranno la quota di tempo di esecuzione del job.
  • Se il job è in esecuzione durante l'esecuzione di un servizio in primo piano: in Android 16, i job in esecuzione contemporaneamente a un servizio in primo piano rispetteranno la quota di tempo di esecuzione del job. Se utilizzi i job per il trasferimento di dati avviato dall'utente, ti consigliamo di utilizzare i job di trasferimento di dati avviati dall'utente.

Questa modifica interessa le attività pianificate utilizzando WorkManager, JobScheduler e DownloadManager. Per eseguire il debug del motivo dell'interruzione di un job, ti consigliamo di registrare il motivo dell'interruzione chiamando WorkInfo.getStopReason() (per i job JobScheduler, chiama JobParameters.getStopReason()).

Per ulteriori informazioni sulle best practice per l'ottimizzazione dell'utilizzo della batteria per le API di pianificazione delle attività, consulta le indicazioni su come ottimizzare l'utilizzo della batteria per le API di pianificazione delle attività.

Ti consigliamo inoltre di utilizzare la nuova API JobScheduler#getPendingJobReasonsHistory introdotta in Android 16 per capire perché un job non è stato eseguito.

Test

Per testare il comportamento dell'app, puoi attivare l'override di determinate ottimizzazioni della quota di job, a condizione che l'app sia in esecuzione su un dispositivo Android 16.

Per disattivare l'applicazione dell'impostazione "lo stato superiore rispetterà la quota di runtime del job", esegui il seguente comando adb:

adb shell am compat enable OVERRIDE_QUOTA_ENFORCEMENT_TO_TOP_STARTED_JOBS APP_PACKAGE_NAME

Per disattivare l'applicazione forzata del criterio "i job in esecuzione contemporaneamente a un servizio in primo piano rispetteranno la quota di tempo di esecuzione del job", esegui il seguente comando adb:

adb shell am compat enable OVERRIDE_QUOTA_ENFORCEMENT_TO_FGS_JOBS APP_PACKAGE_NAME

Per testare determinati comportamenti del bucket in standby dell'app, puoi impostare il bucket in standby dell'app utilizzando il seguente comando adb:

adb shell am set-standby-bucket APP_PACKAGE_NAME active|working_set|frequent|rare|restricted

Per capire il bucket in cui si trova la tua app, puoi ottenere il bucket in standby della tua app utilizzando il seguente comando adb:

adb shell am get-standby-bucket APP_PACKAGE_NAME

Motivo dell'interruzione dei job vuoti abbandonati

如果与作业关联的 JobParameters 对象已被垃圾回收,但尚未调用 JobService#jobFinished(JobParameters, boolean) 来指示作业已完成,则会发生作业被废弃的情况。这表示作业可能会在应用不知情的情况下运行和重新调度。

依赖于 JobScheduler 的应用不会维护对 JobParameters 对象的强引用,并且超时现在将获得新的作业停止原因 STOP_REASON_TIMEOUT_ABANDONED,而不是 STOP_REASON_TIMEOUT

如果新的作业被废弃停止原因频繁出现,系统会采取缓解措施来降低作业频率。

应用应使用新的停止原因来检测和减少被废弃的作业。

如果您使用的是 WorkManager、AsyncTask 或 DownloadManager,则不会受到影响,因为这些 API 会代表您的应用管理作业生命周期。

Ritiro completo di JobInfo#setImportantWhileForeground

Il metodo JobInfo.Builder#setImportantWhileForeground(boolean) indica l'importanza di un job quando l'app di pianificazione è in primo piano o quando è temporaneamente esente dalle limitazioni in background.

Questo metodo è stato ritirato da Android 12 (livello API 31). A partire da Android 16, non funziona più in modo efficace e la chiamata di questo metodo verrà ignorata.

Questa rimozione di funzionalità si applica anche a JobInfo#isImportantWhileForeground(). A partire da Android 16, se il metodo viene chiamato, restituisce false.

L'ambito della priorità di trasmissione ordinata non è più globale

Le app per Android possono definire le priorità per i ricevitori di trasmissione per controllare l'ordine in cui i ricevitori ricevono ed elaborano la trasmissione. Per i gestori dichiarati nel file manifest, le app possono utilizzare l'attributo android:priority per definire la priorità e per i gestori registrati nel contesto, le app possono utilizzare l'API IntentFilter#setPriority() per definire la priorità. Quando viene inviata una trasmissione, il sistema la consegna ai ricevitori in ordine di priorità, dalla più alta alla più bassa.

In Android 16, l'ordine di invio delle trasmissioni che utilizzano l'attributo android:priority o IntentFilter#setPriority() in diversi processi non sarà garantito. Le priorità di trasmissione verranno rispettate solo all'interno della stessa procedura di applicazione e non in tutte le procedure.

Inoltre, le priorità di trasmissione verranno automaticamente limitate all'intervallo (SYSTEM_LOW_PRIORITY + 1, SYSTEM_HIGH_PRIORITY - 1). Solo i componenti di sistema potranno impostare SYSTEM_LOW_PRIORITY, SYSTEM_HIGH_PRIORITY come priorità di trasmissione.

La tua app potrebbe essere interessata se esegue una delle seguenti azioni:

  1. La tua applicazione ha dichiarato più processi con lo stesso intento di trasmissione e si aspetta di ricevere questi intent in un determinato ordine in base alla priorità.
  2. La procedura di applicazione interagisce con altri processi e ha aspettative sulla ricezione di un'intenzione di trasmissione in un determinato ordine.

Se le procedure devono coordinarsi tra loro, devono comunicare utilizzando altri canali di coordinamento.

Modifiche interne all'ART

Android 16 包含 Android 运行时 (ART) 的最新更新,这些更新可提升 Android 运行时 (ART) 的性能,并支持更多 Java 功能。通过 Google Play 系统更新,搭载 Android 12(API 级别 31)及更高版本的 10 亿多部设备也将受益于这些改进。

发布这些变更后,依赖于 ART 内部结构的库和应用代码在搭载 Android 16 的设备以及通过 Google Play 系统更新来更新 ART 模块的较低 Android 版本上可能无法正常运行。

依赖于内部结构(例如非 SDK 接口)始终会导致兼容性问题,但避免依赖于利用内部 ART 结构的代码(或包含代码的库)尤为重要,因为 ART 更改与设备所运行的平台版本无关,并且会通过 Google Play 系统更新推送到超过 10 亿部设备。

所有开发者都应在 Android 16 上对其应用进行全面测试,以检查其应用是否受到影响。此外,请查看已知问题,了解您的应用是否依赖于我们发现的任何依赖于内部 ART 结构的库。如果您的应用代码或库依赖项受到影响,请尽可能寻找公共 API 替代方案,并在问题跟踪器中创建功能请求,为新用例请求公共 API。

Modalità di compatibilità con le dimensioni pagina di 16 kB

Android 15 ha introdotto il supporto per le pagine di memoria da 16 KB per ottimizzare le prestazioni della piattaforma. Android 16 aggiunge una modalità di compatibilità, che consente ad alcune app create per pagine di memoria da 4 KB di essere eseguite su un dispositivo configurato per pagine di memoria da 16 KB.

Se Android rileva che la tua app ha pagine di memoria allineate a 4 KB, utilizza automaticamente la modalità di compatibilità e mostra una finestra di dialogo di notifica all'utente. L'impostazione della proprietà android:pageSizeCompat in AndroidManifest.xml per attivare la modalità di compatibilità con le versioni precedenti impedisce la visualizzazione della finestra di dialogo al momento dell'avvio dell'app. Per ottenere le migliori prestazioni, affidabilità e stabilità, la tua app deve comunque essere allineata a 16 KB. Per ulteriori dettagli, consulta il nostro recente post del blog sull'aggiornamento delle app per supportare le pagine di memoria di 16 KB.

La finestra di dialogo della modalità di compatibilità che viene visualizzata quando il sistema rileva che un'app allineata a 4 KB potrebbe funzionare in modo più ottimale se allineata a 16 KB.

Esperienza utente e interfaccia utente di sistema

Android 16 include le seguenti modifiche volte a creare un'esperienza utente più coerente e intuitiva.

Ritiro degli annunci di accessibilità che causano interruzioni

Android 16 ritira gli annunci di accessibilità, caratterizzati dall'utilizzo di announceForAccessibility o dall'invio di TYPE_ANNOUNCEMENT eventi di accessibilità. Ciò può creare esperienze utente incoerenti per gli utenti di TalkBack e dello screen reader di Android e le alternative soddisfano meglio una gamma più ampia di esigenze degli utenti in una serie di tecnologie per la disabilità di Android.

Esempi di alternative:

La documentazione di riferimento per l'API announceForAccessibility obsoleta include ulteriori dettagli sulle alternative suggerite.

Supporto della navigazione con tre pulsanti

Android 16 introduce il supporto del pulsante Indietro predittivo alla navigazione con tre pulsanti per le app che hanno effettuato correttamente la migrazione al pulsante Indietro predittivo. Se premi a lungo il pulsante Indietro, viene avviata un'animazione di Indietro predittiva che ti mostra un'anteprima della destinazione del gesto Indietro.

Questo comportamento si applica a tutte le aree del sistema che supportano le animazioni Indietro predittive, incluse le animazioni di sistema (torna alla schermata Home, passaggio da un'attività all'altra e così via).

Le animazioni Indietro predittive in modalità di navigazione con tre pulsanti.

Fattori di forma del dispositivo

Android 16 include le seguenti modifiche per le app quando vengono proiettate sui display dai proprietari di dispositivi virtuali.

Sostituzioni del proprietario del dispositivo virtuale

A virtual device owner is a trusted or privileged app that creates and manages a virtual device. Virtual device owners run apps on a virtual device and then project the apps to the display of a remote device, such as a personal computer, virtual reality device, or car infotainment system. The virtual device owner is on a local device, such as a mobile phone.

Virtual device owner on phone creates virtual device that projects app to remote display.

Per-app overrides

On devices running Android 16, virtual device owners can override app settings on select virtual devices that the virtual device owners manage. For example, to improve app layout, a virtual device owner can ignore orientation, aspect ratio, and resizability restrictions when projecting apps onto an external display.

Common breaking changes

The Android 16 behavior might impact your app's UI on large screen form factors such as car displays or Chromebooks, especially layouts that were designed for small displays in portrait orientation. To learn how to make your app adaptive for all device form factors, see About adaptive layouts.

References

Companion app streaming

Sicurezza

Android 16 include modifiche che promuovono la sicurezza del sistema per contribuire a proteggere app e utenti da app dannose.

Maggiore sicurezza contro gli attacchi di reindirizzamento degli intent

Android 16 提供了针对常规 Intent 重定向攻击的默认安全防护,并且所需的兼容性和开发者更改最少。

我们将默认针对 Intent 重定向漏洞引入安全增强解决方案。在大多数情况下,使用 intent 的应用通常不会遇到任何兼容性问题;我们在整个开发过程中收集了指标,以监控哪些应用可能会出现故障。

当攻击者部分或完全控制用于在存在漏洞的应用上下文中启动新组件的 intent 内容时,就会出现 Android 中的intent 重定向,而受害应用会在 intent(“顶级”intent)的 extras 字段中启动不可信的子级 intent。这可能会导致攻击者应用在受害应用上下文中启动私有组件、触发特权操作或获得对敏感数据的 URI 访问权限,从而可能导致数据被盗和任意代码执行。

停用 intent 重定向处理

Android 16 引入了一个新 API,允许应用选择停用启动安全保护。在默认安全行为干扰合法应用用例的特定情况下,这可能很有必要。

对于针对 Android 16 SDK 或更高版本进行编译的应用

您可以直接对 intent 对象使用 removeLaunchSecurityProtection() 方法。

val i = intent
val iSublevel: Intent? = i.getParcelableExtra("sub_intent")
iSublevel?.removeLaunchSecurityProtection() // Opt out from hardening
iSublevel?.let { startActivity(it) }
对于针对 Android 15(API 级别 35)或更低版本进行编译的应用

虽然不建议这样做,但您可以使用反射来访问 removeLaunchSecurityProtection() 方法。

val i = intent
val iSublevel: Intent? = i.getParcelableExtra("sub_intent", Intent::class.java)
try {
    val removeLaunchSecurityProtection = Intent::class.java.getDeclaredMethod("removeLaunchSecurityProtection")
    removeLaunchSecurityProtection.invoke(iSublevel)
} catch (e: Exception) {
    // Handle the exception, e.g., log it
} // Opt-out from the security hardening using reflection
iSublevel?.let { startActivity(it) }