Supporto di più finestre

La modalità multi-finestra consente a più app di condividere lo stesso schermo contemporaneamente. Le app possono essere affiancate o una sopra l'altra (modalità schermo diviso), un'app in una piccola finestra sovrapposta ad altre app (modalità Picture in picture) o singole app in finestre mobili e ridimensionabili separate (modalità formato libero).

Figura 1. Visualizza due app affiancate in modalità schermo diviso.

L'esperienza utente dipende dalla versione di Android e dal tipo di dispositivo:

  • Android 7.0 (livello API 24) ha introdotto la modalità schermo diviso sui dispositivi con schermi piccoli e la modalità Picture in picture su alcuni dispositivi.

    • La modalità schermo diviso riempie lo schermo di due app, che vengono mostrate una accanto all'altra o una sopra l'altra. Gli utenti possono trascinare il divisore separando le due app per ingrandire un'app e l'altra.

    • La modalità Picture in picture consente agli utenti di continuare la riproduzione del video durante l'interazione con un'altra app (vedi Supporto di Picture in picture).

    • La modalità in formato libero, che consente agli utenti di ridimensionare liberamente ogni attività, può essere attivata dai produttori di dispositivi con schermi di grandi dimensioni.

    Puoi configurare il modo in cui l'app gestisce la modalità multi-finestra specificando le dimensioni minime consentite dell'attività. Puoi anche disattivare la modalità multi-finestra per la tua app impostando resizeabableActivity="false" per assicurarti che il sistema mostri sempre l'app a schermo intero.

  • Android 8.0 (livello API 26) estende la modalità Picture in picture ai dispositivi con schermi piccoli.

  • Android 12 (livello API 31) imposta il comportamento standard della modalità multi-finestra.

    • Su schermi di grandi dimensioni (larghezza minima >= 600 dp), la piattaforma supporta tutte le app in modalità multi-finestra, indipendentemente dalla configurazione. Se resizeableActivity="false", l'app viene attivata in modalità di compatibilità quando necessario per adattarsi alle dimensioni del display.

    • Su schermi piccoli (larghezza minima < 600 dp), il sistema controlla minWidth e minHeight di un'attività per determinare se può essere eseguita in modalità multi-finestra. Se resizeableActivity="false", non è possibile eseguire l'app in modalità multi-finestra a prescindere dalla larghezza e dall'altezza minime.

Modalità schermo diviso

Gli utenti possono attivare la modalità schermo diviso procedendo nel seguente modo:

  1. Apri la schermata Recenti.
  2. Visualizzazione di un'app tramite scorrimento
  3. Premi l'icona dell'app nella barra del titolo dell'app
  4. Seleziona l'opzione di menu per lo schermo diviso
  5. Seleziona un'altra app dalla schermata Recenti o chiudi la schermata Recenti ed esegui un'altra app

Gli utenti possono uscire dalla modalità schermo diviso trascinando il divisore delle finestre fino al bordo dello schermo: verso l'alto o verso il basso, a sinistra o a destra.

Lancia adiacente

Se la tua app deve accedere ai contenuti tramite un intent, puoi utilizzare FLAG_ACTIVITY_LAUNCH_ADJACENT per aprire i contenuti in una finestra a schermo diviso adiacente.

FLAG_ACTIVITY_LAUNCH_ADJACENT è stato introdotto in Android 7.0 (livello API 24) per consentire alle app in esecuzione in modalità schermo diviso di avviare attività nella finestra adiacente.

Android 12L (livello API 32) e versioni successive hanno esteso la definizione del flag per consentire alle app con schermo intero di attivare la modalità schermo diviso e quindi avviare le attività nella finestra adiacente.

Per avviare un'attività adiacente, utilizza FLAG_ACTIVITY_LAUNCH_ADJACENT insieme a FLAG_ACTIVITY_NEW_TASK, ad esempio:

Kotlin

fun openUrlInAdjacentWindow(url: String) {
    Intent(Intent.ACTION_VIEW).apply {
        data = Uri.parse(url)
        addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or
                           Intent.FLAG_ACTIVITY_NEW_TASK)
    }.also { intent ->
        startActivity(intent)
    }
}

