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

Come le release precedenti, Android 15 include modifiche del comportamento che potrebbero influire sulla tua app. Le seguenti modifiche del 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 modificare l'app per supportare correttamente questi comportamenti, ove applicabile.

Assicurati di esaminare anche l'elenco delle modifiche del comportamento che interessano tutte le app eseguite su Android 15 a prescindere dal nome (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

Stiamo apportando le seguenti modifiche ai servizi in primo piano con Android 15.

Comportamento di timeout del servizio in primo piano di sincronizzazione dei dati

Android 15 introduce un nuovo comportamento di timeout per dataSync per le app destinate ad Android 15 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 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(), si verificherà un errore con il seguente messaggio di errore: "Un servizio in primo piano di <fgs_type> non è stato interrotto entro il suo timeout: <component_name>". Nella versione beta 2, il messaggio di errore viene mostrato come errore ANR, ma in una release beta futura questo messaggio di errore genererà un'eccezione personalizzata.

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

  1. Fai in modo che il servizio implementi il nuovo metodo Service.onTimeout(int, int). Quando la tua app riceve il callback, assicurati di chiamare stopSelf() entro pochi secondi. Se non interrompi subito l'app, il sistema genera un guasto.
  2. Assicurati che i servizi dataSync della tua app non vengano eseguiti per più di 6 ore totali in 24 ore (a meno che l'utente non interagisca con l'app reimpostando il timer).
  3. Avvia dataSync servizi in primo piano solo a seguito di un'interazione diretta dell'utente; poiché la tua app è in primo piano all'avvio del servizio, quest'ultimo ha tutte le sei ore dopo che l'app è passata in background.
  4. Anziché utilizzare un servizio in primo piano dataSync, usa un'API alternativa.

Se i servizi in primo piano dataSync della tua app sono stati eseguiti per 6 ore negli ultimi 24, non puoi avviare un altro servizio in primo piano dataSync a meno che l'utente non abbia messo in primo piano la tua app (operazione che reimposta il timer). Se provi ad avviare un altro servizio in primo piano dataSync, il sistema genera ForegroundServiceStartNotAllowedException con un messaggio di errore come "Limite di tempo già esaurito per dataSync del tipo di servizio in primo piano".

Nuovo tipo di servizio in primo piano di elaborazione di contenuti multimediali

Android 15 introduce un nuovo tipo di servizio in primo piano, mediaProcessing. Questo tipo di servizio è appropriato per operazioni come la transcodifica di file multimediali. Ad esempio, un'app multimediale potrebbe scaricare un file audio e dover convertirlo in un formato diverso prima di riprodurlo. Puoi utilizzare un servizio mediaProcessing in primo piano per assicurarti che la conversione prosegua anche mentre l'app è in background.

Il sistema consente l'esecuzione dei servizi mediaProcessing 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 per chiamare Service.stopSelf(). Se il servizio non chiama Service.stopSelf(), si verificherà un errore con il messaggio: "Un servizio in primo piano di <fgs_type> non è stato interrotto entro il suo timeout: <component_name>". Nella versione beta 2, il messaggio di errore viene mostrato come errore ANR, ma in una release beta futura questo messaggio di errore genererà un'eccezione personalizzata.

Per evitare di ricevere un errore ANR, puoi eseguire una delle seguenti operazioni:

  1. Fai in modo che il servizio implementi il nuovo metodo Service.onTimeout(int, int). Quando la tua app riceve il callback, assicurati di chiamare stopSelf() entro pochi secondi. Se non interrompi subito l'app, il sistema genera un guasto.
  2. Assicurati che i servizi mediaProcessing della tua app non vengano eseguiti per più di 6 ore totali in 24 ore (a meno che l'utente non interagisca con l'app reimpostando il timer).
  3. Avvia mediaProcessing servizi in primo piano solo a seguito di un'interazione diretta dell'utente; poiché la tua app è in primo piano all'avvio del servizio, quest'ultimo ha tutte le sei ore dopo che l'app è passata in background.
  4. Anziché utilizzare un servizio in primo piano mediaProcessing, usa un'API alternativa, come WorkManager.

Se i servizi in primo piano mediaProcessing della tua app sono stati eseguiti per 6 ore negli ultimi 24, non puoi avviare un altro servizio in primo piano mediaProcessing a meno che l'utente non abbia messo in primo piano la tua app (operazione che reimposta il timer). Se provi ad avviare un altro servizio in primo piano mediaProcessing, il sistema genera ForegroundServiceStartNotAllowedException con un messaggio di errore come "Limite di tempo già esaurito per il tipo di servizio in primo piano mediaProcess".

