No Android 9 (e versões anteriores), os apps eram inseridos no estado PAUSED
quando:
- Uma nova atividade translúcida foi iniciada sobre o app, enquanto ele ainda estava visível (e, portanto, não foi interrompido).
- A atividade perdeu o foco, mas não foi oculta e o usuário pode interagir com ela. Por exemplo, no modo de várias janelas, várias atividades podem ficar visíveis e receber entrada por toque simultaneamente.
Essas situações diferem na quantidade de pausas que um app precisa fazer, mas não podem ser diferenciadas no nível do app.
No Android 10, todas as atividades com foco principal nas pilhas visíveis ficam no
estado RESUMED
. Isso melhora a compatibilidade com
várias janelas e modos MD para apps que usam
onPause()
em vez de onStop()
para interromper a atualização da interface e interagir
com o usuário. Isso significa que:
- As duas atividades na tela dividida são retomadas.
- Todas as atividades visíveis no modo de janelas de formato livre são retomadas.
- As atividades em várias telas podem ser retomadas ao mesmo tempo.
Figura 1. Retomada múltipla em um dispositivo dobrável
Figura 2. Retomada múltipla no modo de computador
As atividades podem estar no estado PAUSED
quando não podem ser focalizadas ou estão
parcialmente ocultas, como:
- Em uma tela dividida minimizada (com a tela de início ao lado), a atividade principal não é retomada porque não é focalizável.
- No modo picture-in-picture, a atividade não é retomada porque não pode ser focalizada.
- Quando as atividades são cobertas por outras atividades transparentes na mesma pilha.
Essa abordagem indica aos apps que uma atividade só pode receber entrada de um
usuário no estado RESUMED
. Antes do Android 10,
as atividades também podiam receber entrada no estado PAUSED
(por exemplo, tente tocar
as duas atividades na tela dividida simultaneamente em um dispositivo com o Android 9).
Para preservar o sinal retomado de versões anteriores do Android e se comunicar quando os apps precisam ter acesso a recursos de acesso exclusivo ou Singleton, o Android 10 inclui um novo callback:
Activity#onTopResumedActivityChanged(boolean onTop)
Quando invocado, esse callback é chamado entre Activity#onResume()
e Activity#onPause()
. Esse callback é opcional e pode ser ignorado,
para que uma atividade possa passar de um estado RESUMED
para um PAUSED
sem se tornar a mais importante no sistema. Por exemplo, no modo de várias janelas.
Como esse callback é opcional, ele não faz parte do ciclo de vida
da atividade e raramente é usado.
A atividade principal retomada anterior recebe e finaliza a execução de
onTopResumedActivity(false)
antes que a próxima atividade principal retomada
receba onTopResumedActivity(true)
, a menos que a atividade anterior
demore muito para processar a chamada de método e atinja o tempo limite de 500 ms.
Compatibilidade
Para manter a compatibilidade ao implementar o currículo múltiplo, considere estas soluções.
Várias atividades retomadas em um processo de app
- Problema. No Android 9 e versões anteriores, apenas uma atividade no sistema é retomada por vez. Todas as transições entre atividades envolvem pausar uma atividade antes de retomar outra. Alguns apps e frameworks, como o Flutter ou o LocalActivityManager do Android, usam esse fato e armazenam o estado da atividade retomada em singletons.
- Solução. No Android 9 e versões anteriores, se duas atividades do mesmo processo forem retomadas, o sistema só vai retomar a atividade que estiver mais alta na ordem Z. Os apps destinados ao Android 10 podem oferecer suporte a várias atividades retomadas ao mesmo tempo.
Acesso simultâneo à câmera
- Problemas. Esses problemas também estão presentes no Android 9 e
versões anteriores. Por exemplo, uma atividade retomada e em tela cheia pode perder o foco da câmera para uma
atividade pausada na parte de cima no modo picture-in-picture, mas ficar mais exposta com
a adoção mais ampla dos modos de várias janelas e várias telas.
- Devido a mudanças feitas no estado
RESUME
, os apps podem ser desconectados da câmera mesmo quando retomados. Para resolver isso, os apps precisam processar a desconexão da câmera sem falhar. Quando desconectados, os apps recebem um callback desconectado, e todas as chamadas para a API começam a gerarCameraAccessException
. resizeableActivity=false
não garante o acesso exclusivo à câmera, já que outros apps que usam a câmera podem ser abertos em outras telas.
- Devido a mudanças feitas no estado
- Soluções. Os desenvolvedores precisam incluir a lógica para quando um app
é desconectado da câmera. Se um app for desconectado da câmera, ele
precisa monitorar os callbacks de disponibilidade da câmera para tentar se reconectar e continuar
usando a câmera. Além do callback
CameraManager#AvailabilityCallback#onCameraAvailable()
, o Android 10 adicionouCameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged()
, que abrange o caso em que o foco (e a prioridade da câmera) alterna entre várias atividades retomadas. Os desenvolvedores de apps precisam usar ambos os callbacks para determinar um bom momento para tentar acessar a câmera.
Retomada múltipla
No Android 10, o estado do ciclo de vida da atividade é determinado pela visibilidade e
ordem Z. Para garantir que o estado correto seja aplicado após as atualizações de visibilidade em uma
atividade e avaliar qual estado do ciclo de vida é aplicável, invoque o
método ActivityRecord#makeActiveIfNeeded()
de diferentes
locais. No Android 10, ativo significa RESUMED
ou
PAUSED
e funciona apenas nessas duas instâncias.
No Android 10, a retomada de uma atividade é rastreada separadamente em cada pilha
em vez de no único local do sistema. Isso ocorre porque várias
transições de atividade podem ser realizadas simultaneamente nos modos de várias janelas. Para
mais detalhes, consulte ActivityStack#mInResumeTopActivity
.
Callback de atividade retomada
Após ações que podem resultar em uma mudança de atividade principal, como
início, retomada ou mudança de ordem Z,
ActivityStackSupervisor#updateTopResumedActivityIfNeeded()
é invocado. Esse
método verifica se a atividade retomada mais importante mudou e executa a atualização, se
necessário. Se a atividade de retomada anterior não liberar o estado de retomada
anterior, uma mensagem de perda do estado de retomada anterior será enviada a ela e um tempo limite será
programado no lado do servidor
(ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()
).
Um relatório do estado de retomada anterior é enviado para a próxima atividade depois que a anterior
libera o estado ou quando um tempo limite é atingido (consulte os usos de:
ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()
Um novo item de transação TopResumedActivityChangeItem
foi adicionado
para informar aos clientes as mudanças de estado de retomada e aproveita a
arquitetura ActivityLifecycler
do Android 9.
O estado de retomada principal é armazenado no lado do cliente e, sempre que a
atividade transita para RESUMED
ou PAUSED
, ela também
verifica se o callback onTopResumedActivityChanged()
precisa ser
invocado. Isso permite um certo desacoplamento na comunicação dos estados do ciclo de vida
e do estado de retomada principal entre o servidor e o cliente.