Retomadas múltiplas

No Android 9 e em versões anteriores, os apps entravam no estado PAUSED quando:

  • Uma nova atividade translúcida 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 obscurecida e podia ser interagida pelo usuário. 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 em pilhas visíveis estão no estado RESUMED. Isso melhora a compatibilidade com os modos Multi-Window e MD para apps que usam onPause() em vez de onStop() para interromper a atualização da interface e a interação com o usuário. Isso significa que:

  • As duas atividades em tela dividida são retomadas.
  • Todas as atividades mais 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 ficar no estado PAUSED quando não podem ser focalizadas ou estão parcialmente ocultas, como:

  • Em uma tela dividida minimizada (com o iniciador na lateral), a atividade principal não é retomada porque não pode ser focalizada.
  • 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 nas duas atividades em tela dividida simultaneamente em um dispositivo com Android 9.

Para preservar o indicador retomado de versões anteriores do Android (e para comunicar quando os apps devem obter 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. Assim, uma atividade pode 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 deve ser usado raramente.

A atividade anterior no topo e retomada recebe e conclui a execução de onTopResumedActivity(false) antes que a próxima atividade no topo e 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 a retomada múltipla, 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 acima 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 em versões anteriores. Por exemplo, uma atividade em tela cheia e retomada 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 uma desconexão da câmera sem falhar. Quando desconectados, os apps recebem um callback de desconexão, e todas as chamadas para a API começam a gerar CameraAccessException.
    • 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.
  • Soluções. Os desenvolvedores precisam incluir lógica para quando um app é desconectado da câmera. Se um app for desconectado da câmera, ele precisará 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() atual, o Android 10 adicionou CameraManager#AvailabilityCallback#onCameraAccessPrioritiesChanged(), que abrange o caso em que o foco (e a prioridade da câmera) muda entre várias atividades retomadas. Os desenvolvedores de apps precisam usar os dois 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 pela ordem Z. Para garantir o estado correto após 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 em um único local no sistema. Isso acontece porque várias transições de atividade podem ser realizadas simultaneamente em modos de várias janelas. Para mais detalhes, consulte ActivityStack#mInResumeTopActivity.

Callback da atividade retomada principal

Depois de ações que podem resultar em uma mudança na atividade principal (como início, retomada ou mudança na ordem Z), ActivityStackSupervisor#updateTopResumedActivityIfNeeded() é invocado. Esse método verifica se a atividade retomada mais importante mudou e faz a atualização, se necessário. Se a atividade anterior em primeiro plano não tiver liberado o estado de primeiro plano, uma mensagem de perda de estado de primeiro plano será enviada a ela, e um tempo limite será programado no lado do servidor (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()). Um relatório do estado de primeiro plano será enviado para a próxima atividade depois que a anterior liberar o estado ou quando um tempo limite for atingido. Consulte os usos de:

ActivityStackSupervisor#scheduleTopResumedActivityStateIfNeeded()

Um novo item de transação TopResumedActivityChangeItem foi adicionado para informar as principais mudanças de estado retomadas aos clientes e aproveita a arquitetura ActivityLifecycler do Android 9.

O estado de retomada da parte superior é armazenado no lado do cliente, e cada vez que a atividade faz a transição para RESUMED ou PAUSED, ela também verifica se o callback onTopResumedActivityChanged() deve ser invocado. Isso permite um certo desacoplamento na comunicação de estados do ciclo de vida e o estado de retomada principal entre os lados do servidor e do cliente.