Java

public void openUrlInAdjacentWindow(String url) {
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setData(Uri.parse(url));
    intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
}

Ciclo di vita dell'attività in modalità multi-finestra

La modalità multi-finestra non modifica il ciclo di vita dell'attività. Tuttavia, lo stato ripristinato delle app in più finestre varia a seconda delle versioni di Android.

Ripresa multipla

Android 10 (livello API 29) e versioni successive supportano la ripresa multipla: tutte le attività rimangono nello stato RESUMED quando il dispositivo è in modalità multi-finestra. Un'attività può essere messa in pausa se sopra l'attività è presente un'attività trasparente o se non è attivabile, ad esempio se è in modalità Picture in picture. È anche possibile che in un determinato momento non sia attiva alcuna attività, ad esempio se il riquadro di notifica a scomparsa è aperto. Il metodo onStop() funziona come al solito: viene chiamato ogni volta che un'attività viene rimossa dallo schermo.

Il ripristino multiplo è disponibile anche su alcuni dispositivi con Android 9 (livello API 28). Per attivare il ripristino multiplo sui dispositivi Android 9, aggiungi i seguenti metadati manifest:

<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />

Per verificare se un determinato dispositivo supporta questi metadati manifest, consulta le specifiche del dispositivo.

Android 9

In modalità multi-finestra su Android 9 (livello API 28) e versioni precedenti, in un determinato momento è attiva solo l'attività con cui l'utente ha interagito più di recente. Questa attività è considerata più in alto ed è l'unica attività nello stato RESUMED. Tutte le altre attività visibili sono STARTED, ma non sono RESUMED. Tuttavia, il sistema assegna una priorità maggiore a queste attività visibili ma non riprese rispetto a quelle che non sono visibili. Se l'utente interagisce con una delle attività visibili, l'attività viene ripresa e l'attività più in alto entra nello stato STARTED.

Quando sono presenti più attività all'interno di un singolo processo di app attivo, l'attività con l'ordine Z più alto viene ripresa, mentre le altre vengono messe in pausa.

Modifiche alla configurazione

Quando l'utente attiva un'app in modalità multi-finestra, il sistema notifica l'attività di una modifica alla configurazione come specificato in Gestire le modifiche alla configurazione. Lo stesso accade anche quando l'utente ridimensiona l'app o la reimposta alla modalità a schermo intero.

In sostanza, questa modifica ha le stesse implicazioni del ciclo di vita delle attività di quando il sistema avvisa l'app che il dispositivo è passato dall'orientamento verticale a quello orizzontale, ad eccezione del fatto che le dimensioni dell'app vengono modificate invece di essere semplicemente scambiate. La tua attività può gestire la modifica alla configurazione oppure l'app può consentire al sistema di eliminare l'attività e ricrearla con le nuove dimensioni.

Se l'utente ridimensiona una finestra e la ingrandisce in entrambe le dimensioni, il sistema ridimensiona l'attività in base all'azione dell'utente e apporta modifiche alla configurazione, se necessario. Se l'app è indietro nel disegnare nelle aree appena esposte, il sistema riempie temporaneamente queste aree con il colore specificato dall'attributo windowBackground o dall'attributo di stile windowBackgroundFallback predefinito.

Accesso esclusivo alle risorse

Per supportare la funzionalità di ripresa multipla, utilizza il callback del ciclo di vita di onTopResumedActivityChanged().

Il callback viene richiamato quando un'attività raggiunge o perde la prima posizione di attività ripresa. Questo è importante quando un'attività utilizza una risorsa singleton condivisa, come il microfono o la videocamera.

Kotlin

override fun onTopResumedActivityChanged(topResumed: Boolean) {
    if (topResumed) {
        // Top resumed activity
        // Can be a signal to re-acquire exclusive resources
    } else {
        // No longer the top resumed activity
    }
}

Java