Per ulteriori informazioni sul tipo di servizio mediaProcessing, consulta Modifiche ai tipi di servizi in primo piano per Android 15: elaborazione di contenuti multimediali.

Limitazioni sui ricevitori di trasmissioni BOOT_COMPLETED che avviano servizi in primo piano

Sono state applicate nuove limitazioni ai ricevitori di trasmissione BOOT_COMPLETED che lanciano servizi in primo piano. I ricevitori BOOT_COMPLETED non sono autorizzati ad avviare i seguenti tipi di servizi in primo piano:

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

Limitazioni relative all'avvio di servizi in primo piano quando un'app conserva l'autorizzazione SYSTEM_ALERT_WINDOW

In precedenza, se un'app aveva l'autorizzazione SYSTEM_ALERT_WINDOW, poteva avviare un servizio in primo piano anche se l'app era attualmente in background (come spiegato nelle esenzioni dalle limitazioni relative all'avvio in background).

Se un'app ha come target Android 15, l'esenzione è ora più limitata. L'app ora deve avere l'autorizzazione SYSTEM_ALERT_WINDOW e anche avere una finestra overlay visibile. In altre parole, l'app deve avviare una finestra TYPE_APPLICATION_OVERLAY e la finestra deve essere visibile prima di avviare un servizio in primo piano.

Se la tua app tenta di avviare un servizio in primo piano in background senza soddisfare questi nuovi requisiti (e non ha altre esenzione), il sistema genera ForegroundServiceStartNotAllowedException.

Se la tua app dichiara l'autorizzazione SYSTEM_ALERT_WINDOW e avvia i servizi in primo piano in background, questa modifica potrebbe essere interessata. Se la tua app riceve un ForegroundServiceStartNotAllowedException, controlla l'ordine delle operazioni dell'app e assicurati che abbia già una finestra di overlay attiva prima che provi ad avviare un servizio in primo piano in background. Puoi verificare se la finestra dell'overlay è attualmente visibile chiamando il numero View.getWindowVisibility() oppure eseguire l'override di View.onWindowVisibilityChanged() per ricevere una notifica ogni volta che la visibilità cambia.

Modifica degli orari in cui le app possono modificare lo stato globale della modalità Non disturbare

Le app destinate ad Android 15 non possono più modificare lo stato o il criterio globale della modalità Non disturbare su un dispositivo (modificando le impostazioni utente o disattivando la modalità DND). Le app devono però fornire un codice AutomaticZenRule, che il sistema combina in un criterio globale con lo schema con il criterio più restrittivo e vincente. Le chiamate alle API esistenti che in precedenza influenzavano lo stato globale (setInterruptionFilter, setNotificationPolicy) comportano la creazione o l'aggiornamento di un elemento AutomaticZenRule implicito, che viene attivato e disattivato a seconda del ciclo di chiamata di queste chiamate API.

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

Modifiche a OpenJDK 17

Android 15 continua il lavoro di aggiornamento delle librerie di base di Android per allinearsi alle funzionalità delle ultime release di OpenJDK LTS.

Una di queste modifiche potrebbe incidere sulla compatibilità delle app destinate ad Android 15:

  • Modifiche alle API di formattazione delle stringhe: la convalida di indice, flag, larghezza e precisione degli argomenti è ora più rigorosa quando si utilizzano le seguenti API String.format() e Formatter.format():

    Ad esempio, viene generata la seguente eccezione quando viene utilizzato un indice di argomento pari a 0 (%0 nella stringa di formato):

    IllegalFormatArgumentIndexException: Illegal format argument index = 0
    

    In questo caso, il problema può essere risolto utilizzando un indice di argomento pari a 1 (%1 nella stringa di formato).

  • Modifiche al tipo di componente Arrays.asList(...).toArray(): quando utilizzi Arrays.asList(...).toArray(), il tipo di componente dell'array risultante è ora un Object, non il tipo degli elementi dell'array sottostante. Di conseguenza, il seguente codice genera un errore ClassCastException:

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

    In questo caso, per conservare String come tipo di componente nell'array risultante, puoi utilizzare invece Collection.toArray(Object[]):

    String[] elements = Arrays.asList("two", "one").toArray(new String[0]);
    
  • Modifiche alla gestione del codice lingua: quando utilizzi l'API Locale, i codici lingua di ebraico, yiddish e indonesiano non vengono più convertiti nelle forme obsolete (ebraico: iw, yiddish: ji e indonesiano: in). Quando specifichi il codice lingua per una di queste impostazioni internazionali, utilizza invece i codici da ISO 639-1 (ebraico: he, Yiddish e indonesiano: yi/indonesiano).id

  • Modifiche alle sequenze di numeri interi casuali: dopo le modifiche apportate in https://bugs.openjdk.org/Sfoglia/JDK-8301574, i seguenti metodi Random.ints() restituiscono ora una sequenza di numeri diversa rispetto ai metodi Random.nextInt():

    In genere, questa modifica non dovrebbe comportare comportamenti in grado di interrompere l'app, ma il tuo codice non dovrebbe aspettarsi che la sequenza generata dai metodi Random.ints() corrisponda a Random.nextInt().

