Dans Android 9 (et versions antérieures), les applications passaient à l'état PAUSED
lorsque :
- Une nouvelle activité translucide a été lancée au-dessus de l'application, alors que celle-ci était toujours visible (et donc non arrêtée).
- L'activité a perdu le focus, mais n'était pas masquée et l'utilisateur pouvait interagir avec elle. Par exemple, en mode multifenêtre, plusieurs activités peuvent être visibles et recevoir des entrées tactiles simultanément.
Ces situations diffèrent par la quantité de mise en pause qu'une application doit effectuer, mais ne peuvent pas être distinguées au niveau de l'application.
Dans Android 10, toutes les activités axées sur le haut de la pile dans les piles visibles résident dans l'état RESUMED
. Cela améliore la compatibilité avec les modes Multi-Window et MD pour les applications qui utilisent onPause()
au lieu de onStop()
pour arrêter d'actualiser l'UI et d'interagir avec l'utilisateur. Autrement dit :
- Les deux activités en écran partagé sont réactivées.
- Toutes les activités visibles au premier plan en mode Format libre sont reprises.
- Les activités sur plusieurs écrans peuvent être reprises en même temps.
Figure 1 : Multireprise sur un appareil pliable
Figure 2. Multireprise en mode Bureau
Les activités peuvent résider dans l'état PAUSED
lorsqu'elles ne peuvent pas être sélectionnées ou sont partiellement masquées, par exemple :
- Dans un écran partagé réduit (avec le lanceur sur le côté), l'activité supérieure n'est pas reprise, car elle n'est pas sélectionnable.
- En mode Picture-in-picture, l'activité n'est pas reprise, car elle ne peut pas être sélectionnée.
- Lorsque des activités sont couvertes par d'autres activités transparentes dans la même pile.
Cette approche indique aux applications qu'une activité ne peut recevoir des saisies de l'utilisateur que dans l'état RESUMED
. Avant Android 10, les activités pouvaient également recevoir des entrées dans l'état PAUSED
(par exemple, essayez de toucher les deux activités en mode Écran partagé simultanément sur un appareil exécutant Android 9).
Pour préserver le signal resumed des versions précédentes d'Android (et pour communiquer le moment où les applications doivent obtenir l'accès à des ressources à accès exclusif ou singleton), Android 10 inclut un nouveau rappel :
Activity#onTopResumedActivityChanged(boolean onTop)
Lorsqu'il est appelé, ce rappel est appelé entre Activity#onResume()
et Activity#onPause()
. Ce rappel est facultatif et peut être ignoré. Une activité peut donc passer de l'état RESUMED
à l'état PAUSED
sans devenir l'activité la plus élevée du système. Par exemple, en mode multifenêtre.
Étant donné que ce rappel est facultatif, il ne fait pas partie du cycle de vie de l'activité et doit être rarement utilisé.
L'activité précédente au premier plan reçoit et termine l'exécution de onTopResumedActivity(false)
avant que la prochaine activité au premier plan ne reçoive onTopResumedActivity(true)
, sauf si l'activité précédente prend trop de temps pour gérer l'appel de méthode et atteint le délai d'expiration de 500 ms.
Compatibilité
Pour maintenir la compatibilité lors de l'implémentation de la reprise multiple, envisagez les solutions suivantes.
Plusieurs activités reprises dans un même processus d'application
- Problème. Dans Android 9 et les versions antérieures, une seule activité du système est reprise à la fois. Toutes les transitions entre les activités impliquent de mettre en pause une activité avant d'en reprendre une autre. Certaines applications et certains frameworks (tels que Flutter ou LocalActivityManager d'Android) utilisent ce fait et stockent l'état de l'activité reprise dans des singletons.
- Solution. Dans Android 9 et les versions antérieures, si deux activités du même processus sont toutes les deux reprises, le système ne reprend que l'activité dont l'ordre Z est le plus élevé. Les applications ciblant Android 10 peuvent prendre en charge la reprise de plusieurs activités en même temps.
Accès simultané à la caméra
- Problèmes Ces problèmes sont également présents dans Android 9 et les versions antérieures. Par exemple, une activité en plein écran et réactivée peut perdre le focus de la caméra au profit d'une activité en pause en mode Picture-in-picture, mais devenir plus exposée avec l'adoption plus large des modes multifenêtre et multi-écran.
- En raison des modifications apportées à l'état
RESUME
, il est possible que les applications soient déconnectées de la caméra même lorsqu'elles sont en pause. Pour résoudre ce problème, les applications doivent gérer la déconnexion de la caméra sans planter. Lorsqu'une application est déconnectée, elle reçoit un rappel de déconnexion et tous les appels à l'API commencent à générerCameraAccessException
. resizeableActivity=false
ne garantit pas un accès exclusif à la caméra, car les autres applications qui utilisent cette même fonctionnalité peuvent être ouvertes sur d'autres écrans.
- En raison des modifications apportées à l'état
- Solutions Les développeurs doivent inclure une logique pour le cas où une application est déconnectée de la caméra. Si une application est déconnectée de la caméra, elle doit surveiller les rappels de disponibilité de la caméra pour essayer de se reconnecter et continuer à utiliser la caméra. En plus du rappel
CameraManager#AvailabilityCallback#onCameraAvailable()
existant, Android 10 a ajoutéCameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()
, qui couvre le cas où la mise au point (et la priorité de la caméra) bascule entre plusieurs activités reprises. Les développeurs d'applications doivent utiliser ces deux rappels pour déterminer le bon moment pour essayer d'accéder à la caméra.
Multireprise
Dans Android 10, l'état du cycle de vie de l'activité est déterminé par la visibilité et l'ordre Z. Pour vous assurer que l'état est correct après les mises à jour de la visibilité d'une activité et évaluer l'état du cycle de vie applicable, appelez la méthode ActivityRecord#makeActiveIfNeeded()
à partir de différents emplacements. Dans Android 10, "actif" signifie RESUMED
ou PAUSED
, et ne fonctionne que dans ces deux cas.
Dans Android 10, la reprise d'une activité est suivie séparément dans chaque pile au lieu d'être suivie dans un seul emplacement du système. En effet, plusieurs transitions d'activité peuvent être effectuées simultanément en mode Multifenêtre. Pour en savoir plus, consultez ActivityStack#mInResumeTopActivity
.
Rappel d'activité la plus récemment reprise
Après des actions pouvant entraîner une modification de l'activité principale (telles que le lancement, la reprise ou la modification de l'ordre Z d'une activité), ActivityStackSupervisor#updateTopResumedActivityIfNeeded()
est appelé. Cette méthode vérifie si l'activité réactivée la plus élevée a changé et effectue la mise à jour si nécessaire. Si l'activité précédemment la plus élevée n'a pas libéré l'état de reprise la plus élevée, un message de perte d'état de reprise la plus élevée lui est envoyé et un délai d'expiration est planifié côté serveur (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
). Un rapport de l'état de reprise la plus élevée est envoyé à l'activité suivante une fois que la précédente a libéré l'état ou lorsqu'un délai d'expiration a été atteint (voir les utilisations de :
ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()
Un nouvel élément de transaction TopResumedActivityChangeItem
a été ajouté pour signaler aux clients les principaux changements d'état de reprise et exploite l'architecture ActivityLifecycler
d'Android 9.
L'état de reprise le plus élevé est stocké côté client. Chaque fois que l'activité passe à RESUMED
ou PAUSED
, elle vérifie également si le rappel onTopResumedActivityChanged()
doit être appelé. Cela permet un certain découplage dans la communication des états de cycle de vie et de l'état de reprise en haut de pile entre les côtés serveur et client.