@Override
public void onTopResumedActivityChanged(boolean topResumed) {
    if (topResumed) {
        // Top resumed activity
        // Can be a signal to re-acquire exclusive resources
    } else {
        // No longer the top resumed activity
    }
}

Tieni presente che un'app può perdere risorse per altri motivi, ad esempio la rimozione di un componente hardware condiviso.

In ogni caso, un'app deve gestire agevolmente gli eventi e le modifiche dello stato che influiscono sulle risorse disponibili.

Per le app che utilizzano una fotocamera, CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() suggerisce che potrebbe essere un buon momento per provare ad accedere alla fotocamera. Questo metodo è disponibile a partire da Android 10 (livello API 29).

Ricorda che resizeableActivity=false non garantisce l'accesso esclusivo alla fotocamera, poiché le altre app che utilizzano la fotocamera possono essere aperte su altri display.

Figura 2. Fotocamera in modalità multi-finestra.

Non è necessario che l'app rilasci la fotocamera quando perde la messa a fuoco. Ad esempio, potresti voler continuare l'anteprima della fotocamera mentre l'utente interagisce con l'app ripresa più in alto e appena messa a fuoco. L'app può continuare a eseguire la videocamera anche se non è l'app ripresa più in alto, ma deve gestire correttamente la richiesta di disconnessione. Quando l'app ripresa più in alto vuole usare la videocamera, può aprirla e l'app perderà l'accesso. L'app può riaprire la fotocamera quando viene ripristinata la messa a fuoco.

Dopo che un'app riceve un callback di CameraDevice.StateCallback#onDisconnected(), per le chiamate successive sulla videocamera verrà visualizzato un messaggio CameraAccessException.

Multi-display

Android 10 (livello API 29) supporta le attività su display secondari. Se un'attività è in esecuzione su un dispositivo con più display, gli utenti possono spostarla da un display all'altro. L'opzione ripresa multipla si applica anche a scenari multischermo; diverse attività possono ricevere l'input dell'utente contemporaneamente.

Un'app può specificare su quale display deve essere eseguita all'avvio o quando crea un'altra attività. Questo comportamento dipende dalla modalità di avvio dell'attività definita nel file manifest, nonché dalle opzioni e dai flag di intent impostati dall'entità che avvia l'attività. Per ulteriori dettagli, consulta il corso ActivityOptions.

Quando un'attività passa a un display secondario, può essere sottoposta a un aggiornamento di contesto, al ridimensionamento delle finestre e a modifiche alla configurazione e alle risorse. Se l'attività gestisce la modifica alla configurazione, l'attività viene notificata in onConfigurationChanged(); in caso contrario, l'attività viene riavviata.

Un'attività deve controllare la visualizzazione corrente in onCreate() e onConfigurationChanged() se gestisce la modifica alla configurazione. Assicurati di aggiornare le risorse e i layout quando la visualizzazione cambia.

Se la modalità di avvio selezionata per un'attività consente più istanze, l'avvio da una schermata secondaria può creare una nuova istanza dell'attività. Entrambe le attività vengono riprese contemporaneamente.

Figura 3.Più istanze di un'attività su più display.

Puoi anche scoprire di più sulle API multi-display che sono state introdotte in Android 8.0.

Attività e contesto dell'applicazione

Per il multi-display è fondamentale utilizzare il contesto giusto. Quando accedi alle risorse, il contesto dell'attività (che viene visualizzato) è diverso da quello dell'applicazione (che non lo è).