Sicurezza

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

Avvii di attività in background protette

Android 15 protegge gli utenti dalle app dannose e offre loro un maggiore controllo sui loro dispositivi aggiungendo modifiche che impediscono alle app dannose in background di portare altre app in primo piano, elevando i loro privilegi e abusando dell'interazione dell'utente. I lanci delle attività in background sono stati limitati a partire da Android 10 (livello API 29).

Impedisci alle app che non corrispondono all'UID principale dello stack di avviare attività

Le app dannose possono avviare l'attività di un'altra app nell'ambito della stessa attività per poi sovrapporsi alla parte superiore, creando l'illusione di essere quell'app. Questo attacco di "dirottamento dell'attività" bypassa le attuali limitazioni di avvio in background perché tutto avviene all'interno della stessa attività visibile. Per ridurre questo rischio, Android 15 aggiunge un flag che impedisce alle app che non corrispondono all'UID principale dello stack di avviare le attività. Per attivare tutte le attività della tua app, aggiorna l'attributo allowCrossUidActivitySwitchFromBelow nel file AndroidManifest.xml dell'app:

<application android:allowCrossUidActivitySwitchFromBelow="false" >

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

  • L'app che esegue il lancio ha come target Android 15.
  • L'app in cima allo stack di attività ha come target Android 15.
  • Le nuove protezioni sono state attivate per tutte le attività visibili

Se le misure di sicurezza sono attivate, 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 UID, sono incluse anche queste altre modifiche:

  • Modifica PendingIntent creator in modo da bloccare il lancio delle attività in background per impostazione predefinita. Ciò contribuisce a impedire che le app creino accidentalmente un PendingIntent che potrebbe essere utilizzato in modo illecito da malintenzionati.
  • Non portare un'app in primo piano a meno che il mittente PendingIntent non lo consenta. Questa modifica ha lo scopo di impedire ad app dannose di abusare della capacità di avviare attività in background. Per impostazione predefinita, alle app non è consentito portare in primo piano lo stack di attività, a meno che l'autore non autorizzi i privilegi di avvio per le attività in background o il mittente non disponga di privilegi di avvio per attività in background.
  • Controlla in che modo l'attività principale di una serie di attività può completarne l'attività. Se l'attività principale termina un'attività, Android torna all'attività più recente. Inoltre, se un'attività non principale completa la sua attività, Android torna alla schermata Home senza bloccare il completamento di questa attività non principale.
  • Impedisci di avviare attività arbitrarie da altre app nella tua attività. Questa modifica impedisce che le app dannose finiscano di phishing per gli utenti creando attività che sembrano provenire da altre app.
  • Impedisci che le finestre non visibili vengano prese in considerazione per l'avvio di attività in background. in modo da impedire che app dannose usino in modo illecito gli avvii delle attività in background per mostrare agli utenti contenuti indesiderati o dannosi.

Intent più sicuri

Android 15 introduce nuove misure di sicurezza per rendere le intenzioni più sicure e solide. Lo scopo di queste modifiche è prevenire 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:

  • Utilizza i filtri per intent di destinazione:gli intent che hanno come target componenti specifici devono corrispondere accuratamente alle specifiche del filtro per intent del target. Se invii un intent per lanciare l'attività di un'altra app, il componente di intent target deve essere in linea con i filtri di intent dichiarati dell'attività di ricezione.
  • Gli intent devono avere azioni:gli intent senza un'azione non corrisponderanno più ad alcun filtro di intent. Ciò significa che gli intent usati per avviare attività o servizi devono avere un'azione chiaramente definita.

