Riprendi da dove avevi interrotto

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

  • Una nuova attività traslucida veniva avviata sopra l'app, mentre l'app era ancora visibile (e, di conseguenza, non era stata arrestata).
  • L'attività perdeva lo stato attivo, ma non era oscurata e l'utente poteva interagire con essa. Ad esempio, in modalità multi-finestra, diverse 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à principali selezionabili 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 schermo diviso vengono riprese.
  • Tutte le attività principali visibili 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 possono essere selezionate o sono parzialmente oscurate, ad esempio:

  • In uno schermo diviso ridotto a icona (con il launcher sul lato), l'attività principale 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 contemporaneamente entrambe le attività in schermo diviso su un dispositivo con Android 9).

Per conservare il segnale ripreso delle versioni precedenti di Android (e per comunicare quando le app devono ottenere l'accesso a risorse esclusive 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, quindi un'attività può passare dallo stato RESUMED allo stato PAUSED senza diventare la principale 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à principale ripresa precedente riceve e completa l'esecuzione di onTopResumedActivity(false) prima che la successiva attività principale ripresa riceva onTopResumedActivity(true), a meno che l'attività precedente 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, prendi in considerazione queste soluzioni.

Più attività riprese in un processo di app

  • Problema. In Android 9 e versioni precedenti, viene ripresa una sola attività alla volta nel sistema. Tutte le transizioni tra le attività comportano la sospensione 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à con un ordine Z più alto. 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 lo stato attivo della videocamera a favore di un'attività in pausa in modalità Picture in picture, ma diventare più esposta con una maggiore adozione delle modalità multi-finestra e multi-display.
    • A causa delle modifiche apportate allo stato RESUME, le app potrebbero essere disconnesse dalla videocamera anche se riprese. Per risolvere questo problema, le app devono gestire una disconnessione della videocamera senza arrestarsi in modo anomalo. Quando sono disconnesse, 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 videocamera, perché altre app che utilizzano la videocamera possono essere aperte su altri display.
  • Soluzioni. Gli sviluppatori devono includere la logica per quando un'app viene disconnessa dalla videocamera. Se un'app viene 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 lo stato attivo (e la priorità della videocamera) passa tra diverse attività riprese. Gli sviluppatori di app devono utilizzare entrambi questi callback per determinare il momento giusto per provare a ottenere l'accesso alla videocamera.

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 sia corretto dopo gli aggiornamenti della visibilità di un'attività e per valutare quale stato del ciclo di vita è applicabile, richiama il metodo ActivityRecord#makeActiveIfNeeded() da posizioni diverse. 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é in un'unica posizione nel sistema. Questo perché in modalità multi-finestra è possibile eseguire contemporaneamente diverse transizioni di attività. Per maggiori dettagli, consulta ActivityStack#mInResumeTopActivity.

Callback dell'attività principale ripresa

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 verifica se l'attività principale ripresa è cambiata ed esegue l'aggiornamento, se necessario. Se l'attività principale ripresa precedente non ha rilasciato lo stato principale ripreso, viene inviato un messaggio di perdita dello stato principale ripreso e viene pianificato un timeout sul lato server (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()). Un report dello stato principale ripreso viene inviato all'attività successiva dopo che quella precedente ha rilasciato lo stato o quando è stato raggiunto un timeout (vedi gli utilizzi di:

ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()

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

Lo stato principale ripreso viene memorizzato sul lato client e ogni volta che l'attività passa a RESUMED o PAUSED, viene verificato anche se deve essere richiamato il callback onTopResumedActivityChanged(). Ciò consente un certo disaccoppiamento nella comunicazione degli stati del ciclo di vita e dello stato principale ripreso tra il lato server e il lato client.