Il contesto dell'attività contiene informazioni sulla visualizzazione ed è sempre regolato per l'area di visualizzazione in cui compare l'attività. In questo modo puoi ottenere le informazioni corrette sulle metriche relative alla densità o alla finestra della tua app. Dovresti utilizzare sempre il contesto dell'attività (o un altro contesto basato sull'interfaccia utente) per ottenere informazioni sulla finestra o sulla visualizzazione corrente. Questa operazione riguarda anche alcune API di sistema che utilizzano informazioni provenienti dal contesto (ad esempio, consulta Panoramica di Toast).

La configurazione della finestra delle attività e la visualizzazione principale definiscono le risorse e il contesto. Ottieni la visualizzazione attuale come segue:

Kotlin

val activityDisplay = activity.getDisplay()

Java

Display activityDisplay = activity.getDisplay();

Visualizza le metriche della finestra di attività corrente:

Kotlin

val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()

Java

WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();

Ottieni le metriche massime di finestra per la configurazione di sistema attuale:

Kotlin

val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()

Java

WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();

Le metriche massime relative alle finestre consentono di effettuare calcoli, scelte di layout o per determinare le dimensioni delle risorse da recuperare in anticipo. La disponibilità in onCreate() ti consente di prendere queste decisioni prima che venga superato il primo layout. Queste metriche non devono essere utilizzate per posizionare specifici elementi di visualizzazione, ma usare le informazioni dell'oggetto Configuration.

Ritagli display

I dispositivi pieghevoli potrebbero avere una geometria di ritaglio diversa quando sono piegati e non piegati. Per evitare problemi di ritagli, consulta l'articolo Supporto di ritagli display.

Display secondari

Puoi scaricare i display disponibili dal servizio di sistema DisplayManager:

Kotlin

val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
val displays = displayManager.getDisplays()

Java

DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = displayManager.getDisplays();

Utilizza la classe Display per ottenere informazioni su un determinato display, ad esempio le dimensioni di visualizzazione o i flag che indicano se un display è sicuro. Tuttavia, non dare per scontato che le dimensioni di visualizzazione saranno le stesse dell'area di visualizzazione allocata alla tua applicazione. Ricorda che in modalità multi-finestra l'applicazione occupa una parte del display.

Stabilisci se un'attività può essere avviata su un display:

Kotlin

val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
val activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)

Java

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
boolean activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent);

Poi avvia l'attività sul display:

Kotlin

val options = ActivityOptions.makeBasic()
options.setLaunchDisplayId(targetDisplay.displayId)
startActivity(intent, options.toBundle())

Java

ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(targetDisplay.displayId);
startActivity(intent, options.toBundle());

Supporto di più display

Android offre il supporto multi-display per tastiere software, sfondi e Avvio app.

Tastiera software

Una tastiera può essere mostrata su una schermata secondaria se il display è configurato per supportare le decorazioni del sistema. L'editor del metodo di immissione viene visualizzato automaticamente se un campo di testo richiede input su quel display.

Figura 4. Tastiera su un display secondario.

Sfondo

In Android 10 (livello API 29), le schermate secondarie possono avere uno sfondo. Il framework crea un'istanza separata di WallpaperService.Engine per ogni display. Assicurati che la superficie di ogni motore sia disegnata in modo indipendente. Gli sviluppatori possono caricare gli asset utilizzando il contesto di visualizzazione in WallpaperService.Engine#getDisplayContext(). Inoltre, assicurati che il WallpaperInfo.xmlset di file android:supportsMultipleDisplays="true".

Figura 5. Sfondo sul telefono e sul display secondario.

Avvio app

Una nuova categoria di filtri per intent, SECONDARY_HOME, fornisce un'attività dedicata per le schermate secondarie. Le istanze dell'attività vengono utilizzate su tutti i display che supportano le decorazioni del sistema, una per ogni display.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

L'attività deve avere una modalità di avvio che non impedisca l'esecuzione di più istanze e in grado di adattarsi a dimensioni dello schermo diverse. La modalità di avvio non può essere singleInstance o singleTask.

Ad esempio, l'implementazione AOSP di Launcher3 supporta un'attività SECONDARY_HOME.

Figura 6. Avvio app di Material Design su uno smartphone.
Figura 7. Avvio app di Material Design su un display secondario.

Metriche finestra

Android 11 (livello API 30) ha introdotto i seguenti metodi WindowManager per definire i limiti delle app in esecuzione in modalità multi-finestra:

I metodi della libreria Jetpack WindowManager computeCurrentWindowMetrics() e computeMaximumWindowMetrics() offrono rispettivamente funzionalità simili, ma con compatibilità con le versioni precedenti al livello API 14.