Kotlin


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

Java


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

Esperienza utente e UI di sistema

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

Modifiche al riquadro delle finestre

Esistono due modifiche relative ai riquadri di finestre in Android 15: edge-to-edge è applicato per impostazione predefinita e esistono anche modifiche alla configurazione, ad esempio la configurazione predefinita delle barre di sistema.

Applicazione perimetrale

Le app sono edge-to-edge per impostazione predefinita sui dispositivi con Android 15 se hanno come target Android 15.

Un'app destinata ad Android 14 e non a livello perimetrale su un dispositivo Android 15.


Un'app destinata ad Android 15 e edge-to-edge su un dispositivo Android 15. Questa app utilizza principalmente componenti di Material 3 Compose che applicano automaticamente gli insiemi. Questo schermo non è influenzato negativamente dall'applicazione perimetrale di Android 15.

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

  • Barra di navigazione tramite gesto
    • Trasparente per impostazione predefinita.
    • L'offset inferiore è disabilitato, quindi i contenuti vengono spostati dietro la barra di navigazione del sistema, a meno che non vengano applicati gli insiemi.
    • Le app setNavigationBarColor e R.attr#navigationBarColor sono ritirate e non influiscono sulla navigazione tramite gesti.
    • setNavigationBarContrastEnforced e R.attr#navigationBarContrastEnforced continuano a non avere alcun effetto sulla navigazione tramite gesti.
  • Navigazione con tre pulsanti
    • Opacità impostata sull'80% per impostazione predefinita, con un colore che potrebbe corrispondere allo sfondo della finestra.
    • L'offset inferiore è disattivato in modo che i contenuti siano posizionati dietro la barra di navigazione del sistema, a meno che non vengano applicati gli insiemi.
    • Le impostazioni setNavigationBarColor e R.attr#navigationBarColor sono impostate per corrispondere allo sfondo della finestra per impostazione predefinita. Affinché si applichi questo valore predefinito, lo sfondo della finestra deve essere disegnato a colori. Questa API è deprecata, ma continua a influire sulla navigazione con tre pulsanti.
    • I criteri setNavigationBarContrastEnforced e R.attr#navigationBarContrastEnforced sono true per impostazione predefinita e aggiungono uno sfondo opaco dell'80% nella navigazione con tre pulsanti.
  • Barra di stato
    • Trasparente per impostazione predefinita.
    • L'offset superiore è disabilitato, quindi i contenuti sono posizionati dietro la barra di stato, a meno che non vengano applicati gli insiemi.
    • Le app setStatusBarColor e R.attr#statusBarColor sono ritirate e non hanno alcun effetto su Android 15.
    • Le app setStatusBarContrastEnforced e R.attr#statusBarContrastEnforced sono deprecate, ma hanno ancora un effetto su Android 15.
  • Ritaglio del display
    • Il 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 appaiano bordo a bordo.

L'esempio seguente mostra un'app prima e dopo il targeting di Android 15 e prima e dopo l'applicazione degli insiemi.

Un'app destinata ad Android 14 e non a livello perimetrale su un dispositivo Android 15.
Un'app per Android 15 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 delle applicazioni edge-to-edge di Android 15. La UI nascosta include la barra superiore dell'app Material 2, i pulsanti di azione mobili e le voci dell'elenco.
Un'app destinata ad Android 15 è edge-to-edge su un dispositivo Android 15 e applica inserti in modo che l'UI non sia nascosta.
Cosa controllare se la tua app è già edge-to-edge

