Cambiamenti del comportamento: app destinate ad Android 15 o versioni successive

Come le release precedenti, Android 15 include modifiche al comportamento che potrebbero interessare la tua app. Le seguenti modifiche al comportamento si applicano esclusivamente alle app che hanno come target Android 15 o versioni successive. Se la tua app ha come target Android 15 o versioni successive, devi modificarla in modo da supportare correttamente questi comportamenti, ove applicabile.

Assicurati di esaminare anche l'elenco delle modifiche al comportamento che interessano tutte le app in esecuzione su Android 15, indipendentemente dal targetSdkVersion della tua app.

Funzionalità di base

Android 15 modifica o espande varie funzionalità di base del sistema Android.

Modifiche ai servizi in primo piano

我们将对 Android 15 中的前台服务进行以下更改。

数据同步前台服务超时行为

Android 15 introduce un nuovo comportamento di timeout per dataSync per le app che hanno come target Android 15 (livello API 35) o versioni successive. Questo comportamento si applica anche al nuovo tipo di servizio in primo piano mediaProcessing.

Il sistema consente l'esecuzione dei servizi dataSync di un'app per un totale di 6 ore in un periodo di 24 ore, dopodiché il sistema chiama il metodo Service.onTimeout(int, int) del servizio in esecuzione (introdotto in Android 15). Al momento, il servizio ha alcuni secondi di tempo per chiamare Service.stopSelf(). Quando viene chiamato Service.onTimeout(), il servizio non è più considerato un servizio in primo piano. Se il servizio non chiama Service.stopSelf(), il sistema genera un'eccezione interna. L'eccezione viene registrata in Logcat con il seguente messaggio:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type dataSync did not stop within its timeout: [component name]"

Per evitare problemi con questa modifica del comportamento, puoi eseguire una o più delle seguenti operazioni:

  1. Chiedi al tuo servizio di implementare il nuovo metodo Service.onTimeout(int, int). Quando l'app riceve il Callback, assicurati di chiamare stopSelf() entro alcuni secondi. Se non interrompi immediatamente l'app, il sistema genera un errore.
  2. Assicurati che i servizi dataSync della tua app non vengano eseguiti per più di un totale di 6 ore in un periodo di 24 ore (a meno che l'utente non interagisca con l'app, reimpostando il timer).
  3. Avvia i servizi in primo piano dataSync solo in seguito a un'interazione diretta con l'utente. Poiché l'app è in primo piano all'avvio del servizio, il servizio ha a disposizione tutte le sei ore dopo che l'app passa in background.
  4. Anziché utilizzare un servizio in primo piano dataSync, utilizza un'API alternativa.

Se i servizi in primo piano dataSync della tua app sono stati in esecuzione per 6 ore nelle ultime 24, non puoi avviare un altro servizio in primo piano dataSync a meno che l'utente non abbia portato la tua app in primo piano (il che reimposta il timer). Se provi a avviare un altro servizio in primo piano dataSync, il sistema genera un messaggio di errore ForegroundServiceStartNotAllowedException come "Tempo limite già esaurito per il servizio in primo piano di tipo dataSync".

Test

Per testare il comportamento dell'app, puoi attivare i timeout della sincronizzazione dei dati anche se la tua app non ha come target Android 15 (a condizione che l'app sia in esecuzione su un dispositivo Android 15). Per abilitare i timeout, esegui questo comando adb:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

Puoi anche modificare il periodo di timeout per testare più facilmente il comportamento della tua app quando viene raggiunto il limite. Per impostare un nuovo periodo di timeout, esegui il seguente comando adb:

adb shell device_config put activity_manager data_sync_fgs_timeout_duration duration-in-milliseconds

新的媒体处理前台服务类型

Android 15 introduces a new foreground service type, mediaProcessing. This service type is appropriate for operations like transcoding media files. For example, a media app might download an audio file and need to convert it to a different format before playing it. You can use a mediaProcessing foreground service to make sure the conversion continues even while the app is in the background.

The system permits an app's mediaProcessing services to run for a total of 6 hours in a 24-hour period, after which the system calls the running service's Service.onTimeout(int, int) method (introduced in Android 15). At this time, the service has a few seconds to call Service.stopSelf(). If the service does not call Service.stopSelf(), the system throws an internal exception. The exception is logged in Logcat with the following message:

Fatal Exception: android.app.RemoteServiceException: "A foreground service of
type mediaProcessing did not stop within its timeout: [component name]"