Per ottenere metriche per display diversi da quella corrente, procedi nel seguente modo (come mostrato nello snippet di codice):

  • Creare un contesto di visualizzazione
  • Crea un contesto della finestra per il display
  • Ottieni WindowManager del contesto della finestra
  • Ottieni una percentuale pari a WindowMetrics dell'area di visualizzazione massima disponibile per l'app

Kotlin

val windowMetrics = context.createDisplayContext(display)
                    .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
                    .getSystemService(WindowManager::class.java)
                    .maximumWindowMetrics

Java

WindowMetrics windowMetrics = context.createDisplayContext(display)
                              .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
                              .getSystemService(WindowManager.class)
                              .getMaximumWindowMetrics();

Metodi deprecati

I metodi Display getSize() e getMetrics() sono stati deprecati nel livello API 30 in favore dei nuovi metodi WindowManager.

Android 12 (livello API 31) ritira i metodi Display getRealSize() e getRealMetrics() e ne aggiorna il comportamento in modo che corrisponda meglio al comportamento di getMaximumWindowMetrics().

Configurazione della modalità multi-finestra

Se la tua app ha come target Android 7.0 (livello API 24) o versioni successive, puoi configurare in che modo e se le attività dell'app supportano la modalità multi-finestra. Puoi impostare attributi nel file manifest per controllare sia la dimensione sia il layout. Le impostazioni degli attributi di un'attività principale si applicano a tutte le attività all'interno del relativo stack. Ad esempio, se l'attività principale ha android:resizeableActivity="true", tutte le attività nello stack di attività sono ridimensionabili. Su alcuni dispositivi più grandi, come i Chromebook, la tua app potrebbe essere eseguita in una finestra ridimensionabile anche se specifichi android:resizeableActivity="false". Se si verificano problemi relativi alla tua app, puoi usare i filtri su Google Play per limitarne la disponibilità su questi dispositivi.

Android 12 (livello API 31) utilizza la modalità multi-finestra per impostazione predefinita. Su schermi di grandi dimensioni (sw >= 600 dp), tutte le app vengono eseguite in modalità multi-finestra, indipendentemente dalla loro configurazione. Sugli schermi piccoli, il sistema controlla le impostazioni minWidth, minHeight e resizeableActivity di un'attività per determinare se l'attività può essere eseguita in modalità multi-finestra.

resizeableActivity

Imposta questo attributo nell'elemento <activity> o <application> del file manifest per attivare o disattivare la modalità multi-finestra per il livello API 30 e livelli precedenti:

<application
  android:name=".MyActivity"
  android:resizeableActivity=["true" | "false"] />;

Se questo attributo è impostato su true, l'attività può essere avviata in modalità schermo diviso e formato libero. Se l'attributo è impostato su false, l'attività non supporta la modalità multi-finestra. Se il valore è false e l'utente tenta di avviare l'attività in modalità multi-finestra, l'attività occupa la modalità a schermo intero.

Se la tua app ha come target il livello API 24 o superiore, ma non specifichi un valore per questo attributo, il valore predefinito dell'attributo sarà "true".

Se la tua app ha come target il livello API 31 o superiore, questo attributo funziona in modo diverso su schermi piccoli e grandi:

  • Schermi grandi (sw >= 600 dp): tutte le app supportano la modalità multi-finestra. L'attributo indica se un'attività può essere ridimensionata. Se resizeableActivity="false", l'app viene attivata in modalità di compatibilità quando necessario per adattarsi alle dimensioni del display.
  • Schermate piccole (sw < 600 dp): se resizeableActivity="true" e la larghezza e l'altezza minima dell'attività rientrano nei requisiti per la modalità multi-finestra, l'attività supporta la modalità multi-finestra. Se resizeableActivity="false", l'attività non supporta la modalità multi-finestra a prescindere dalla larghezza e altezza minime dell'attività.

supportsPictureInPicture

Imposta questo attributo nel nodo <activity> del file manifest per indicare se l'attività supporta la modalità Picture in picture.

<activity
  android:name=".MyActivity"
  android:supportsPictureInPicture=["true" | "false"] />

configChanges

