Riprendi da dove avevi interrotto

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 generare CameraAccessException.
    • resizeableActivity=false non garantisce l'accesso esclusivo alla fotocamera, perché altre app che la utilizzano possono essere aperte su altri display.
  • 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 aggiunto CameraManager#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.