To avoid having the exception, you can do one of the following:

  1. Have your service implement the new Service.onTimeout(int, int) method. When your app receives the callback, make sure to call stopSelf() within a few seconds. (If you don't stop the app right away, the system generates a failure.)
  2. Make sure your app's mediaProcessing services don't run for more than a total of 6 hours in any 24-hour period (unless the user interacts with the app, resetting the timer).
  3. Only start mediaProcessing foreground services as a result of direct user interaction; since your app is in the foreground when the service starts, your service has the full six hours after the app goes to the background.
  4. Instead of using a mediaProcessing foreground service, use an alternative API, like WorkManager.

If your app's mediaProcessing foreground services have run for 6 hours in the last 24, you cannot start another mediaProcessing foreground service unless the user has brought your app to the foreground (which resets the timer). If you try to start another mediaProcessing foreground service, the system throws ForegroundServiceStartNotAllowedException with an error message like "Time limit already exhausted for foreground service type mediaProcessing".

For more information about the mediaProcessing service type, see Changes to foreground service types for Android 15: Media processing.

Testing

To test your app's behavior, you can enable media processing timeouts even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). To enable timeouts, run the following adb command:

adb shell am compat enable FGS_INTRODUCE_TIME_LIMITS your-package-name

You can also adjust the timeout period, to make it easier to test how your app behaves when the limit is reached. To set a new timeout period, run the following adb command:

adb shell device_config put activity_manager media_processing_fgs_timeout_duration duration-in-milliseconds

对启动前台服务的 BOOT_COMPLETED 广播接收器的限制

Esistono nuove limitazioni per i BOOT_COMPLETED ricevitori di trasmissione che avviano servizi in primo piano. BOOT_COMPLETED di destinatari non sono autorizzati ad avviare il i seguenti tipi di servizi in primo piano:

Se un receiver BOOT_COMPLETED tenta di avviare uno di questi tipi di servizi in primo piano, il sistema genera un'eccezione ForegroundServiceStartNotAllowedException.

Test

Per verificare il comportamento della tua app, puoi attivare queste nuove limitazioni anche se le tue L'app non ha come target Android 15 (purché l'app sia installata su un Android 15) dispositivo). Esegui il seguente comando adb:

adb shell am compat enable FGS_BOOT_COMPLETED_RESTRICTIONS your-package-name

Per inviare un annuncio BOOT_COMPLETED senza riavviare il dispositivo: esegui questo comando adb:

adb shell am broadcast -a android.intent.action.BOOT_COMPLETED your-package-name

在应用拥有 SYSTEM_ALERT_WINDOW 权限时启动前台服务的限制

Previously, if an app held the SYSTEM_ALERT_WINDOW permission, it could launch a foreground service even if the app was currently in the background (as discussed in exemptions from background start restrictions).

If an app targets Android 15, this exemption is now narrower. The app now needs to have the SYSTEM_ALERT_WINDOW permission and also have a visible overlay window. That is, the app needs to first launch a TYPE_APPLICATION_OVERLAY window and the window needs to be visible before you start a foreground service.

If your app attempts to start a foreground service from the background without meeting these new requirements (and it does not have some other exemption), the system throws ForegroundServiceStartNotAllowedException.

If your app declares the SYSTEM_ALERT_WINDOW permission and launches foreground services from the background, it may be affected by this change. If your app gets a ForegroundServiceStartNotAllowedException, check your app's order of operations and make sure your app already has an active overlay window before it attempts to start a foreground service from the background. You can check if your overlay window is currently visible by calling View.getWindowVisibility(), or you can override View.onWindowVisibilityChanged() to get notified whenever the visibility changes.

Testing

To test your app's behavior, you can enable these new restrictions even if your app is not targeting Android 15 (as long as the app is running on an Android 15 device). To enable these new restrictions on starting foreground services from the background, run the following adb command:

adb shell am compat enable FGS_SAW_RESTRICTIONS your-package-name

Modifiche alle circostanze in cui le app possono modificare lo stato globale della modalità Non disturbare

Le app che hanno come target Android 15 (livello API 35) e versioni successive non possono più modificare lo stato o i criteri globali della modalità Non disturbare (ND) su un dispositivo (modificando le impostazioni utente o disattivando la modalità ND). Le app devono invece fornire un AutomaticZenRule, che il sistema combina in una norma globale con lo schema vigente che prevede l'applicazione della norma più restrittiva. Le chiamate alle API esistenti che precedentemente influivano sullo stato globale (setInterruptionFilter, setNotificationPolicy) comportano la creazione o l'aggiornamento di un valore AutomaticZenRule implicito, che viene attivato e disattivato in base al ciclo di chiamata di queste chiamate API.