Per gestire autonomamente le modifiche alla configurazione multi-finestra, ad esempio quando un utente ridimensiona una finestra, aggiungi l'attributo android:configChanges al nodo manifest dell'app <activity> con almeno i seguenti valori:

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize | smallestScreenSize
      | screenLayout | orientation" />

Dopo aver aggiunto android:configChanges, l'attività e i frammenti ricevono un callback a onConfigurationChanged() anziché essere eliminati e ricreati. In seguito, puoi aggiornare manualmente le visualizzazioni, ricaricare le risorse ed eseguire altre operazioni in base alle esigenze.

<layout>

Su Android 7.0 (livello API 24) e versioni successive, l'elemento manifest <layout> supporta diversi attributi che influiscono sul comportamento di un'attività in modalità multi-finestra:

  • android:defaultHeight, android:defaultWidth: altezza e larghezza predefinite dell'attività quando viene avviata in modalità in formato libero.

  • android:gravity: il posizionamento iniziale dell'attività quando viene avviata in modalità in formato libero. Consulta la classe Gravity per i valori idonei.

  • android:minHeight, android:minWidth: altezza e larghezza minime per l'attività sia in modalità schermo diviso che in formato libero. Se l'utente sposta il divisore in modalità schermo diviso per ridurre l'attività rispetto al minimo specificato, il sistema ritaglia l'attività alla dimensione richiesta dall'utente.

Il codice seguente mostra come specificare le dimensioni e la località predefinite di un'attività, e le sue dimensioni minime, quando l'attività viene visualizzata in modalità in formato libero:

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end|..."
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

Modalità multi-finestra in fase di esecuzione

A partire da Android 7.0, il sistema offre funzionalità per supportare le app che possono essere eseguite in modalità multi-finestra.

Funzionalità disattivate in modalità multi-finestra

In modalità multi-finestra, Android potrebbe disattivare o ignorare le funzionalità che non si applicano a un'attività che condivide lo schermo del dispositivo con altre attività o app.

Inoltre, alcune opzioni di personalizzazione dell'interfaccia utente di sistema sono disattivate. Ad esempio, le app non possono nascondere la barra di stato se sono in esecuzione in modalità multi-finestra (vedi Controllare la visibilità dell'interfaccia utente di sistema).

Il sistema ignora le modifiche all'attributo android:screenOrientation.

Query e callback in modalità multi-finestra

La classe Activity offre i seguenti metodi per supportare la modalità multi-finestra:

  • isInMultiWindowMode(): indica se l'attività è in modalità multi-finestra.

  • isInPictureInPictureMode(): indica se l'attività è in modalità Picture in picture.

  • onMultiWindowModeChanged(): il sistema chiama questo metodo ogni volta che l'attività entra o disattiva la modalità multi-finestra. Il sistema passa al metodo un valore true se l'attività entra in modalità multi-finestra o false se l'attività sta uscendo dalla modalità multi-finestra.

  • onPictureInPictureModeChanged(): il sistema chiama questo metodo ogni volta che l'attività entra o disattiva la modalità Picture in picture. Il sistema trasmette al metodo il valore true se l'attività entra in modalità Picture in picture o false se l'attività esce dalla modalità Picture in picture.

La classe Fragment espone le versioni di molti di questi metodi, ad esempio Fragment.onMultiWindowModeChanged().

Modalità Picture in picture

Per impostare un'attività in modalità Picture in picture, chiama enterPictureInPictureMode(). Questo metodo non ha effetto se il dispositivo non supporta la modalità Picture in picture. Per maggiori informazioni, vedi Aggiungere video utilizzando Picture in picture (PIP).

Nuove attività in modalità multi-finestra

Quando avvii una nuova attività, puoi indicare che la nuova attività deve essere visualizzata accanto a quella corrente, se possibile. Utilizza il flag di intent FLAG_ACTIVITY_LAUNCH_ADJACENT, che indica al sistema di provare a creare la nuova attività in una finestra adiacente, in modo che le due attività condividano lo schermo. Il sistema fa il possibile, ma non è garantito che ciò avvenga.

