Ripresa multipla

In Android 9 (e versioni precedenti), le app sono state inserite nello stato PAUSED quando:

  • Una nuova attività traslucida è stata avviata sopra l'app, mentre l'app era ancora visibile (e quindi non è stata interrotta).
  • L'attività ha perso lo stato attivo, ma non era nascosta e l'utente poteva interagire con essa. Ad esempio, in modalità multi-finestra, è possibile visualizzare più attività e ricevere input tocco contemporaneamente.

Queste situazioni differiscono per la quantità di messa in pausa che un'app deve eseguire, ma non possono essere distinta a livello di app.

In Android 10, tutte le attività che possono essere messe a fuoco in primo piano nelle serie visibili si trovano nello stato RESUMED. In questo modo, viene migliorata la compatibilità con le modalità Multi-Window e MD per le app che utilizzano onPause() anziché onStop() per interrompere l'aggiornamento dell'interfaccia utente e l'interazione con l'utente. Ciò significa che:

  • Entrambe le attività in schermo diviso vengono riprese.
  • Tutte le attività più visibili in modalità di visualizzazione delle finestre in formato libero vengono riprese.
  • È possibile riprendere contemporaneamente le attività su più schermate.

Figura 1. Riprendi multipli su un dispositivo pieghevole

Figura 2. Riprendi multipli in modalità desktop

Le attività possono trovarsi nello stato PAUSED quando non è possibile metterle a fuoco o sono parzialmente occultate, ad esempio:

  • In uno schermo diviso ridotto a icona (con Avvio app a lato), l'attività principale non viene ripresa perché non è attivabile.
  • In modalità Picture in picture, l'attività non viene ripresa perché non è possibile mettere a fuoco.
  • Quando le attività sono coperte da altre attività trasparenti nello stesso stack.

Questo approccio indica alle app che un'attività può ricevere input da un utente solo nello stato RESUMED. Prima di Android 10, le attività potevano anche ricevere input nello stato PAUSED (ad esempio, prova a toccare contemporaneamente entrambe le attività in split screen su un dispositivo con Android 9).

Per preservare l'indicatore ripreso delle release di Android precedenti (e per comunicare quando le app devono ottenere l'accesso a risorse ad accesso esclusivo o singleton), Android 10 include un nuovo callback:

Activity#onTopResumedActivityChanged(boolean onTop)

Quando viene richiamato, questo callback viene chiamato tra Activity#onResume() e Activity#onPause(). Questo callback è facoltativo e può essere ignorato, in modo che un'attività possa passare da uno stato RESUMED a uno stato PAUSED senza diventare la più importante nel sistema. Ad esempio, in modalità multi-finestra. Poiché questo callback è facoltativo, non fa parte del ciclo di vita dell'attività e dovrebbe essere utilizzato raramente.

L'attività principale precedentemente ripresa riceve e completa l'esecuzione di onTopResumedActivity(false) prima che l'attività principale successiva ripresa riceva onTopResumedActivity(true), a meno che l'attività precedente non impieghi troppo tempo per gestire la chiamata al metodo e raggiunga il timeout di 500 ms.

Compatibilità

Per mantenere la compatibilità durante l'implementazione del salvataggio multiplo, valuta queste soluzioni.

Più attività riprese in un unico processo dell'app

  • Problema. In Android 9 e versioni precedenti, viene ripresa solo un'attività alla volta nel sistema. Tutte le transizioni tra attività comportano la messa in pausa di un'attività prima di riprendere un'altra. Alcune app e framework (come Flutter o LocalActivityManager di Android) sfruttano questo fatto e memorizzano lo stato dell'attività ripresa in oggetti singleton.
  • Soluzione. In Android 9 e versioni precedenti, se vengono entrambe riprese due attività dello stesso processo, il sistema riprende solo l'attività più alta nell'ordine Z. Le app che hanno come target Android 10 possono supportare la ripresa di più attività contemporaneamente.

Accesso simultaneo alla fotocamera

  • Problemi. Questi problemi sono presenti anche su Android 9 e versioni precedenti. Ad esempio, un'attività a schermo intero e ripresa può perdere l'attenzione della fotocamera a favore di un'attività in pausa in alto in modalità Picture in picture, ma diventare più visibile con l'adozione più ampia delle modalità multi-finestra e multi-display.
    • A causa delle modifiche apportate allo stato RESUME, le app potrebbero essere disconnesse dalla videocamera anche durante la ripresa. Per risolvere il problema, le app devono gestire una disconnessione della videocamera senza arrestarsi in modo anomalo. Quando la connessione viene interrotta, le app ricevono un callback di disconnessione e tutte le chiamate all'API iniziano a generare CameraAccessException.
    • resizeableActivity=false non garantisce l'accesso esclusivo alla fotocamera, perché altre app che utilizzano la fotocamera possono essere aperte su altri display.
  • Soluzioni. Gli sviluppatori devono includere la logica per quando un'app viene scollegata dalla videocamera. Se un'app è disconnessa dalla videocamera, deve monitorare i callback di disponibilità della videocamera per provare a riconnettersi e continuare a utilizzarla. Oltre al callback CameraManager#AvailabilityCallback#onCameraAvailable() esistente, Android 10 ha aggiunto CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged(), che riguarda il caso in cui la messa a fuoco (e la priorità della fotocamera) passi da una all'altra attività ripresa. Gli sviluppatori di app dovrebbero usare entrambi questi callback per determinare il momento opportuno per provare ad accedere alla fotocamera.

Ripresa multipla

In Android 10, lo stato del ciclo di vita dell'attività è determinato dalla visibilità e dall'ordine Z. Per assicurarti che lo stato corretto dopo gli aggiornamenti della visibilità di un'attività sia corretto e valutare quale stato del ciclo di vita sia applicabile, invoca il metodo ActivityRecord#makeActiveIfNeeded() da posizioni diverse. In Android 10, per "attivo" si intende RESUMED o PAUSED e funziona solo in questi due casi.

In Android 10, la ripresa di un'attività viene monitorata separatamente in ogni pila anziché nella singola posizione del sistema. Questo perché in modalità multi-finestra è possibile eseguire contemporaneamente più transizioni di attività. Per maggiori dettagli, vedi ActivityStack#mInResumeTopActivity.

Callback per l'attività più ripresa

Dopo azioni che possono comportare una modifica dell'attività principale (ad esempio l'avvio, la ripresa o la modifica dell'ordine Z dell'attività), viene invocato ActivityStackSupervisor#updateTopResumedActivityIfNeeded(). Questo metodo controlla se l'attività ripresa più in alto è cambiata ed esegue l'aggiornamento, se necessario. Se l'attività precedente più ripresa non ha rilasciato lo stato superiore ripristinato, viene inviato a quest'ultima un messaggio di perdita dello stato superiore ripristinato e viene pianificato un timeout sul lato server (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()). Un report dello stato superiore ripristinato viene inviato all'attività successiva dopo che la precedente ha rilasciato lo stato o quando è stato raggiunto un timeout (vedi utilizzi di:

ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()

È stato aggiunto un nuovo elemento di transazione TopResumedActivityChangeItem per segnalare ai client le modifiche dello stato di ripresa superiore e sfrutta l'architettura ActivityLifecycler di Android 9.

Lo stato di ripresa superiore viene memorizzato lato client e ogni volta che l'attività passa a RESUMED o PAUSED viene anche controllato se deve essere invocato il callback onTopResumedActivityChanged(). Ciò consente un certo disaccoppiamento nella comunicazione degli stati del ciclo di vita e dello stato di ripresa più recente tra il lato server e il lato client.