Retomadas múltiplas

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 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 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 adicionou CameraManager#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.