Se la tua app è già edge-to-edge e utilizza gli insiemi, questa operazione non influisce in gran parte, ad eccezione degli scenari che seguono. Tuttavia, anche se ritieni che non ci siano conseguenze, ti consigliamo di testare la tua app.

  • Hai una finestra non mobile, ad esempio una Activity, che utilizza SHORT_EDGES, NEVER o DEFAULT anziché LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS. Se l'app si arresta in modo anomalo all'avvio, è possibile che sia dovuto alla schermata iniziale. Puoi eseguire l'upgrade della dipendenza della schermata iniziale principale a 1.2.0-alpha01 o a una versione successiva oppure impostare window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutInDisplayCutoutMode.always.
  • Potrebbero esserci schermate a traffico ridotto con UI nascosta. Verifica che queste schermate meno visitate non abbiano una UI nascosta. Le schermate a traffico più basso 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à a livello perimetrale, è molto probabile che il problema ti riguardi. Oltre agli scenari per le app già edge-to-edge, dovresti considerare quanto segue:

  • Se la tua app utilizza i componenti Material 3 (androidx.compose.material3) nella scrittura, ad esempio TopAppBar, BottomAppBar e NavigationBar, è probabile che questi componenti non siano interessati perché gestiscono automaticamente gli insiemi.
  • Se la tua app utilizza componenti di Material 2 ( androidx.compose.material) in Compose, questi componenti non gestiscono automaticamente gli insiemi. Tuttavia, puoi accedere agli insiemi e applicarli manualmente. In androidx.compose.material 1.6.0 e versioni successive, utilizza il parametro windowInsets per applicare manualmente gli insiemi per BottomAppBar, TopAppBar, BottomNavigation e NavigationRail. Allo stesso modo, utilizza il parametro contentWindowInsets per Scaffold.
  • Se la tua app utilizza le viste e i componenti Material (com.google.android.material), la maggior parte dei componenti Material basati sulle visualizzazioni, come BottomNavigationView, BottomAppBar, NavigationRailView o NavigationView, gestisce gli inserti e non richiedono alcun lavoro aggiuntivo. Tuttavia, devi aggiungere android:fitsSystemWindows="true" se utilizzi AppBarLayout.
  • Per gli elementi componibili personalizzati, applica manualmente gli insiemi come spaziatura interna. Se i tuoi contenuti si trovano all'interno di un valore Scaffold, puoi utilizzare i riquadri utilizzando i valori di spaziatura interna Scaffold. In caso contrario, applica la spaziatura interna utilizzando uno delle WindowInsets.
  • Se la tua app utilizza visualizzazioni e BottomSheet, SideSheet o container personalizzati, applica la spaziatura interna utilizzando ViewCompat.setOnApplyWindowInsetsListener. Per RecyclerView, applica la spaziatura interna utilizzando questo listener e aggiungi anche clipToPadding="false".
Cosa controllare se la tua app deve offrire una protezione dello sfondo personalizzata

Se la tua app deve offrire una protezione personalizzata in background per la navigazione con tre pulsanti o la barra di stato, devi posizionare una vista componibile o una vista 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 viste perimetrali e sulla scrittura da bordo a bordo per ulteriori considerazioni sull'applicazione degli insiemi.

API deprecate

Le seguenti API sono state ritirate:

Configurazione stabile

Se la tua app ha come target Android 15 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 alternative migliori, come ViewGroup, WindowInsets o WindowMetricsCalculator appropriate, a seconda delle tue esigenze.

Configuration è disponibile dall'API 1. In genere viene ottenuto da Activity.onConfigurationChanged. Fornisce informazioni come densità, orientamento e dimensioni delle finestre. Una caratteristica importante delle dimensioni delle finestre restituite da Configuration è che in precedenza le barre di sistema sono state escluse.

La dimensione della configurazione viene in genere utilizzata per la selezione delle risorse, ad esempio /res/layout-h500dp, e questo è ancora un caso d'uso valido. Tuttavia, è sempre stato sconsigliato utilizzare l'IA per il calcolo del layout. Se lo fai, dovresti abbandonarlo ora. Dovresti sostituire l'utilizzo di Configuration con qualcosa più adatto al tuo caso d'uso.

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

Nell'elenco che segue sono descritti i campi interessati da questa modifica:

  • Le dimensioni Configuration.screenWidthDp e screenHeightDp non escludono più le barre di sistema.
  • L'app Configuration.smallestScreenWidthDp è indirettamente interessata dalle modifiche a screenWidthDp e screenHeightDp.
  • L'app Configuration.orientation è indirettamente interessata dalle modifiche apportate a screenWidthDp e screenHeightDp sui dispositivi vicini a quadrati.
  • L'attività Display.getSize(Point) è indirettamente interessata dalle modifiche apportate a Configuration. Questa funzionalità è stata ritirata a partire dal livello API 30.
  • Display.getMetrics() funziona già in questo modo dal livello API 33.

L'attributo eleganteTextHeight è impostato su true per impostazione predefinita

