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 na parte de cima 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 o iniciador ao lado), a atividade de cima 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 entradas no estado PAUSED. Por exemplo, tente tocar em ambas as atividades na tela dividida simultaneamente em um dispositivo com o Android 9.

Para preservar o indicador retomado de versões anteriores do Android (e para comunicar quando os apps precisam ter acesso a recursos de acesso exclusivo ou único), 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 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ó retomará a atividade que estiver mais alta na ordem Z. Os apps destinados ao Android 10 podem oferecer suporte a várias atividades sendo 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 esse problema, os apps precisam processar uma desconexão da câmera sem falhas. 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 esses 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 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 acontece 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 principal retomada

Depois de 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 principal anterior não tiver liberado o estado principal, uma mensagem de perda de estado principal será enviada a ela e um tempo limite será programado no lado do servidor (ActivityStackSupervisor#scheduleTopResumedStateLossTimeout()). Um relatório do estado principal é 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.