Se un dispositivo è in modalità in formato libero e stai avviando una nuova attività, puoi specificare le dimensioni della nuova attività e la posizione dello schermo chiamando ActivityOptions.setLaunchBounds(). Il metodo non ha effetto se il dispositivo non è in modalità multi-finestra.

A livello API 30 e versioni precedenti, se lanci un'attività all'interno di uno stack di attività, l'attività sostituisce l'attività sullo schermo, ereditando tutte le sue proprietà multi-finestra. Se vuoi avviare la nuova attività come finestra separata in modalità multi-finestra, devi avviarla in un nuovo stack di attività.

Android 12 (livello API 31) consente alle app di suddividere la finestra delle attività di un'applicazione tra più attività. Puoi stabilire in che modo l'app visualizza le sue attività (a schermo intero, affiancate o in pila) creando un file di configurazione XML o effettuando chiamate API Jetpack WindowManager.

Trascina

Gli utenti possono trascinare i dati da un'attività all'altra mentre le due attività condividono lo schermo. Prima di Android 7.0, gli utenti potevano trascinare i dati solo per una singola attività. Per aggiungere rapidamente il supporto dell'accettazione dei contenuti eliminati, consulta l'API DropHelper. Per indicazioni complete sul trascinamento, consulta l'articolo Attivare il trascinamento.

Multiistanza

Ogni attività principale ha la propria attività, che viene eseguita in un processo separato e viene visualizzata in una propria finestra. Per avviare una nuova istanza dell'app in una finestra separata, puoi avviare nuove attività con il flag FLAG_ACTIVITY_NEW_TASK. Puoi combinare questa impostazione con alcuni degli attributi multi-finestra per richiedere una posizione specifica per la nuova finestra. Ad esempio, un'app di shopping può mostrare più finestre per confrontare i prodotti.

Android 12 (livello API 31) consente di avviare due istanze di un'attività affiancate nella stessa finestra di attività.

Se vuoi consentire agli utenti di avviare un'altra istanza della tua applicazione da Avvio applicazioni o dalla barra delle applicazioni, assicurati che l'Attività di Avvio applicazioni imposti android:resizeableActivity="true" e non utilizzi una modalità di avvio che impedisce più istanze. Ad esempio, è possibile creare un'istanza di un'attività singleInstancePerTask più volte in attività diverse quando è impostata FLAG_ACTIVITY_MULTIPLE_TASK o FLAG_ACTIVITY_NEW_DOCUMENT.

Non confondere l'istanza multi-istanza con un layout a più riquadri, ad esempio una presentazione elenco-dettaglio che utilizza SlidingPaneLayout, che viene eseguita all'interno di una singola finestra.

Tieni presente che quando più istanze sono in esecuzione in finestre separate su un dispositivo pieghevole, una o più istanze potrebbero essere inviate in background se la postura cambia. Ad esempio, supponiamo che un dispositivo sia aperto e abbia due istanze di app in esecuzione in due finestre ai lati della piegatura. Se il dispositivo è piegato, una delle istanze potrebbe essere terminata anziché tentare di adattare le finestre di entrambe le istanze su uno schermo più piccolo.

Verifica della modalità multi-finestra

Indipendentemente dal fatto che l'app abbia come target il livello API 24 o versioni successive, devi verificare come funziona in modalità multi-finestra nel caso in cui un utente provi ad avviarla in modalità multi-finestra su un dispositivo con Android 7.0 o versioni successive.

Dispositivi di test

I dispositivi con Android 7.0 (livello API 24) o versioni successive supportano la modalità multi-finestra.

Livello API 23 o inferiore

Quando gli utenti tentano di utilizzare l'app in modalità multi-finestra, il sistema ridimensiona forzatamente l'app a meno che l'app non dichiari un orientamento fisso.

Se la tua app non dichiara un orientamento fisso, devi avviarla su un dispositivo con Android 7.0 o versioni successive e tentare di attivare la modalità schermo diviso dell'app. Verifica che l'esperienza utente sia accettabile quando l'app viene ridimensionata forzatamente.