Per le app che hanno come target Android 15, l'attributo elegantTextHeight TextView diventa true per impostazione predefinita, sostituendo il carattere compatto usato per impostazione predefinita con alcuni script che hanno metriche verticali di grandi dimensioni con una molto più leggibile. Il carattere compatto è stato introdotto per evitare interruzioni nei layout. Android 13 (livello API 33) impedisce molte di queste interruzioni consentendo al layout del testo di estendere l'altezza verticale utilizzando l'attributo fallbackLineSpacing.

In Android 15, il carattere compatto rimane ancora nel sistema, pertanto la tua app può impostare elegantTextHeight su false per avere lo stesso comportamento di prima, ma è improbabile che sia supportato nelle prossime release. Pertanto, se la tua app supporta i seguenti script: arabo, laotiano, Myanmar, tamil, gujarati, kannada, malayalam, Odia, telugu o thailandese, testa l'app impostando elegantTextHeight su true.

Comportamento di elegantTextHeight per le app che hanno come target Android 14 (livello API 34) e versioni precedenti.
Comportamento di elegantTextHeight per le app destinate ad Android 15.

Modifiche alla larghezza di TextView per forme di lettere complesse

Nelle versioni precedenti di Android, alcuni caratteri corsivi o alcune lingue con una modellazione complessa potrebbero tracciare le lettere nell'area del carattere precedente o successivo. In alcuni casi, tali lettere venivano tagliate nella posizione iniziale o finale. A partire da Android 15, un elemento TextView alloca la larghezza per ricavare spazio sufficiente per queste lettere e consente alle app di richiedere spaziatura interna extra a sinistra per evitare il ritaglio.

Poiché questa modifica influisce sul modo in cui un elemento TextView decide la larghezza, TextView assegna una maggiore larghezza per impostazione predefinita se l'app ha come target Android 15 o versioni successive. Puoi abilitare o disabilitare questo comportamento chiamando l'API setUseBoundsForWidth su TextView.

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

I seguenti esempi mostrano come queste modifiche possono migliorare il layout del testo per alcuni caratteri e lingue.

Layout standard per il testo in inglese in corsivo. Alcune lettere sono troncate. Ecco il codice XML corrispondente:

<TextView
    android:fontFamily="cursive"
    android:text="java" />
Layout per lo stesso testo 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 in thailandese. Alcune lettere sono tagliate. Ecco il codice XML corrispondente:

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

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

Altezza riga predefinita sensibile alle impostazioni internazionali per EditText

Nelle versioni precedenti di Android, il layout del testo estendeva l'altezza del testo per adattarlo all'altezza della riga del carattere corrispondente alle impostazioni internazionali correnti. Ad esempio, se i contenuti erano in giapponese, poiché l'altezza della riga del carattere giapponese è leggermente più grande di quella di un carattere latino, l'altezza del testo è aumentata leggermente. Tuttavia, nonostante queste differenze di altezza delle righe, le dimensioni dell'elemento EditText sono state uniformi, indipendentemente dall'impostazione internazionale utilizzata, come illustrato nell'immagine seguente:

Tre riquadri che rappresentano gli elementi EditText che possono contenere testo in inglese (en), giapponese (ja) e birmano (my). L'altezza dell'elemento EditText è la stessa, anche se queste lingue hanno righe di altezza diverse l'una dall'altra.

Per le app che hanno come target Android 15, ora viene riservata un'altezza minima della riga per EditText affinché corrisponda al carattere di riferimento per le impostazioni internazionali specificate, come mostrato nella seguente immagine:

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

Se necessario, la tua app può ripristinare il comportamento precedente specificando l'attributo useLocalePreferredLineHeightForMinimum su false e la tua app 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 che hanno come target Android 15 o versioni successive.

Limitazioni relative alla richiesta di messa a fuoco audio

Le app destinate ad Android 15 devono essere l'app principale o eseguire un servizio in primo piano relativo all'audio per richiedere lo stato attivo dell'audio. Se un'app tenta di richiedere lo stato attivo quando non soddisfa uno di questi requisiti, la chiamata restituisce AUDIOFOCUS_REQUEST_FAILED.

Un servizio in primo piano è considerato correlato all'audio se il tipo è mediaPlayback, camera, microphone o phoneCall.

Per scoprire di più sul focus audio, consulta Gestire il focus audio.

Limitazioni non SDK aggiornate

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

Se la tua app non è destinata ad Android 15, alcune di queste modifiche potrebbero non essere applicate immediatamente. Tuttavia, sebbene sia possibile per la tua app accedere ad alcune interfacce non SDK a seconda del livello API target dell'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.

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