Tieni presente che questa modifica influisce sul comportamento osservabile solo se l'app chiama setInterruptionFilter(INTERRUPTION_FILTER_ALL) e si aspetta che la chiamata disattivi un AutomaticZenRule precedentemente attivato dai relativi proprietari.

Modifiche all'API OpenJDK

Android 15 将继续更新 Android 的核心库,以与最新 OpenJDK LTS 版本中的功能保持一致。

其中一些变更可能会影响以 Android 15(API 级别 35)为目标平台的应用的兼容性:

  • 对字符串格式化 API 的更改:现在,使用以下 String.format()Formatter.format() API 时,对参数索引、标志、宽度和精度的验证更为严格:

    例如,使用参数索引 0(格式字符串中的 %0)时,系统会抛出以下异常:

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    在这种情况下,可以通过使用参数编号 1(格式字符串中的 %1)来解决此问题。

  • Arrays.asList(...).toArray() 的组件类型变更:使用 Arrays.asList(...).toArray() 时,生成数组的组件类型现在为 Object,而不是底层数组元素的类型。因此,以下代码会抛出 ClassCastException

    String[] elements = (String[]) Arrays.asList("one", "two").toArray();
    

    对于这种情况,如需在生成的数组中将 String 保留为组件类型,您可以改用 Collection.toArray(Object[])

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • 语言代码处理方式变更:使用 Locale API 时,希伯来语、意第绪语和印度尼西亚语的语言代码不再转换为已废弃的形式(希伯来语:iw、意第绪语:ji、印度尼西亚语:in)。在为其中一种语言区域指定语言代码时,请改用 ISO 639-1 中的代码(希伯来语:he、意第绪语:yi、印度尼西亚语:id)。

  • 对随机 int 序列的更改:在 https://bugs.openjdk.org/browse/JDK-8301574 中进行更改后,以下 Random.ints() 方法现在返回的数字序列与 Random.nextInt() 方法返回的序列不同:

    通常,此更改不会导致应用出现破坏行为,但您的代码不应预期从 Random.ints() 方法生成的序列与 Random.nextInt() 匹配。

