In Android 9 (e versioni precedenti), le app entravano 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 la messa a fuoco, ma non è stata oscurata e l'utente ha potuto interagire con essa. Ad esempio, in modalità multi-finestra, più attività possono essere visibili e ricevere input tattili contemporaneamente.
Queste situazioni differiscono per la quantità di sospensione che un'app deve eseguire, ma non possono essere distinte a livello di app.
In Android 10, tutte le attività selezionabili in primo piano negli stack visibili si trovano nello stato
RESUMED
. Ciò migliora la compatibilità con
Multi-Window e le modalità MD per le app che utilizzano
onPause()
anziché onStop()
per interrompere l'aggiornamento dell'interfaccia utente e l'interazione
con l'utente. Ciò significa:
- Entrambe le attività in modalità schermo diviso vengono riprese.
- Tutte le attività visibili in primo piano in modalità finestra in formato libero vengono riprese.
- Le attività su più schermi possono essere riprese contemporaneamente.
Figura 1. Ripresa multipla su un dispositivo pieghevole
Figura 2. Ripresa multipla in modalità desktop
Le attività possono trovarsi nello stato PAUSED
quando non è possibile metterle a fuoco o sono
parzialmente occluse, ad esempio:
- In una schermata divisa ridotta (con il launcher laterale), l'attività in primo piano non viene ripresa perché non è selezionabile.
- In modalità Picture in picture, l'attività non viene ripresa perché non è selezionabile.
- 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 ricevere input anche nello stato PAUSED
(ad esempio, prova a toccare
entrambe le attività in modalità Split Screen contemporaneamente su un dispositivo con Android 9).
Per preservare il segnale resumed delle versioni precedenti di Android (e per comunicare quando le app devono ottenere l'accesso a risorse singleton o con accesso esclusivo), 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 dallo stato RESUMED
a quello PAUSED
senza diventare la più in primo piano nel sistema. Ad esempio, in modalità multi-finestra.
Poiché questo callback è facoltativo, non fa parte del ciclo di vita
dell'attività e deve essere utilizzato raramente.
L'attività precedente ripresa in primo piano riceve e termina l'esecuzione di
onTopResumedActivity(false)
prima che l'attività successiva ripresa in primo piano
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 della ripresa multipla, valuta queste soluzioni.
Più attività riprese in un processo dell'app
- Problema. In Android 9 e versioni precedenti, viene ripresa una sola attività alla volta nel sistema. Tutte le transizioni tra le attività prevedono la messa in pausa di un'attività prima di riprenderne un'altra. Alcune app e alcuni framework (come Flutter o LocalActivityManager di Android) utilizzano questo fatto e memorizzano lo stato dell'attività ripresa nei singleton.
- Soluzione. In Android 9 e versioni precedenti, se vengono riprese due attività dello stesso processo, il sistema riprende solo l'attività che si trova più in alto nell'ordine Z. Le app che hanno come target Android 10 possono supportare la ripresa di più attività contemporaneamente.
Accesso simultaneo alla videocamera
- Problemi. Questi problemi sono presenti anche in Android 9 e versioni precedenti. Ad esempio, un'attività a schermo intero e ripresa può perdere la messa a fuoco della fotocamera a favore di un'attività in pausa in primo piano in modalità Picture in picture, ma diventare più esposta 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 dopo la ripresa. Per risolvere questo problema, le app devono gestire la 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 generareCameraAccessException
. resizeableActivity=false
non garantisce l'accesso esclusivo alla fotocamera, perché altre app che la utilizzano possono essere aperte su altri display.
- A causa delle modifiche apportate allo stato
- Soluzioni. Gli sviluppatori devono includere la logica per quando un'app
viene disconnessa dalla videocamera. Se un'app è disconnessa dalla videocamera, deve
monitorare i callback di disponibilità della videocamera per provare a riconnettersi e continuare
a utilizzare la videocamera. Oltre al callback
CameraManager#AvailabilityCallback#onCameraAvailable()
esistente, Android 10 ha aggiuntoCameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()
, che copre il caso in cui la messa a fuoco (e la priorità della videocamera) cambia tra diverse attività riprese. Gli sviluppatori di app devono utilizzare entrambi questi callback per determinare il momento migliore per tentare di accedere alla videocamera.
Multi-resume
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à e valutare quale stato del ciclo di vita è applicabile, richiama il metodo ActivityRecord#makeActiveIfNeeded()
da diverse posizioni. In Android 10, attivo significa RESUMED
o
PAUSED
e funziona solo in queste due istanze.
In Android 10, la ripresa di un'attività viene monitorata separatamente in ogni stack
anziché nella singola posizione del sistema. Questo perché in modalità multi-finestra è possibile eseguire contemporaneamente diverse transizioni di attività. Per
maggiori dettagli, vedi ActivityStack#mInResumeTopActivity
.
Callback dell'attività ripresa in primo piano
Dopo le azioni che possono comportare una modifica dell'attività principale (ad esempio avvio, ripresa o modifica dell'ordine Z dell'attività),
viene richiamato ActivityStackSupervisor#updateTopResumedActivityIfNeeded()
. Questo
metodo controlla se l'attività ripresa in primo piano è cambiata ed esegue l'aggiornamento se
necessario. Se l'attività precedente ripresa in primo piano non ha rilasciato lo stato di ripresa in primo piano, le viene inviato un messaggio di perdita dello stato di ripresa in primo piano e viene pianificato un timeout sul lato server (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
). Un report dello stato di ripresa in primo piano viene inviato all'attività successiva dopo che quella 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 principale e sfrutta l'architettura
ActivityLifecycler
di Android 9.
Lo stato di ripresa dall'alto viene memorizzato sul lato client e ogni volta che l'attività passa a RESUMED
o PAUSED
, viene anche verificato se deve essere richiamato il callback onTopResumedActivityChanged()
. Ciò consente un certo disaccoppiamento nella comunicazione degli stati del ciclo di vita
e dello stato di ripresa principale tra il server e il client.