L'incorporamento delle attività ottimizza le app sui dispositivi con schermi di grandi dimensioni suddividendo la finestra delle attività di un'applicazione tra due attività o due istanze della stessa attività.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/settings_app.png?authuser=7&hl=it)
Se la tua app consiste in più attività, l'incorporamento delle attività ti consente di offrire un'esperienza utente migliorata su tablet, pieghevoli e dispositivi ChromeOS.
L'incorporamento delle attività non richiede il refactoring del codice. Puoi stabilire il modo in cui l'app visualizza le sue attività, una accanto all'altra o in pila, creando un file di configurazione XML o effettuando chiamate API Jetpack WindowManager.
Il supporto per schermi di piccole dimensioni viene mantenuto automaticamente. Quando la tua app è su un dispositivo con uno schermo piccolo, le attività vengono sovrapposte. Sugli schermi grandi, le attività vengono visualizzate una accanto all'altra. Il sistema determina la presentazione in base alla configurazione che hai creato, senza bisogno di logica di diramazione.
L'incorporamento delle attività supporta i cambiamenti di orientamento del dispositivo e funziona perfettamente sui dispositivi pieghevoli, impilando e rimuovendo le attività quando il dispositivo si piega e si apre.
L'incorporamento delle attività è supportato sulla maggior parte dei dispositivi con schermi di grandi dimensioni con Android 12L (livello API 32) e versioni successive.
Finestra attività divisa
L'incorporamento delle attività suddivide la finestra delle attività dell'app in due container: principale e secondario. I container contengono attività avviate dall'attività principale o da altre attività già presenti.
Le attività vengono raggruppate nel container secondario all'avvio e il container secondario è impilato sopra il container principale su schermi di piccole dimensioni, in modo che l'impilamento delle attività e la navigazione a ritroso siano coerenti con l'ordine delle attività già integrate nell'app.
L'incorporamento delle attività ti consente di visualizzare le attività in diversi modi. La tua app può suddividere la finestra delle attività avviando contemporaneamente due attività affiancate:
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/a_b.png?authuser=7&hl=it)
Oppure, un'attività che occupa l'intera finestra dell'attività può creare una suddivisione avviando una nuova attività accanto a:
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/a_to_a_b.png?authuser=7&hl=it)
Le attività già incluse in una suddivisione e che condividono la finestra di un'attività possono avviare altre attività nei seguenti modi:
A lato sopra un'altra attività:
Figura 4. L'attività A inizia l'attività C a lato sopra l'attività B. Di lato e sposta la divisione lateralmente, nascondendo l'attività principale precedente:
Figura 5. L'attività B inizia l'attività C di lato e sposta la divisione lateralmente. Avvia un'attività in posizione superiore, ovvero nello stesso stack di attività:
Figura 6. L'attività B avvia l'attività C senza ulteriori flag di intent. Per avviare un'attività a finestra intera nella stessa attività:
Figura 7. L'attività A o l'attività B avvia l'attività C che occupa la finestra dell'attività.
Navigazione a ritroso
Diversi tipi di applicazioni possono avere diverse regole di navigazione a ritroso in uno stato di finestra di attività divisa a seconda delle dipendenze tra le attività o del modo in cui gli utenti attivano l'evento Indietro, ad esempio:
- Integrazione: se le attività sono correlate e non deve essere visualizzata una senza l'altra, la navigazione a ritroso può essere configurata per completare entrambe.
- Proseguimento da solo: se le attività sono completamente indipendenti, la navigazione a ritroso di un'attività non influisce sullo stato di un'altra attività nella finestra dell'attività.
L'evento Indietro viene inviato all'ultima attività attiva quando utilizzi la navigazione con pulsanti. Con la navigazione basata sui gesti, l'evento Indietro viene inviato all'attività in cui si è verificato il gesto.
Layout a più riquadri
Jetpack WindowManager ti consente di creare un'attività di incorporamento di riquadri a più riquadri su dispositivi con schermi di grandi dimensioni con Android 12L (livello API 32) o versioni successive e su alcuni dispositivi con versioni della piattaforma precedenti. Le app esistenti basate su più attività anziché su frammenti o layout basati sulla visualizzazione, come SlidingPaneLayout
, possono offrire una migliore esperienza utente su schermi di grandi dimensioni senza dover ricorrere al refactoring del codice sorgente.
Un esempio comune è la suddivisione elenco-dettagli. Per garantire una presentazione di alta qualità, il sistema avvia l'attività relativa all'elenco e quindi l'applicazione avvia immediatamente l'attività relativa ai dettagli. Il sistema di transizione attende che entrambe le attività vengano tracciate, quindi le visualizza insieme. Per l'utente, le due attività vengono avviate come una sola.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/launcher_to_list-detail.png?authuser=7&hl=it)
Suddividi attributi
Puoi specificare la proporzione della finestra delle attività tra i container suddivisi e la disposizione dei container rispetto agli altri.
Per le regole definite in un file di configurazione XML, imposta i seguenti attributi:
splitRatio
: imposta le proporzioni del contenitore. Il valore è un numero in virgola mobile nell'intervallo aperto (0,0, 1,0).splitLayoutDirection
: specifica il layout dei container suddivisi tra loro. I valori includono:ltr
: da sinistra a destrartl
: da destra a sinistralocale
:ltr
ortl
viene determinato dalle impostazioni internazionali
Consulta la sezione Configurazione XML di seguito per alcuni esempi.
Per le regole create utilizzando le API WindowManager, crea un oggetto SplitAttributes
con SplitAttributes.Builder
e richiama i seguenti metodi del builder:
setSplitType()
: imposta le proporzioni dei contenitori suddivisi. VediSplitAttributes.SplitType
per gli argomenti validi, tra cui il metodoSplitAttributes.SplitType.ratio()
.setLayoutDirection()
: imposta il layout dei container. Consulta la sezioneSplitAttributes.LayoutDirection
per i valori possibili.
Per alcuni esempi, consulta l'API WindowManager di seguito.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/a_b_vs_a_b.png?authuser=7&hl=it)
Segnaposto
Le attività segnaposto sono attività secondarie vuote che occupano un'area di una suddivisione attività. Sono destinati a essere sostituiti da un'altra attività che include contenuti. Ad esempio, un'attività segnaposto potrebbe occupare il lato secondario di una suddivisione attività in un layout elenco dettagliato fino a quando non viene selezionato un elemento dell'elenco e a quel punto un'attività contenente le informazioni dettagliate per l'elemento dell'elenco selezionato sostituisce il segnaposto.
Per impostazione predefinita, il sistema visualizza i segnaposto solo quando c'è abbastanza spazio per una suddivisione attività. I segnaposto terminano automaticamente quando le dimensioni di visualizzazione vengono impostate su una larghezza o un'altezza troppo ridotta per visualizzare una suddivisione. Quando lo spazio lo consente, il sistema riavvia il segnaposto con uno stato reinizializzato.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/placeholder_finished_recreated.png?authuser=7&hl=it)
Tuttavia, l'attributo stickyPlaceholder
di un metodo SplitPlaceholderRule
o setSticky()
di SplitPlaceholder.Builder
può sostituire il comportamento predefinito. Quando l'attributo o il metodo specifica un valore true
, il sistema visualizza il segnaposto come attività di livello più alto nella finestra dell'attività quando la visualizzazione viene ridimensionata a un riquadro singolo da una visualizzazione a due riquadri (vedi Configurazione divisa per un esempio).
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/placeholder_sticky.png?authuser=7&hl=it)
Modifiche alle dimensioni delle finestre
Quando le modifiche alla configurazione del dispositivo riducono la larghezza della finestra delle attività in modo che non sia sufficientemente grande per un layout a più riquadri (ad esempio, quando un dispositivo pieghevole con schermo grande passa dalle dimensioni del tablet alle dimensioni del telefono o la finestra dell'app viene ridimensionata in modalità multi-finestra), le attività non segnaposto nel riquadro secondario della finestra delle attività vengono raggruppate sopra le attività nel riquadro principale.
Le attività segnaposto vengono mostrate solo quando la larghezza di visualizzazione è sufficiente per una suddivisione. Su schermi più piccoli, il segnaposto viene ignorato automaticamente. Quando l'area di visualizzazione diventa di nuovo abbastanza grande, il segnaposto viene ricreato. (vedi la sezione Segnaposto sopra).
La sovrapposizione delle attività è possibile perché WindowManager ordina le attività nel riquadro secondario sopra le attività nel riquadro principale.
Più attività nel riquadro secondario
L'attività B avvia l'attività C in loco senza ulteriori flag di intent:
generando il seguente ordine z di attività nella stessa attività:
Quindi, in una finestra delle attività più piccola, l'applicazione si riduce a una singola attività con C in cima allo stack:
Se torni indietro nella finestra più piccola, puoi spostarti tra le attività impilate una sull'altra.
Se la configurazione della finestra delle attività viene ripristinata a una dimensione maggiore che può ospitare più riquadri, le attività vengono visualizzate di nuovo una accanto all'altra.
Suddivisione in pila
L'attività B inizia l'attività C di lato e sposta la divisione lateralmente:
Il risultato è il seguente ordine z di attività nella stessa attività:
In una finestra dell'attività più piccola, l'applicazione si riduce a una singola attività con C in alto:
Orientamento verticale fisso
L'impostazione del manifest android:screenOrientation consente alle app di vincolare le attività all'orientamento verticale oppure orizzontale. Per migliorare l'esperienza utente sui dispositivi con schermi di grandi dimensioni come tablet e pieghevoli, i produttori di dispositivi (OEM) possono ignorare le richieste di orientamento dello schermo e l'orientamento dell'app in formato verticale per i display orizzontali o in orizzontale su display verticali.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/a_letterboxed_portrait_and_landscape.png?authuser=7&hl=it)
Analogamente, quando l'incorporamento delle attività è abilitato, gli OEM possono personalizzare i dispositivi per attività di formato Letterbox e verticale con orientamento orizzontale su schermi di grandi dimensioni (larghezza ≥ 600 dp). Quando un'attività a verticale fisso avvia una seconda attività, il dispositivo può visualizzare le due attività una accanto all'altra in un display a due riquadri.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/a_letterboxed_portrait_to_a_b.png?authuser=7&hl=it)
Aggiungi sempre la proprietà android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED
al file manifest dell'app per comunicare ai dispositivi che l'app supporta l'incorporamento dell'attività (consulta la sezione Configurazione di suddivisione di seguito). I dispositivi personalizzati OEM possono quindi stabilire se attivare o meno le attività letterbox fisso e verticale.
Configurazione di suddivisione
Le regole di suddivisione configurano le suddivisioni delle attività. Puoi definire le regole di suddivisione in un file di configurazione XML o effettuando chiamate API WindowManager di Jetpack.
In entrambi i casi, l'app deve accedere alla libreria WindowManager e deve informare il sistema che l'app ha implementato l'incorporamento dell'attività.
Procedi nel seguente modo:
Aggiungi la dipendenza più recente della libreria WindowManager al file
build.gradle
a livello di modulo della tua app, ad esempio:implementation 'androidx.window:window:1.1.0-beta02'
La libreria WindowManager fornisce tutti i componenti necessari per l'incorporamento dell'attività.
Comunica al sistema che la tua app ha implementato l'incorporamento dell'attività.
Aggiungi la proprietà
android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED
all'elemento <application> del file manifest dell'app e imposta il valore su true, ad esempio:<manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application> <property android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED" android:value="true" /> </application> </manifest>
Nella release WindowManager 1.1.0-alpha06 e successive, le suddivisioni di incorporamento dell'attività sono disabilitate a meno che la proprietà non venga aggiunta al manifest e impostata su true.
Inoltre, i produttori di dispositivi utilizzano l'impostazione per abilitare funzionalità personalizzate per le app che supportano l'incorporamento dell'attività. Ad esempio, i dispositivi possono applicare un'attività in modalità solo verticale su display orizzontali per orientare l'attività per la transizione a un layout a due riquadri all'inizio di una seconda attività (vedi Orientamento verticale fisso).
Configurazione XML
Per creare un'implementazione basata su XML dell'incorporamento delle attività, completa i seguenti passaggi:
Crea un file di risorse XML con le seguenti operazioni:
- Definisce le attività che condividono una suddivisione
- Configura le opzioni di suddivisione
- Crea un segnaposto per il contenitore secondario della suddivisione quando i contenuti non sono disponibili
- Specifica le attività che non devono mai far parte di una suddivisione
Ecco alcuni esempi:
<!-- main_split_config.xml --> <resources xmlns:window="http://schemas.android.com/apk/res-auto"> <!-- Define a split for the named activities. --> <SplitPairRule window:splitRatio="0.33" window:splitLayoutDirection="locale" window:splitMinWidthDp="840" window:splitMaxAspectRatioInPortrait="alwaysAllow" window:finishPrimaryWithSecondary="never" window:finishSecondaryWithPrimary="always" window:clearTop="false"> <SplitPairFilter window:primaryActivityName=".ListActivity" window:secondaryActivityName=".DetailActivity"/> </SplitPairRule> <!-- Specify a placeholder for the secondary container when content is not available. --> <SplitPlaceholderRule window:placeholderActivityName=".PlaceholderActivity" window:splitRatio="0.33" window:splitLayoutDirection="locale" window:splitMinWidthDp="840" window:splitMaxAspectRatioInPortrait="alwaysAllow" window:stickyPlaceholder="false"> <ActivityFilter window:activityName=".ListActivity"/> </SplitPlaceholderRule> <!-- Define activities that should never be part of a split. Note: Takes precedence over other split rules for the activity named in the rule. --> <ActivityRule window:alwaysExpand="true"> <ActivityFilter window:activityName=".ExpandedActivity"/> </ActivityRule> </resources>
Crea un inizializzatore.
Il componente WindowManager
RuleController
analizza il file di configurazione XML e rende le regole disponibili al sistema. Una libreria Jetpack StartupInitializer
rende disponibile il file XML aRuleController
all'avvio dell'app, in modo che le regole vengano applicate all'avvio di un'attività.Per creare un inizializzatore, segui questi passaggi:
Aggiungi la dipendenza più recente della libreria Jetpack Startup al file
build.gradle
a livello di modulo, ad esempio:implementation 'androidx.startup:startup-runtime:1.1.1'
Crea una classe che implementa l'interfaccia
Initializer
.L'inizializzatore rende le regole di suddivisione disponibili per
RuleController
passando l'ID del file di configurazione XML (main_split_config.xml
) al metodoRuleController.parseRules()
.Kotlin
class SplitInitializer : Initializer<RuleController> { override fun create(context: Context): RuleController { return RuleController.getInstance(context).apply { setRules(RuleController.parseRules(context, R.xml.main_split_config)) } } override fun dependencies(): List<Class<out Initializer<*>>> { return emptyList() } }
Java
public class SplitInitializer implements Initializer<RuleController> { @NonNull @Override public RuleController create(@NonNull Context context) { RuleController ruleController = RuleController.getInstance(context); ruleController.setRules( RuleController.parseRules(context, R.xml.main_split_config) ); return ruleController; } @NonNull @Override public List<Class<? extends Initializer<?>>> dependencies() { return Collections.emptyList(); } }
Crea un fornitore di contenuti per le definizioni delle regole.
Aggiungi
androidx.startup.InitializationProvider
al file manifest dell'app come<provider>
. Includi un riferimento all'implementazione dell'inizializzatoreRuleController
,SplitInitializer
:<!-- AndroidManifest.xml --> <provider android:name="androidx.startup.InitializationProvider" android:authorities="${applicationId}.androidx-startup" android:exported="false" tools:node="merge"> <!-- Make SplitInitializer discoverable by InitializationProvider. --> <meta-data android:name="${applicationId}.SplitInitializer" android:value="androidx.startup" /> </provider>
InitializationProvider
rileva e inizializzaSplitInitializer
prima che venga chiamato il metodoonCreate()
dell'app. Di conseguenza, le regole di suddivisione diventano effettive all'inizio dell'attività principale dell'app.
API WindowManager
Puoi implementare l'incorporamento dell'attività in modo programmatico con una manciata di chiamate API. Effettua le chiamate nel metodo onCreate()
di una sottoclasse di Application
per assicurarti che le regole siano effettive prima di avviare qualsiasi attività.
Per creare in modo programmatico una suddivisione attività:
Crea una regola di suddivisione:
Crea un elemento
SplitPairFilter
che identifichi le attività che condividono la suddivisione:Kotlin
val splitPairFilter = SplitPairFilter( ComponentName(this, ListActivity::class.java), ComponentName(this, DetailActivity::class.java), null )
Java
SplitPairFilter splitPairFilter = new SplitPairFilter( new ComponentName(this, ListActivity.class), new ComponentName(this, DetailActivity.class), null );
Per aggiungere il filtro a un insieme di filtri, procedi nel seguente modo:
Kotlin
val filterSet = setOf(splitPairFilter)
Java
Set<SplitPairFilter> filterSet = new HashSet<>(); filterSet.add(splitPairFilter);
Crea attributi di layout per la suddivisione:
Kotlin
val splitAttributes: SplitAttributes = SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build()
Java
final SplitAttributes splitAttributes = new SplitAttributes.Builder() .setSplitType(SplitAttributes.SplitType.ratio(0.33f)) .setLayoutDirection(SplitAttributes.LayoutDirection.LEFT_TO_RIGHT) .build();
SplitAttributes.Builder
crea un oggetto contenente gli attributi di layout:setSplitType
: definisce la modalità di allocazione dell'area di visualizzazione disponibile a ciascun contenitore attività. Il tipo di suddivisione rapporto specifica la proporzione dell'area di visualizzazione disponibile assegnata al contenitore principale. Il contenitore secondario occupa la parte restante dell'area di visualizzazione disponibile.setLayoutDirection
: specifica in che modo sono disposti i contenitori delle attività l'uno rispetto all'altro, il contenitore principale.
Crea una
SplitPairRule
:Kotlin
val splitPairRule = SplitPairRule.Builder(filterSet) .setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER) .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS) .setClearTop(false) .build()
Java
SplitPairRule splitPairRule = new SplitPairRule.Builder(filterSet) .setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithSecondary(SplitRule.FinishBehavior.NEVER) .setFinishSecondaryWithPrimary(SplitRule.FinishBehavior.ALWAYS) .setClearTop(false) .build();
SplitPairRule.Builder
crea e configura la regola:filterSet
: contiene filtri per le coppie di suddivisione che determinano quando applicare la regola identificando le attività che condividono una suddivisione.setDefaultSplitAttributes
: applica gli attributi di layout alla regola.setMinWidthDp
: imposta la larghezza di visualizzazione minima (in pixel indipendenti dalla densità, dp) che consente una suddivisione.setMinSmallestWidthDp
: imposta il valore minimo (in dp) che deve avere la dimensione di visualizzazione minore tra le due per consentire una suddivisione indipendentemente dall'orientamento del dispositivo.setMaxAspectRatioInPortrait
: consente di impostare le proporzioni massime del display (altezza:larghezza) con orientamento verticale per le quali vengono visualizzate le suddivisioni delle attività. Se le proporzioni di un display verticale superano quelle massime, le suddivisioni vengono disattivate indipendentemente dalla larghezza del display. Nota:il valore predefinito è 1,4 e, sulla maggior parte dei tablet, le attività occupano l'intera finestra dell'attività con orientamento verticale. Vedi ancheSPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
esetMaxAspectRatioInLandscape
. Il valore predefinito per l'orientamento orizzontale èALWAYS_ALLOW
.setFinishPrimaryWithSecondary
: imposta in che modo la fine di tutte le attività nel contenitore secondario influisce sulle attività nel contenitore principale.NEVER
indica che il sistema non deve completare le attività principali quando tutte le attività nel contenitore secondario terminano (vedi Completare le attività).setFinishSecondaryWithPrimary
: imposta in che modo il completamento di tutte le attività nel contenitore principale influisce sulle attività nel contenitore secondario.ALWAYS
indica che il sistema deve sempre terminare le attività nel contenitore secondario al termine di tutte le attività nel contenitore principale (vedi Completare le attività).setClearTop
: specifica se tutte le attività nel contenitore secondario vengono terminate quando viene avviata una nuova attività nel contenitore. False indica che le nuove attività vengono sovrapposte alle attività già presenti nel contenitore secondario.
Ottieni l'istanza singleton di WindowManager
RuleController
e aggiungi la regola:Kotlin
val ruleController = RuleController.getInstance(this) ruleController.addRule(splitPairRule)
Java
RuleController ruleController = RuleController.getInstance(this); ruleController.addRule(splitPairRule);
Crea un segnaposto per il contenitore secondario quando i contenuti non sono disponibili:
Crea un elemento
ActivityFilter
che identifichi l'attività con cui il segnaposto condivide la suddivisione della finestra di un'attività:Kotlin
val placeholderActivityFilter = ActivityFilter( ComponentName(this, ListActivity::class.java), null )
Java
ActivityFilter placeholderActivityFilter = new ActivityFilter( new ComponentName(this, ListActivity.class), null );
Per aggiungere il filtro a un insieme di filtri, procedi nel seguente modo:
Kotlin
val placeholderActivityFilterSet = setOf(placeholderActivityFilter)
Java
Set<ActivityFilter> placeholderActivityFilterSet = new HashSet<>(); placeholderActivityFilterSet.add(placeholderActivityFilter);
Crea una
SplitPlaceholderRule
:Kotlin
val splitPlaceholderRule = SplitPlaceholderRule.Builder( placeholderActivityFilterSet, Intent(context, PlaceholderActivity::class.java) ).setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS) .setSticky(false) .build()
Java
SplitPlaceholderRule splitPlaceholderRule = new SplitPlaceholderRule.Builder( placeholderActivityFilterSet, new Intent(context, PlaceholderActivity.class) ).setDefaultSplitAttributes(splitAttributes) .setMinWidthDp(840) .setMinSmallestWidthDp(600) .setMaxAspectRatioInPortrait(EmbeddingAspectRatio.ratio(1.5f)) .setFinishPrimaryWithPlaceholder(SplitRule.FinishBehavior.ALWAYS) .setSticky(false) .build();
SplitPlaceholderRule.Builder
crea e configura la regola:placeholderActivityFilterSet
: contiene filtri di attività che determinano quando applicare la regola identificando le attività a cui è associata l'attività segnaposto.Intent
: specifica l'avvio dell'attività segnaposto.setDefaultSplitAttributes
: applica gli attributi di layout alla regola.setMinWidthDp
: imposta la larghezza di visualizzazione minima (in pixel indipendenti dalla densità, dp) che consente una suddivisione.setMinSmallestWidthDp
: imposta il valore minimo (in dp) che la dimensione di visualizzazione più piccola deve avere per consentire una suddivisione indipendentemente dall'orientamento del dispositivo.setMaxAspectRatioInPortrait
: consente di impostare le proporzioni massime del display (altezza:larghezza) con orientamento verticale per le quali vengono visualizzate le suddivisioni delle attività. Nota:il valore predefinito è 1, 4 e determina che le attività compilano la finestra delle attività con orientamento verticale sulla maggior parte dei tablet. Vedi ancheSPLIT_MAX_ASPECT_RATIO_PORTRAIT_DEFAULT
esetMaxAspectRatioInLandscape
. Il valore predefinito per l'orientamento orizzontale èALWAYS_ALLOW
.setFinishPrimaryWithPlaceholder
: imposta in che modo la fine dell'attività segnaposto influisce sulle attività nel contenitore principale. ALWAYS indica che il sistema deve sempre terminare le attività nel contenitore principale al termine del segnaposto (vedi Termina attività).setSticky
: determina se l'attività segnaposto viene visualizzata in cima alla serie di attività su display piccoli dopo che il segnaposto è apparso per la prima volta in una suddivisione con una larghezza minima sufficiente.
Aggiungi la regola a WindowManager
RuleController
:Kotlin
ruleController.addRule(splitPlaceholderRule)
Java
ruleController.addRule(splitPlaceholderRule);
Specifica le attività che non devono mai far parte di una suddivisione:
Crea un
ActivityFilter
che identifichi un'attività che deve sempre occupare l'intera area di visualizzazione dell'attività:Kotlin
val expandedActivityFilter = ActivityFilter( ComponentName(this, ExpandedActivity::class.java), null )
Java
ActivityFilter expandedActivityFilter = new ActivityFilter( new ComponentName(this, ExpandedActivity.class), null );
Per aggiungere il filtro a un insieme di filtri, procedi nel seguente modo:
Kotlin
val expandedActivityFilterSet = setOf(expandedActivityFilter)
Java
Set<ActivityFilter> expandedActivityFilterSet = new HashSet<>(); expandedActivityFilterSet.add(expandedActivityFilter);
Crea una
ActivityRule
:Kotlin
val activityRule = ActivityRule.Builder(expandedActivityFilterSet) .setAlwaysExpand(true) .build()
Java
ActivityRule activityRule = new ActivityRule.Builder( expandedActivityFilterSet ).setAlwaysExpand(true) .build();
ActivityRule.Builder
crea e configura la regola:expandedActivityFilterSet
: contiene filtri di attività che determinano quando applicare la regola identificando le attività da escludere dalle suddivisioni.setAlwaysExpand
: specifica se l'attività deve riempire l'intera finestra dell'attività.
Aggiungi la regola a WindowManager
RuleController
:Kotlin
ruleController.addRule(activityRule)
Java
ruleController.addRule(activityRule);
Incorporamento tra applicazioni
Su Android 13 (livello API 33) e versioni successive, le app possono incorporare attività di altre app. L'incorporamento delle attività tra applicazioni o UID consente l'integrazione visiva delle attività di più applicazioni Android. Il sistema mostra sullo schermo un'attività dell'app host e un'attività incorporata di un'altra app sullo schermo affiancata o in alto e in basso, proprio come nell'incorporamento di attività in una singola app.
Ad esempio, l'app Impostazioni potrebbe incorporare l'attività di selezione dello sfondo dall'app BackgroundPicker:
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/wallpaper_activity_embedded_in_settings_app.png?authuser=7&hl=it)
Modello di attendibilità
I processi di hosting che incorporano attività di altre app sono in grado di ridefinire la presentazione delle attività incorporate, inclusi dimensioni, posizione, ritaglio e trasparenza. Gli host dannosi possono utilizzare questa funzionalità per ingannare gli utenti e creare attacchi di clickjacking o altri rimedi all'interfaccia utente.
Per evitare l'uso improprio dell'incorporamento di attività tra app, Android richiede alle app di attivare l'opzione per consentire l'incorporamento delle loro attività. Le app possono designare gli host come attendibili o non attendibili.
Host attendibili
Per consentire ad altre applicazioni di incorporare e controllare completamente la presentazione delle attività della tua app, specifica il certificato SHA-256 dell'applicazione host nell'attributo android:knownActivityEmbeddingCerts
degli elementi <activity>
o <application>
del file manifest dell'app.
Imposta il valore di android:knownActivityEmbeddingCerts
come stringa:
<activity
android:name=".MyEmbeddableActivity"
android:knownActivityEmbeddingCerts="@string/known_host_certificate_digest"
... />
oppure, per specificare più certificati, un array di stringhe:
<activity
android:name=".MyEmbeddableActivity"
android:knownActivityEmbeddingCerts="@array/known_host_certificate_digests"
... />
che fa riferimento a una risorsa come la seguente:
<resources>
<string-array name="known_host_certificate_digests">
<item>cert1</item>
<item>cert2</item>
...
</string-array>
</resources>
I proprietari di app possono ottenere un digest del certificato SHA eseguendo l'attività signingReport
di Gradle. Il digest del certificato è l'impronta SHA-256 senza i due punti di separazione. Per ulteriori informazioni, consulta le sezioni Eseguire un report sulla firma e Autenticazione del client.
Host non attendibili
Per consentire a un'app di incorporare le sue attività e controllarne la presentazione, specifica l'attributo android:allowUntrustedActivityEmbedding
negli elementi <activity>
o <application>
del file manifest dell'app, ad esempio:
<activity
android:name=".MyEmbeddableActivity"
android:allowUntrustedActivityEmbedding="true"
... />
Il valore predefinito dell'attributo è false e impedisce l'incorporamento dell'attività tra app.
Autenticazione personalizzata
Per ridurre i rischi dell'incorporamento delle attività non attendibili, crea un meccanismo di autenticazione personalizzato che verifichi l'identità dell'host. Se conosci i certificati host, utilizza la libreria androidx.security.app.authenticator
per l'autenticazione. Se l'host esegue l'autenticazione dopo aver incorporato la tua attività, puoi visualizzare i contenuti effettivi. In caso contrario, puoi informare l'utente che l'azione non è stata consentita e bloccare i contenuti.
Utilizza il metodo ActivityEmbeddingController#isActivityEmbedded()
della libreria Jetpack WindowManager per verificare se un host sta incorporando la tua attività, ad esempio:
Kotlin
fun isActivityEmbedded(activity: Activity): Boolean { return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity) }
Java
boolean isActivityEmbedded(Activity activity) { return ActivityEmbeddingController.getInstance(this).isActivityEmbedded(activity); }
Limitazione delle dimensioni minime
Il sistema Android applica l'altezza e la larghezza minime specificate nell'elemento <layout>
del file manifest dell'app alle attività incorporate. Se un'applicazione non specifica l'altezza e la larghezza minime, si applicano i valori predefiniti di sistema (sw220dp
).
Se l'host tenta di ridimensionare il container incorporato a una dimensione inferiore al minimo, il container incorporato si espande in modo da occupare l'intero limite delle attività.
<alias-attività>
Affinché l'incorporamento delle attività attendibili o non attendibili funzioni con l'elemento <activity-alias>
, è necessario applicare android:knownActivityEmbeddingCerts
o android:allowUntrustedActivityEmbedding
all'attività di destinazione anziché all'alias. Il criterio che verifica la sicurezza sul server di sistema si basa sui flag impostati nella destinazione, non sull'alias.
Applicazione host
Le applicazioni host implementano l'incorporamento delle attività tra app nello stesso modo in cui implementano l'incorporamento delle attività singole app. Gli oggetti SplitPairRule
e SplitPairFilter
o ActivityRule
e ActivityFilter
specificano le attività incorporate e le suddivisioni delle finestre delle attività. Le regole di suddivisione vengono definite staticamente in XML o in fase di runtime tramite le chiamate API Jetpack WindowManager.
Se un'applicazione host tenta di incorporare un'attività per la quale non è stata attivata l'incorporamento cross-app, l'attività occupa tutti i limiti delle attività. Di conseguenza, le applicazioni host devono sapere se le attività di destinazione consentono l'incorporamento tra app.
Se un'attività incorporata avvia una nuova attività nella stessa attività e per la nuova attività non è stata attivata l'incorporamento cross-app, l'attività occupa tutti i limiti dell'attività anziché sovrapporsi all'attività nel contenitore incorporato.
Un'applicazione host può incorporare le proprie attività senza restrizioni, purché queste vengano avviate nella stessa attività.
Esempi di suddivisione
Dividi dalla finestra intera
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/a_to_a_b.png?authuser=7&hl=it)
Non è richiesto alcun refactoring. Puoi definire la configurazione per la suddivisione
in modo statico o in fase di runtime, quindi chiamare
Context#startActivity()
senza parametri aggiuntivi.
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Dividi per impostazione predefinita
Quando la pagina di destinazione di un'applicazione è progettata per essere suddivisa in due contenitori su schermi di grandi dimensioni, l'esperienza utente è migliore quando entrambe le attività vengono create e presentate contemporaneamente. Tuttavia, i contenuti potrebbero non essere disponibili per il contenitore secondario della suddivisione finché l'utente non interagisce con l'attività nel contenitore principale (ad esempio, l'utente seleziona un elemento da un menu di navigazione). Un'attività segnaposto può riempire il vuoto finché i contenuti non possono essere visualizzati nel container secondario della suddivisione (vedi segnaposto sopra).
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/launcher_main_placeholder.png?authuser=7&hl=it)
Per creare una suddivisione con un segnaposto, crea un segnaposto e associalo all'attività principale:
<SplitPlaceholderRule
window:placeholderActivityName=".PlaceholderActivity">
<ActivityFilter
window:activityName=".MainActivity"/>
</SplitPlaceholderRule>
Suddivisione tramite link diretto
Quando un'app riceve un intent, l'attività target può essere mostrata come parte secondaria di una suddivisione dell'attività, ad esempio una richiesta di mostrare una schermata dei dettagli con informazioni su un elemento di un elenco. Sui display piccoli, il dettaglio viene mostrato nell'intera finestra delle attività; sui dispositivi più grandi, accanto all'elenco.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/deep_link_split.png?authuser=7&hl=it)
La richiesta di lancio deve essere indirizzata all'attività principale e l'attività di dettaglio target deve essere lanciata in una suddivisione. Il sistema sceglie automaticamente la presentazione corretta (in pila o affiancata) in base alla larghezza di visualizzazione disponibile.
Kotlin
override fun onCreate(savedInstanceState Bundle?) { . . . RuleController.getInstance(this) .addRule(SplitPairRule.Builder(filterSet).build()) startActivity(Intent(this, DetailActivity::class.java)) }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { . . . RuleController.getInstance(this) .addRule(new SplitPairRule.Builder(filterSet).build()); startActivity(new Intent(this, DetailActivity.class)); }
La destinazione del link diretto potrebbe essere l'unica attività che dovrebbe essere disponibile per l'utente nello stack di navigazione a ritroso; potresti voler evitare di ignorare l'attività dei dettagli e lasciare solo l'attività principale:
Puoi invece completare entrambe le attività contemporaneamente utilizzando l'attributo
finishPrimaryWithSecondary
:
<SplitPairRule
window:finishPrimaryWithSecondary="always">
<SplitPairFilter
window:primaryActivityName=".ListActivity"
window:secondaryActivityName=".DetailActivity"/>
</SplitPairRule>
Consulta la sezione Attributi di configurazione di seguito.
Più attività in contenitori divisi
Sovrapporre più attività in un container suddiviso consente agli utenti di accedere a contenuti profondi. Ad esempio, con una suddivisione elenco-dettagli, l'utente potrebbe dover accedere a una sezione di sottodettagli, ma mantenere attiva l'attività principale:
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/list-detail_to_list-sub-detail.png?authuser=7&hl=it)
Kotlin
class DetailActivity { . . . fun onOpenSubDetail() { startActivity(Intent(this, SubDetailActivity::class.java)) } }
Java
public class DetailActivity { . . . void onOpenSubDetail() { startActivity(new Intent(this, SubDetailActivity.class)); } }
L'attività dei dettagli secondari viene posizionata sopra l'attività dei dettagli, nascondendola:
L'utente può quindi tornare al livello di dettaglio precedente tornando indietro nello stack:
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/list-sub-detail_to_list-detail.png?authuser=7&hl=it)
Sovrapporre le attività una sopra l'altra è il comportamento predefinito quando le attività vengono avviate da un'attività nello stesso contenitore secondario. Le attività avviate dal container principale all'interno di un segmento attivo terminano anch'esse nel container secondario in cima allo stack delle attività.
Attività in una nuova attività
Quando le attività in una finestra di attività divisa avviano attività in una nuova attività, quest'ultima è separata dall'attività che include la suddivisione e viene visualizzata a schermo intero. La schermata Recenti mostra due attività: l'attività suddivisa e la nuova.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/task_1_to_task_2.png?authuser=7&hl=it)
Sostituzione attività
Le attività possono essere sostituite nello stack di container secondario, ad esempio quando l'attività principale viene utilizzata per la navigazione di primo livello e l'attività secondaria è una destinazione selezionata. Ogni selezione della navigazione di primo livello deve avviare una nuova attività nel contenitore secondario e rimuovere quella o le attività che erano presenti in precedenza.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/menu_screen_a_to_menu_screen_b.png?authuser=7&hl=it)
Se l'app non completa l'attività nel contenitore secondario quando la selezione della navigazione cambia, la navigazione a ritroso potrebbe creare confusione quando la suddivisione è compressa (quando il dispositivo è piegato). Ad esempio, se c'è un menu nel riquadro principale e le schermate A e B sono sovrapposte nel riquadro secondario, quando l'utente chiude lo smartphone, B si trova su A e A è sopra il menu. Quando l'utente torna dalla pagina B, al suo posto viene visualizzata la lettera A.
In questi casi, è necessario rimuovere lo schermo A dallo stack posteriore.
Il comportamento predefinito quando si esegue l'avvio in un nuovo container su una suddivisione esistente è quello di collocare i nuovi container secondari in cima e conservare quelli vecchi nel back stack. Puoi configurare le suddivisioni in modo da cancellare i container secondari
precedenti con clearTop
e avviare normalmente le nuove attività.
<SplitPairRule
window:clearTop="true">
<SplitPairFilter
window:primaryActivityName=".Menu"
window:secondaryActivityName=".ScreenA"/>
<SplitPairFilter
window:primaryActivityName=".Menu"
window:secondaryActivityName=".ScreenB"/>
</SplitPairRule>
Kotlin
class MenuActivity { . . . fun onMenuItemSelected(selectedMenuItem: Int) { startActivity(Intent(this, classForItem(selectedMenuItem))) } }
Java
public class MenuActivity { . . . void onMenuItemSelected(int selectedMenuItem) { startActivity(new Intent(this, classForItem(selectedMenuItem))); } }
In alternativa, utilizza la stessa attività secondaria e dall'attività principale (di menu) invia nuovi intent che si risolvono nella stessa istanza, ma attivano un aggiornamento dello stato o dell'interfaccia utente nel contenitore secondario.
Più suddivisioni
Le app possono fornire una navigazione approfondita multilivello avviando attività aggiuntive a lato.
Quando un'attività in un container secondario avvia una nuova attività a lato, viene creata una nuova suddivisione sopra la suddivisione esistente.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/a_b_to_b_c.png?authuser=7&hl=it)
Lo stack posteriore contiene tutte le attività che sono state aperte in precedenza, quindi gli utenti possono passare alla suddivisione A/B al termine dell'operazione C.
Per creare una nuova suddivisione, avvia la nuova attività sul lato del container secondario esistente. Dichiara le configurazioni sia per i segmenti A/B e B/C e l'attività di lancio C normalmente da B:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
<SplitPairFilter
window:primaryActivityName=".B"
window:secondaryActivityName=".C"/>
</SplitPairRule>
Kotlin
class B { . . . fun onOpenC() { startActivity(Intent(this, C::class.java)) } }
Java
public class B { . . . void onOpenC() { startActivity(new Intent(this, C.class)); } }
Reagisci alle modifiche di stato di suddivisione
Le diverse attività in un'app possono avere elementi UI che svolgono la stessa funzione; ad esempio, un controllo che apre una finestra contenente le impostazioni dell'account.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/main_detail_with_ui_element.png?authuser=7&hl=it)
Se due attività che hanno un elemento UI in comune sono suddivise in una suddivisione, è ridondante e potrebbe confondere la visualizzazione dell'elemento in entrambe le attività.
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/main_detail_with_ui_element_duplicated.png?authuser=7&hl=it)
Per sapere quando le attività si trovano in una suddivisione, controlla il flusso SplitController.splitInfoList
o registra un listener con SplitControllerCallbackAdapter
per rilevare eventuali cambiamenti nello stato di suddivisione. Quindi, modifica l'UI di conseguenza:
Kotlin
val layout = layoutInflater.inflate(R.layout.activity_main, null) val view = layout.findViewById<View>(R.id.infoButton) lifecycleScope.launch { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { splitController.splitInfoList(this@SplitDeviceActivity) // The activity instance. .collect { list -> view.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE } } }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { . . . new SplitControllerCallbackAdapter(SplitController.getInstance(this)) .addSplitListener( this, Runnable::run, splitInfoList -> { View layout = getLayoutInflater().inflate(R.layout.activity_main, null); layout.findViewById(R.id.infoButton).setVisibility( splitInfoList.isEmpty() ? View.VISIBLE : View.GONE); }); }
Le coroutine possono essere lanciate in qualsiasi stato del ciclo di vita, ma in genere vengono lanciate nello stato STARTED
per risparmiare risorse (per saperne di più, consulta Utilizzare le coroutine Kotlin con componenti sensibili al ciclo di vita).
I callback possono essere effettuati in qualsiasi stato del ciclo di vita, anche quando un'attività viene interrotta. Generalmente i listener devono essere registrati in onStart()
e
non registrati in onStop()
.
modale a schermo intero
Alcune attività impediscono agli utenti di interagire con l'applicazione finché non viene eseguita un'azione specificata; ad esempio, un'attività nella schermata di accesso, una schermata di conferma delle norme o un messaggio di errore. Le attività modali non dovrebbero comparire in una suddivisione.
È possibile forzare un'attività a riempire sempre la finestra dell'attività utilizzando la configurazione di espansione:
<ActivityRule
window:alwaysExpand="true">
<ActivityFilter
window:activityName=".FullWidthActivity"/>
</ActivityRule>
Termina attività
Gli utenti possono terminare le attività ai lati del segmento scorrendo dal bordo del display:
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/swipe_gesture_finish_b.png?authuser=7&hl=it)
![](https://developer.android.com/static/images/guide/topics/large-screens/activity-embedding/swipe_gesture_finish_a.png?authuser=7&hl=it)
Se il dispositivo è configurato per l'utilizzo del pulsante Indietro anziché della navigazione tramite gesti, l'input viene inviato all'attività attiva, ovvero l'attività toccata o avviata per ultima.
L'effetto che il completamento di tutte le attività in un contenitore ha sul contenitore opposto dipende dalla configurazione di suddivisione.
Attributi di configurazione
Puoi specificare gli attributi delle regole di coppia di suddivisione per configurare il modo in cui il completamento di tutte le attività su un lato della suddivisione influisca sulle attività sull'altro lato della suddivisione. Gli attributi sono:
window:finishPrimaryWithSecondary
: come la fine di tutte le attività nel contenitore secondario influisce sulle attività nel contenitore principalewindow:finishSecondaryWithPrimary
: come la fine di tutte le attività nel contenitore principale influisce sulle attività nel contenitore secondario
I valori possibili degli attributi includono:
always
: completa sempre le attività nel contenitore associatonever
: non completare mai le attività nel contenitore associatoadjacent
: completa le attività nel contenitore associato quando i due contenitori sono visualizzati adiacenti, ma non quando sono impilati.
Ecco alcuni esempi:
<SplitPairRule
<!-- Do not finish primary container activities when all secondary container activities finish. -->
window:finishPrimaryWithSecondary="never"
<!-- Finish secondary container activities when all primary container activities finish. -->
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Configurazione predefinita
Quando tutte le attività in un contenitore di una suddivisione vengono terminate, il contenitore rimanente occupa l'intera finestra:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Completa le attività insieme
Completa automaticamente le attività nel contenitore principale al termine di tutte le attività nel contenitore secondario:
<SplitPairRule
window:finishPrimaryWithSecondary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Completa automaticamente le attività nel contenitore secondario al termine di tutte le attività nel contenitore principale:
<SplitPairRule
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Completa le attività insieme quando tutte le attività nel contenitore principale o secondario terminano:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Completa più attività nei container
Se più attività sono raggruppate in un contenitore diviso, il completamento di un'attività in fondo alla pila non termina automaticamente le attività nell'elenco superiore.
Ad esempio, se due attività si trovano nel contenitore secondario, C sopra di B:
e la configurazione della suddivisione è definita dalla configurazione delle attività A e B:
<SplitPairRule>
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
se finisci l'attività principale, la suddivisione rimane.
Il completamento dell'attività inferiore (principale) del container secondario non rimuove le attività che si trovano sopra il container e quindi conserva anche la suddivisione.
Vengono eseguite anche eventuali regole aggiuntive per completare le attività insieme, come il completamento dell'attività secondaria con l'attività principale:
<SplitPairRule
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
E quando la suddivisione è configurata per completare l'operazione principale e secondaria insieme:
<SplitPairRule
window:finishPrimaryWithSecondary="always"
window:finishSecondaryWithPrimary="always">
<SplitPairFilter
window:primaryActivityName=".A"
window:secondaryActivityName=".B"/>
</SplitPairRule>
Modifica le proprietà di suddivisione in fase di esecuzione
Le proprietà di una suddivisione attualmente attiva e visibile non possono essere modificate. La modifica delle regole di suddivisione influisce su ulteriori avvii di attività e nuovi container, ma non sulle suddivisioni esistenti e attive.
Per modificare le proprietà dei segmenti attivi, termina l'attività secondaria o le attività nella suddivisione e avviala di nuovo di lato con una nuova configurazione.
Estrae un'attività da una suddivisione a una finestra intera
Crea una nuova configurazione che mostri l'intera finestra dell'attività secondaria, quindi riavvia l'attività con un intent che si risolve nella stessa istanza.
Verificare il supporto suddiviso in fase di runtime
L'incorporamento delle attività è supportato su Android 12L (livello API 32) e versioni successive, ma è disponibile anche su alcuni dispositivi con versioni della piattaforma precedenti. Per verificare la disponibilità della funzionalità in fase di runtime, utilizza la proprietà SplitController.splitSupportStatus
o il metodo SplitController.getSplitSupportStatus()
:
Kotlin
if (SplitController.getInstance(this).splitSupportStatus == SplitController.SplitSupportStatus.SPLIT_AVAILABLE) { // Device supports split activity features. }
Java
if (SplitController.getInstance(this).getSplitSupportStatus() == SplitController.SplitSupportStatus.SPLIT_AVAILABLE) { // Device supports split activity features. }
Se i segmenti non sono supportati, le attività vengono avviate sopra lo stack delle attività (in base al modello di incorporamento non attività).
Impedisci override del sistema
I produttori di dispositivi Android (produttore di apparecchiature originali o OEM) possono implementare l'incorporamento dell'attività come funzione del sistema dei dispositivi. Il sistema specifica regole di suddivisione per le app multiattività, che sostituiscono il comportamento di windowing delle app. L'override di sistema forza le app multiattività in una modalità di incorporamento dell'attività definita dal sistema.
L'incorporamento dell'attività di sistema può migliorare la presentazione dell'app tramite layout a più riquadri, come list-detail, senza alcuna modifica all'app. Tuttavia, l'incorporamento dell'attività del sistema potrebbe anche causare errori di layout, bug o conflitti con l'incorporamento dell'attività implementato dall'app.
La tua app può impedire o consentire l'incorporamento dell'attività di sistema impostando una proprietà nel file manifest dell'app, ad esempio:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<property
android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_ALLOW_SYSTEM_OVERRIDE"
android:value="true|false" />
</application>
</manifest>
Il nome della proprietà è definito nell'oggetto Jetpack WindowManager
WindowProperties.
Imposta il valore su false
se la tua app implementa l'incorporamento delle attività o se
vuoi altrimenti impedire al sistema di applicare le regole di incorporamento delle attività
all'app. Imposta il valore su true
per consentire al sistema di applicare
l'incorporamento di attività definito dal sistema alla tua app.
Limitazioni, restrizioni e avvertenze
- Solo l'app host dell'attività, identificata come proprietaria dell'attività principale nell'attività, può organizzare e incorporare altre attività nell'attività. Se le attività che supportano l'incorporamento e le suddivisioni vengono eseguite in un'attività che appartiene a un'altra applicazione, l'incorporamento e le suddivisioni non funzioneranno per quelle attività.
- Le attività possono essere organizzate solo all'interno di una singola attività. Quando si avvia un'attività in una nuova attività, questa viene sempre inserita in una nuova finestra espansa al di fuori di eventuali suddivisioni esistenti.
- Solo le attività nello stesso processo possono essere organizzate e suddivise. Il callback
SplitInfo
segnala solo le attività che appartengono allo stesso processo, in quanto non è possibile sapere quali sono le attività in processi diversi. - Ogni coppia o singola regola di attività si applica solo agli avvii di attività che si verificano dopo la registrazione della regola. Al momento non è possibile aggiornare i segmenti esistenti o le relative proprietà visive.
- La configurazione del filtro della coppia divisa deve corrispondere agli intent utilizzati durante l'avvio completo delle attività. La corrispondenza avviene nel momento in cui viene avviata una nuova attività dal processo dell'applicazione, quindi potrebbe non essere a conoscenza dei nomi dei componenti che vengono risolti in un secondo momento nel processo di sistema quando si utilizzano intent impliciti. Se il nome di un componente non è noto al momento del lancio, è possibile utilizzare un carattere jolly ("*/*") e l'applicazione di filtri in base all'azione dell'intent.
- Al momento non è possibile spostare le attività tra i container o all'interno e all'esterno dei segmenti dopo la loro creazione. Le suddivisioni vengono create dalla libreria WindowManager solo quando vengono avviate nuove attività con regole corrispondenti, mentre le suddivisioni vengono eliminate al termine dell'ultima attività in un container di suddivisione.
- Le attività possono essere riavviate quando la configurazione cambia. Di conseguenza, quando viene creata o rimossa una suddivisione e i limiti delle attività cambiano, l'attività può passare per l'eliminazione completa dell'istanza precedente e per crearne una nuova. Di conseguenza, gli sviluppatori di app devono fare attenzione, ad esempio, al lancio di nuove attività dai callback del ciclo di vita.
- I dispositivi devono includere l'interfaccia delle estensioni delle finestre per supportare l'incorporamento dell'attività. Quasi tutti i dispositivi con schermi di grandi dimensioni con Android 12L (livello API 32) o versioni successive includono l'interfaccia. Tuttavia, alcuni dispositivi con schermi di grandi dimensioni che non sono in grado di eseguire più attività non includono l'interfaccia delle estensioni delle finestre. Se un dispositivo con schermo grande non supporta la modalità multi-finestra, potrebbe non supportare l'incorporamento dell'attività.
Risorse aggiuntive
- Codelab: creazione di un layout con elenco dettagliato con incorporamento delle attività e Material Design
- Percorso di apprendimento - Incorporamento delle attività