在您更新应用 build 配置中的 compileSdk 以使用 Android 15(API 级别 35)后,新的 SequencedCollection API 可能会影响应用的兼容性:

  • kotlin-stdlib 中的 MutableList.removeFirst()MutableList.removeLast() 扩展函数发生冲突

    Java 中的 List 类型会映射到 Kotlin 中的 MutableList 类型。由于 List.removeFirst()List.removeLast() API 已在 Android 15(API 级别 35)中引入,因此 Kotlin 编译器会将函数调用(例如 list.removeFirst())静态解析为新的 List API,而不是 kotlin-stdlib 中的扩展函数。

    如果将应用重新编译并将 compileSdk 设置为 35 且将 minSdk 设置为 34 或更低级别,然后在 Android 14 及更低版本上运行该应用,系统会抛出运行时错误:

    java.lang.NoSuchMethodError: No virtual method
    removeFirst()Ljava/lang/Object; in class Ljava/util/ArrayList;
    

    Android Gradle 插件中现有的 NewApi lint 选项可以捕获这些新的 API 用法。

    ./gradlew lint
    
    MainActivity.kt:41: Error: Call requires API level 35 (current min is 34): java.util.List#removeFirst [NewApi]
          list.removeFirst()
    

    如需修复运行时异常和 lint 错误,可以在 Kotlin 中将 removeFirst()removeLast() 函数调用分别替换为 removeAt(0)removeAt(list.lastIndex)。如果您使用的是 Android Studio Ladybug | 2024.1.3 或更高版本,则该版本还提供了针对这些错误的快速修复选项。

    如果 lint 选项已停用,请考虑移除 @SuppressLint("NewApi")lintOptions { disable 'NewApi' }

  • 与 Java 中的其他方法冲突

    现有类型中添加了新方法,例如 ListDeque。这些新方法可能与其他接口和类中具有相同名称和参数类型的方法不兼容。如果方法签名发生冲突且不兼容,javac 编译器会输出构建时错误。例如:

    错误示例 1:

    javac MyList.java
    
    MyList.java:135: error: removeLast() in MyList cannot implement removeLast() in List
      public void removeLast() {
                  ^
      return type void is not compatible with Object
      where E is a type-variable:
        E extends Object declared in interface List
    

    错误示例 2:

    javac MyList.java
    
    MyList.java:7: error: types Deque<Object> and List<Object> are incompatible;
    public class MyList implements  List<Object>, Deque<Object> {
      both define reversed(), but with unrelated return types
    1 error
    

    错误示例 3:

    javac MyList.java
    
    MyList.java:43: error: types List<E#1> and MyInterface<E#2> are incompatible;
    public static class MyList implements List<Object>, MyInterface<Object> {
      class MyList inherits unrelated defaults for getFirst() from types List and MyInterface
      where E#1,E#2 are type-variables:
        E#1 extends Object declared in interface List
        E#2 extends Object declared in interface MyInterface
    1 error
    

    如需修复这些构建错误,实现这些接口的类应使用兼容的返回类型替换该方法。例如:

    @Override
    public Object getFirst() {
        return List.super.getFirst();
    }
    

Sicurezza

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

Versioni TLS con limitazioni

Android 15 limita l'utilizzo delle versioni TLS 1.0 e 1.1. Queste versioni erano precedentemente deprecate in Android, ma ora non sono consentite per le app che hanno come target Android 15.

Avvio di attività in background protette

Android 15 protegge gli utenti da app dannose e offre loro un maggiore controllo i propri dispositivi aggiungendo modifiche che impediscano ad app in background dannose di mettere in primo piano altre app, aumentare i loro privilegi e abusare interazione dell'utente. I lanci di attività in background sono stati limitati dal giorno Android 10 (livello API 29).

Impedisci alle app che non corrispondono all'UID principale nell'impilare di avviare attività

Le app dannose possono avviare l'attività di un'altra app all'interno della stessa attività, quindi sovrapporsi, creando l'illusione di essere quell'app. Questo attacco di "pirateria dell'attività" aggira le attuali limitazioni di lancio in background perché avviene all'interno della stessa attività visibile. Per ridurre questo rischio, Android 15 aggiunge un un flag che impedisce l'avvio delle app che non corrispondono all'UID principale nello stack attività. Per attivare tutte le attività delle app, aggiorna le allowCrossUidActivitySwitchFromBelow nel file AndroidManifest.xml dell'app:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

Le nuove misure di sicurezza sono attive se tutte le seguenti condizioni sono vere:

  • L'app che esegue il lancio ha come target Android 15.
  • L'app nella parte superiore dello stack di attività ha come target Android 15.
  • Per qualsiasi attività visibile sono state attivate le nuove protezioni

Se le misure di sicurezza sono attive, le app potrebbero tornare alla schermata Home anziché all'ultima app visibile se completano la propria attività.

Altre modifiche

Oltre alla limitazione per la corrispondenza dell'UID, anche queste altre modifiche vengono inclusi:

  • Modifica i creator di PendingIntent in modo che blocchino l'avvio delle attività in background per impostazione predefinita. In questo modo è possibile impedire alle app di creare accidentalmente un PendingIntent che potrebbero essere utilizzati in modo illecito da malintenzionati.
  • Non mettere un'app in primo piano a meno che il mittente PendingIntent lo consente. Questa modifica ha lo scopo di impedire alle app dannose di utilizzare in modo illecito possibilità di avviare attività in background. Per impostazione predefinita, alle app non è consentito portare la serie di attività in primo piano, a meno che il creator non consenta i privilegi di lancio delle attività in background o che il mittente non disponga di questi privilegi.
  • Controlla il modo in cui l'attività principale di uno stack di attività può completarne le attività. Se attività principale completa un'attività, Android torna all'attività precedente l'ultima attività. Inoltre, se un'attività non principale completa la propria attività, Android torna alla home page; non bloccherà la finitura di questa parte non superiore attività.
  • Impedisci di avviare attività arbitrarie da altre app alla tua. un'attività. Questa modifica impedisce alle app dannose di applicare phishing agli utenti creando attività che sembrano provenire da altre app.
  • Impedire che le finestre non visibili vengano prese in considerazione per l'attività in background Google Cloud. In questo modo è possibile evitare che app dannose utilizzino in modo illecito lo sfondo. viene avviata un'attività per mostrare agli utenti contenuti indesiderati o dannosi.

Intenzioni più sicure

Android 15 introduce nuove misure di sicurezza facoltative per rendere gli intent più sicuri e affidabili. Lo scopo di queste modifiche è prevenire le potenziali vulnerabilità e l'uso improprio di intent che possono essere sfruttati da app dannose. Ci sono due miglioramenti principali alla sicurezza degli intent in Android 15:

  • Corrispondenza ai filtri intent di destinazione: gli intent che hanno come target componenti specifici devono corrispondere con precisione alle specifiche dei filtri intent del target. Se invii un intento per avviare l'attività di un'altra app, il componente dell'intent di destinazione deve essere in linea con i filtri intent dichiarati dell'attività di destinazione.
  • Gli intent devono avere azioni: gli intent senza un'azione non corrisponderanno più a nessun filtro intent. Ciò significa che gli intent utilizzati per avviare attività o servizi devono avere un'azione chiaramente definita.

Per verificare in che modo la tua app risponde a queste modifiche, usa StrictMode nell'app. Per visualizzare log dettagliati sulle violazioni dell'utilizzo di Intent, aggiungi il seguente metodo:

Kotlin


fun onCreate() {
    StrictMode.setVmPolicy(VmPolicy.Builder()
        .detectUnsafeIntentLaunch()
        .build()
    )
}

Java


public void onCreate() {
    StrictMode.setVmPolicy(new VmPolicy.Builder()
            .detectUnsafeIntentLaunch()
            .build());
}

Esperienza utente e interfaccia utente di sistema

Android 15 include alcune modifiche volte a creare un'esperienza utente più coerente e intuitiva.

Modifiche all'incavo della finestra

In Android 15 sono presenti due modifiche relative agli inserti delle finestre: la visualizzazione edge-to-edge è applicata per impostazione predefinita e sono presenti anche modifiche alla configurazione, ad esempio la configurazione predefinita delle barre di sistema.

Applicazione edge-to-edge

Le app sono edge-to-edge per impostazione predefinita sui dispositivi con Android 15 se hanno come target Android 15 (livello API 35).

Un'app che ha come target Android 14 e non è edge-to-edge su un dispositivo Android 15.


Un'app che ha come target Android 15 (livello API 35) ed è edge-to-edge su un dispositivo Android 15. Questa app utilizza principalmente componenti Compose di Material 3 che applicano automaticamente gli inserti. Questa schermata non è interessata dall'applicazione delle norme relative alle schermate edge-to-edge di Android 15.

Si tratta di una modifica che potrebbe influire negativamente sull'interfaccia utente della tua app. Le modifiche interessano le seguenti aree dell'interfaccia utente:

  • Maniglia della barra di navigazione per i gesti
    • Trasparente per impostazione predefinita.
    • Lo spazio di compensazione in basso è disattivato, pertanto i contenuti vengono disegnati dietro la barra di navigazione del sistema, a meno che non vengano applicati gli inserti.
    • setNavigationBarColor e R.attr#navigationBarColor sono stati ritirati e non influiscono sulla navigazione tramite gesti.
    • setNavigationBarContrastEnforced e R.attr#navigationBarContrastEnforced continuano a non avere alcun effetto sulla navigazione con i gesti.
  • Navigazione con tre pulsanti
    • L'opacità è impostata su 80% per impostazione predefinita, con un colore che potrebbe corrispondere allo sfondo della finestra.
    • Lo spazio di compensazione in basso è disattivato, quindi i contenuti vengono disegnati dietro la barra di navigazione del sistema se non vengono applicati gli inserti.
    • Per impostazione predefinita, setNavigationBarColor e R.attr#navigationBarColor sono impostati in modo da corrispondere allo sfondo della finestra. Affinché questo valore predefinito venga applicato, lo sfondo della finestra deve essere una risorsa drawable a colori. Questa API è stata ritirata, ma continua a influire sulla navigazione con tre pulsanti.
    • setNavigationBarContrastEnforced e R.attr#navigationBarContrastEnforced sono veri per impostazione predefinita, il che aggiunge un sfondo opaco all'80% alla navigazione con tre pulsanti.
  • Barra di stato
    • Trasparente per impostazione predefinita.
    • L'offset superiore è disattivato, quindi i contenuti vengono disegnati dietro la barra di stato, a meno che non vengano applicati gli inserti.
    • setStatusBarColor e R.attr#statusBarColor sono stati ritirati e non hanno alcun effetto su Android 15.
    • setStatusBarContrastEnforced e R.attr#statusBarContrastEnforced sono deprecati, ma hanno ancora un effetto su Android 15.
  • Ritaglio del display
    • layoutInDisplayCutoutMode delle finestre non mobili deve essere LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. SHORT_EDGES, NEVER e DEFAULT vengono interpretati come ALWAYS in modo che gli utenti non vedano una barra nera causata dal ritaglio del display e che le app vengano visualizzate da un bordo all'altro.

L'esempio seguente mostra un'app prima e dopo aver scelto come target Android 15 (livello API 35) e prima e dopo l'applicazione degli inset.

Un'app che ha come target Android 14 e non è edge-to-edge su un dispositivo Android 15.
Un'app che ha come target Android 15 (livello API 35) ed è edge-to-edge su un dispositivo Android 15. Tuttavia, molti elementi ora sono nascosti dalla barra di stato, dalla barra di navigazione con tre pulsanti o dal ritaglio del display a causa dell'applicazione delle norme relative alla visualizzazione edge-to-edge di Android 15. L'interfaccia utente nascosta include la barra delle app Material 2 superiore, i pulsanti di azione fluttuanti e gli elementi dell'elenco.
Un'app che ha come target Android 15 (livello API 35), è edge to edge su un dispositivo Android 15 e applica inserti in modo che l'interfaccia utente non sia nascosta.
Cosa controllare se la tua app è già edge-to-edge

Se la tua app è già da bordo a bordo e applica inserti, non è prevista alcuna interruzione, tranne nei seguenti scenari. Tuttavia, anche se ritieni di non essere interessato, ti consigliamo di testare la tua app.

  • Hai una finestra non mobile, ad esempio un Activity che utilizza SHORT_EDGES, NEVER o DEFAULT anziché LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. Se la tua app si arresta in modo anomalo all'avvio, il problema potrebbe essere la schermata iniziale. Puoi eseguire l'upgrade della dipendenza core splashscreen alla versione 1.2.0-alpha01 o successiva oppure impostare window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always.
  • Potrebbero essere presenti schermate con traffico inferiore con UI ostruite. Verifica che queste schermate meno visitate non abbiano un'interfaccia utente occlusa. Le schermate con meno traffico includono:
    • Schermate di onboarding o di accesso
    • Pagine Impostazioni
Cosa controllare se la tua app non è già edge-to-edge

Se la tua app non è già edge-to-edge, è molto probabile che sia interessata. Oltre agli scenari per le app già a schermo intero, devi considerare quanto segue:

  • Se la tua app utilizza i componenti Material 3 ( androidx.compose.material3) in compose, come TopAppBar, BottomAppBar e NavigationBar, è probabile che questi componenti non siano interessati perché gestiscono automaticamente gli inserti.
  • Se la tua app utilizza i componenti Material 2 ( androidx.compose.material) in Compose, questi componenti non gestiscono automaticamente gli inserti. Tuttavia, puoi accedere agli insert e applicarli manualmente. In androidx.compose.material 1.6.0 e versioni successive, utilizza il parametro windowInsets per applicare manualmente gli inserti per BottomAppBar, TopAppBar, BottomNavigation e NavigationRail. Analogamente, utilizza il parametro contentWindowInsets per Scaffold.
  • Se la tua app utilizza viste e Componenti Materiale (com.google.android.material), la maggior parte dei Componenti Materiale basati su viste come BottomNavigationView, BottomAppBar, NavigationRailView o NavigationView gestisce gli inserti e non richiede alcun lavoro aggiuntivo. Tuttavia, devi aggiungere android:fitsSystemWindows="true" se utilizzi AppBarLayout.
  • Per i composabili personalizzati, applica gli inserti manualmente come spaziatura interna. Se i contenuti sono all'interno di un Scaffold, puoi utilizzare gli inserti utilizzando i valori di spaziatura Scaffold. In caso contrario, applica il padding utilizzando uno dei parametri WindowInsets.
  • Se la tua app utilizza visualizzazioni e BottomSheet, SideSheet o personalizzati contenuti, applica il padding utilizzando ViewCompat.setOnApplyWindowInsetsListener. Per RecyclerView, applica il padding utilizzando questo ascoltatore e aggiungi anche clipToPadding="false".
Cosa controllare se la tua app deve offrire una protezione in background personalizzata

Se la tua app deve offrire una protezione in background personalizzata alla barra di navigazione a tre pulsanti o alla barra di stato, deve posizionare un composable o una visualizzazione dietro la barra di sistema utilizzando WindowInsets.Type#tappableElement() per ottenere l'altezza della barra di navigazione a tre pulsanti o WindowInsets.Type#statusBars.

Risorse edge-to-edge aggiuntive

Consulta le guide sulle visualizzazioni edge to edge e sulla composizione edge to edge per ulteriori considerazioni sull'applicazione degli inserti.

API deprecate

Le seguenti API sono deprecate, ma non disattivate:

Le seguenti API sono obsolete e disabilitate:

Configurazione stabile

Se la tua app ha come target Android 15 (livello API 35) o versioni successive, Configuration non esclude più le barre di sistema. Se utilizzi le dimensioni dello schermo nella classe Configuration per il calcolo del layout, devi sostituirle con migliori alternative, ad esempio ViewGroup, WindowInsets o WindowMetricsCalculator appropriati, a seconda delle tue esigenze.

Configuration è disponibile dall'API 1. In genere viene ottenuta da Activity.onConfigurationChanged. Fornisce informazioni come densità, orientamento e dimensioni delle finestre. Una caratteristica importante delle dimensioni della finestra riportate da Configuration è che in precedenza escludevano le barre di sistema.

Le dimensioni della configurazione vengono in genere utilizzate per la selezione delle risorse, ad esempio/res/layout-h500dp, e questo è ancora un caso d'uso valido. Tuttavia, l'utilizzo per il calcolo del layout è sempre stato sconsigliato. In questo caso, allontanati subito. Dovresti sostituire l'uso di Configuration con qualcosa di più adatto in base al tuo caso d'uso.

Se lo utilizzi per calcolare il layout, utilizza un ViewGroup appropriato, ad esempio CoordinatorLayout o ConstraintLayout. Se lo utilizzi per determinare l'altezza della barra di navigazione di sistema, utilizza WindowInsets. Se vuoi conoscere le dimensioni attuali della finestra dell'app, utilizza computeCurrentWindowMetrics.

Il seguente elenco descrive i campi interessati da questa modifica:

Il valore predefinito dell'attributo elegantTextHeight è true

对于以 Android 15(API 级别 35)为目标平台的应用,elegantTextHeight TextView 属性默认会变为 true,将默认使用的紧凑字体替换为一些具有较大垂直测量的脚本,使其更易于阅读。紧凑字体旨在防止布局中断;Android 13(API 级别 33)允许文本布局利用 fallbackLineSpacing 属性拉伸垂直高度,从而防止许多此类中断。

在 Android 15 中,系统中仍保留了紧凑字体,因此您的应用可以将 elegantTextHeight 设置为 false 以获得与之前相同的行为,但即将发布的版本不太可能支持此字体。因此,如果您的应用支持以下脚本:阿拉伯语、老挝语、缅甸语、泰米尔语、古吉拉特语、卡纳达语、马拉雅拉姆语、奥里亚语、泰卢固语或泰语,请将 elegantTextHeight 设置为 true 以测试您的应用。

针对以 Android 14(API 级别 34)及更低版本为目标平台的应用的 elegantTextHeight 行为。
以 Android 15 为目标平台的应用的 elegantTextHeight 行为。

Modifiche alla larghezza di TextView per forme di lettere complesse

Nelle versioni precedenti di Android, alcuni caratteri corsivi o lingue con forme complesse potrebbero disegnare le lettere nell'area del carattere precedente o successivo. In alcuni casi, queste lettere sono state tagliate all'inizio o alla fine. A partire da Android 15, un TextView assegna una larghezza sufficiente per disegnare queste lettere e consente alle app di richiedere spaziature aggiuntive a sinistra per evitare il ritaglio.

Poiché questa modifica influisce sulla modalità di determinazione della larghezza da parte di TextView, per impostazione predefinita TextView allocate più larghezza se l'app ha come target Android 15 (livello API 35) o versioni successive. Puoi attivare o disattivare questo comportamento chiamando l'API setUseBoundsForWidth su TextView.

Poiché l'aggiunta di spaziatura interna a sinistra potrebbe causare un disallineamento dei layout esistenti, la spaziatura interna non viene aggiunta per impostazione predefinita anche per le app che hanno come target Android 15 o versioni successive. Tuttavia, puoi aggiungere un ulteriore spazio per evitare il ritaglio chiamando setShiftDrawingOffsetForStartOverhang.

Gli esempi riportati di seguito mostrano come queste modifiche possono migliorare il layout del testo per alcuni caratteri e lingue.

Layout standard per il testo inglese con carattere corsivo. Alcune lettere sono tagliate. Ecco il codice XML corrispondente:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
Layout per lo stesso testo in inglese con larghezza e spaziatura interna aggiuntive. Ecco il codice XML corrispondente:

<TextView
    android:fontFamily="cursive"
    android:text="java"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />
Layout standard per il testo thailandese. Alcune lettere sono tagliate. Ecco il codice XML corrispondente:

<TextView
    android:text="คอมพิวเตอร์" />
Layout per lo stesso testo thailandese con larghezza e spaziatura aggiuntivi. Ecco il codice XML corrispondente:

<TextView
    android:text="คอมพิวเตอร์"
    android:useBoundsForWidth="true"
    android:shiftDrawingOffsetForStartOverhang="true" />

Altezza della riga predefinita basata sulla lingua per EditText

Nelle versioni precedenti di Android, il layout del testo allungava l'altezza del testo per raggiungere l'altezza della riga del carattere corrispondente alle impostazioni internazionali correnti. Ad esempio, se i contenuti erano in giapponese, l'altezza del testo è aumentata leggermente perché l'altezza della riga del carattere giapponese è leggermente superiore a quella di un carattere latino. Tuttavia, nonostante queste differenze nelle altezze delle righe, le dimensioni dell'elemento EditText erano uniformi, indipendentemente dall'impostazione internazionale utilizzata, come illustrato nell'immagine seguente:

Tre caselle che rappresentano elementi EditText che possono contenere testo in inglese (en), giapponese (ja) e birmano (my). L'EditText è della stessa altezza, anche se queste lingue hanno altezze diverse.

Per le app che hanno come target Android 15 (livello API 35), ora è stata riservata un'altezza minima della riga per EditText in modo che corrisponda al carattere di riferimento per le impostazioni internazionali specificate, come mostrato nell'immagine seguente:

Tre caselle che rappresentano elementi EditText che possono contenere testo in inglese (en), giapponese (ja) e birmano (my). L'altezza del carattere EditText ora include lo spazio per l'altezza della riga predefinita per i caratteri di queste lingue.

Se necessario, l'app può ripristinare il comportamento precedente specificando l'attributo useLocalePreferredLineHeightForMinimum su false e può impostare metriche verticali minime personalizzate utilizzando l'API setMinimumFontMetrics in Kotlin e Java.

Fotocamera e contenuti multimediali

Android 15 apporta le seguenti modifiche al comportamento della fotocamera e dei contenuti multimediali per le app con target Android 15 o versioni successive.

Limitazioni per la richiesta dell'attenzione audio

Per richiedere l'attenzione audio, le app che hanno come target Android 15 (livello API 35) devono essere l'app principale o eseguire un servizio in primo piano. Se un'app tenta di richiedere lo stato attivo quando non soddisfa uno di questi requisiti, la chiamata restituisce AUDIOFOCUS_REQUEST_FAILED.

Per scoprire di più sul controllo audio, consulta l'articolo Gestire il controllo audio.

Limitazioni non SDK aggiornate

Android 15 include elenchi aggiornati di interfacce non SDK con limitazioni in base alla collaborazione con gli sviluppatori Android e ai test interni più recenti. Ove possibile, ci assicuriamo che siano disponibili alternative pubbliche prima di applicare limitazioni alle interfacce non SDK.

Se la tua app non ha come target Android 15, alcune di queste modifiche potrebbero non interessarti immediatamente. Tuttavia, anche se è possibile per la tua app accedere ad alcune interfacce non SDK a seconda del livello API target dell'app, l'utilizzo di qualsiasi metodo o campo non SDK comporta sempre un rischio elevato di interrompere l'app.

Se non sai con certezza se la tua app utilizza interfacce non SDK, puoi testarla per scoprirlo. Se la tua app si basa su interfacce non SDK, devi iniziare a pianificare una migrazione alle alternative SDK. Tuttavia, 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.

Per scoprire di più sulle modifiche in questa release di Android, consulta Aggiornamenti alle limitazioni relative alle interfacce non SDK in Android 15. Per saperne di più sulle interfacce non SDK in generale, consulta Limitazioni relative alle interfacce non SDK.