Se l'app dichiara un orientamento fisso, devi provare ad attivare la modalità multi-finestra. In questo caso, verifica che l'app rimanga in modalità a schermo intero.

Livelli API da 24 a 30

Se la tua app ha come target i livelli API da 24 a 30 e non disabilita il supporto multi-finestra, verifica il seguente comportamento nelle modalità schermo diviso e in formato libero:

  • Avvia l'app a schermo intero, quindi passa alla modalità multi-finestra premendo a lungo il pulsante Recenti. Verifica che il cambio di app venga eseguito correttamente.

  • Avvia l'app direttamente in modalità multi-finestra e verifica che venga avviata correttamente. Puoi avviare un'app in modalità multi-finestra premendo il pulsante Recenti, quindi tenendo premuto a lungo la barra del titolo dell'app e trascinandola in una delle aree evidenziate sullo schermo.

  • Ridimensiona la tua app in modalità schermo diviso trascinando il divisore per lo schermo. Verifica che l'app venga ridimensionata senza arresti anomali e che gli elementi UI necessari siano visibili.

  • Se hai specificato dimensioni minime per l'app, prova a ridimensionarla in modo che le dimensioni della finestra siano inferiori a quelle specificate. Verifica di non poter ridimensionare l'app in modo che sia inferiore alle dimensioni minime specificate.

  • Verifica che le prestazioni della tua app siano accettabili tramite tutti i test. Ad esempio, verifica che non vi sia un ritardo troppo lungo per l'aggiornamento della UI dopo il ridimensionamento dell'app.

Livello API 31 o superiore

Se la tua app ha come target il livello API 31 o superiore e la larghezza minima e l'altezza minima dell'attività principale sono inferiori o uguali alle rispettive dimensioni dell'area di visualizzazione disponibile, verifica tutti i comportamenti elencati per i livelli API da 24 a 30.

Elenco di controllo per il test

Per verificare le prestazioni dell'app in modalità multi-finestra, prova le seguenti operazioni. Devi provare queste operazioni sia in modalità schermo diviso che in formato libero, se non diversamente indicato.

  • Attiva ed esci dalla modalità multi-finestra.

  • Passa da un'app a un'altra e verifica che l'app funzioni correttamente mentre è visibile, ma non attiva. Ad esempio, se nell'app è in corso la riproduzione di video, verifica che la riproduzione del video continui mentre l'utente interagisce con un'altra app.

  • In modalità schermo diviso, prova a spostare il divisore per lo schermo per ingrandire e rimpicciolire l'app. Prova queste operazioni entrambe una accanto all'altra e una sopra le altre configurazioni. Verifica che l'app non abbia arresti anomali, che la funzionalità essenziale sia visibile e che l'operazione di ridimensionamento non richieda troppo tempo.

  • Esegui diverse operazioni di ridimensionamento in rapida successione. Verifica che l'app non si arresti in modo anomalo o non perda memoria. Memory Profiler di Android Studio fornisce informazioni sull'utilizzo della memoria da parte della tua app (vedi Esaminare l'utilizzo della memoria dell'app con Memory Profiler).

  • Utilizza normalmente l'app in diverse configurazioni di finestre e verifica che funzioni correttamente. Verifica che il testo sia leggibile e che gli elementi UI non siano troppo piccoli per interagire.

Supporto multi-finestra disattivato

Nei livelli API da 24 a 30, se hai disattivato il supporto multi-finestra impostando android:resizeableActivity="false", devi avviare l'app su un dispositivo con versioni Android dalla 7.0 alla 11 e provare a impostare l'app in modalità schermo diviso e formato libero. Verifica che, in questo caso, l'app rimanga in modalità a schermo intero.

Risorse aggiuntive

Per ulteriori informazioni sul supporto della modalità multi-finestra in Android, vedi:

##

Consigliate per te

* Nota: il testo del link viene visualizzato quando JavaScript è disattivato * Modalità di compatibilità del dispositivo * Supporto ridimensionabilità di schermi di grandi dimensioni * Gestisci le modifiche alla configurazione