Sempre que um app é executado em segundo plano, ele consome alguns dos recursos limitados do dispositivo, como a RAM. Isso pode prejudicar a experiência do usuário, principalmente se ele estiver usando um app que consome muitos recursos, como um jogo ou um vídeo. Para melhorar a experiência do usuário, o Android 8.0 (nível 26 da API) impõe limitações ao que os apps podem fazer enquanto são executados em segundo plano. Este documento descreve as mudanças no sistema operacional e como atualizar seu app para que ele funcione bem com as novas limitações.
Visão geral
Muitos aplicativos e serviços do Android podem ser executados simultaneamente. Por exemplo, um usuário pode estar jogando um jogo em uma janela enquanto navega na Web em outra e usa um terceiro app para ouvir música. Quanto mais apps estiverem em execução ao mesmo tempo, maior será a carga no sistema. Se outros apps ou serviços estiverem em execução em segundo plano, isso vai gerar cargas adicionais no sistema, o que pode resultar em uma experiência de usuário ruim. Por exemplo, o app de música pode ser desativado repentinamente.
Para reduzir a chance de esses problemas, o Android 8.0 coloca limitações no que os apps podem fazer enquanto os usuários não estão interagindo diretamente com eles. Os aplicativos são limitados de duas maneiras:
Limitações de serviços em segundo plano: enquanto um app está inativo, há limites para o uso de serviços em segundo plano. Isso não se aplica a serviços em primeiro plano, que são mais perceptíveis para o usuário.
Limitações de transmissão: com exceções limitadas, os apps não podem usar o manifesto para se registrar para transmissões implícitas. Eles ainda podem se registrar para essas transmissões no momento de execução e usar o manifesto para se registrar para transmissões explícitas e transmissões segmentadas especificamente para o app.
Na maioria dos casos, os apps podem contornar essas limitações usando
jobs JobScheduler
. Essa abordagem permite que um app se organize para
realizar o trabalho quando não estiver em execução, mas ainda oferece ao sistema
a liberdade de programar esses trabalhos de uma forma que não afete a experiência
do usuário. O Android 8.0 oferece várias melhorias em JobScheduler
que facilitam a substituição de serviços e
broadcast receivers por jobs programados. Para mais informações, consulte
Melhorias no JobScheduler.
Limitações de serviço em segundo plano
Os serviços em execução em segundo plano podem consumir recursos do dispositivo, o que pode resultar em uma experiência do usuário pior. Para atenuar esse problema, o sistema aplica várias limitações aos serviços.
O sistema distingue apps em primeiro plano dos segundo plano. A definição de segundo plano para fins de limitações de serviço é diferente da definição usada pelo gerenciamento de memória. Um app pode estar em segundo plano em relação ao gerenciamento de memória, mas em primeiro plano em relação à capacidade de iniciar serviços. Considera-se que um aplicativo esteja em primeiro plano se alguma das seguintes coisas acontecer:
- Há uma atividade visível, esteja ela em curso ou pausada.
- Há um serviço de primeiro plano.
- Outro app em primeiro plano está conectado ao app, seja vinculado a um dos
serviços dele ou fazendo uso de um dos provedores de conteúdo. Por exemplo,
o app está em primeiro plano se outro app se vincula ao:
- IME
- Serviço de plano de fundo
- Listener de notificações
- Serviço de voz ou texto
Se nenhuma dessas condições for verdadeira, será considerado que o app está em segundo plano.
Enquanto um app está em primeiro plano, ele pode criar e executar serviços em primeiro plano e
em segundo plano livremente. Quando um app entra em segundo plano, ele tem uma
janela de vários minutos em que ainda pode criar e usar
serviços. Ao final desse período, o app é considerado inativo. Nesse
momento, o sistema interrompe os serviços em segundo plano do app, como se ele
tivesse chamado os métodos Service.stopSelf()
dos serviços.
Em determinadas circunstâncias, um app em segundo plano é colocado em uma lista de permissões temporária por vários minutos. Enquanto um app está na lista de permissões, ele pode iniciar serviços sem limitação, e os serviços em segundo plano podem ser executados. Um app é colocado na lista de permissões quando processa uma tarefa que é visível para o usuário, como:
- Processamento de uma mensagem de alta prioridade do Firebase Cloud Messaging (FCM).
- Receber uma transmissão, como uma mensagem SMS/MMS.
- Execução de um
PendingIntent
em uma notificação. - Inicie um
VpnService
antes que o app de VPN seja promovido para o primeiro plano.
Em muitos casos, o app pode substituir os serviços em segundo plano por jobs JobScheduler
.
Por exemplo, o CoolPhotoApp precisa verificar
se o usuário recebeu fotos compartilhadas de amigos, mesmo que o app não esteja
em execução em primeiro plano. Anteriormente, o app usava um serviço em segundo plano que
verificava o armazenamento em nuvem do app. Para migrar para o Android 8.0 (nível 26 da API),
o desenvolvedor substitui o serviço em segundo plano por um job programado, que é
iniciado periodicamente, consulta o servidor e é encerrado.
Antes do Android 8.0, a maneira usual de criar um serviço em primeiro plano
era criar um serviço em segundo plano e depois promover esse serviço para o primeiro plano.
Com o Android 8.0, há uma complicação: o sistema não permite que um app em segundo plano
crie um serviço em segundo plano. Por esse motivo, o Android 8.0 apresenta
o novo método startForegroundService()
para iniciar um novo serviço em
primeiro plano. Depois que o sistema cria
o serviço, o app tem cinco segundos para chamar o método [startForeground()
](/reference/android/app/Service#startForeground(int, android.app.Notification) do serviço para mostrar a nova
notificação visível para o usuário. Se o app não chamar startForeground()
dentro do
limite de tempo, o sistema vai interromper o serviço e declarar que o app é um
ANR.
Limitações de transmissão
Se um app se registrar para receber transmissões, o receptor do app vai consumir recursos sempre que a transmissão for enviada. Isso pode causar problemas se muitos apps se registrarem para receber transmissões com base em eventos do sistema. Um evento do sistema que aciona uma transmissão pode fazer com que todos esses apps consumam recursos em rápida sequência, prejudicando a experiência do usuário. Para atenuar esse problema, o Android 7.0 (nível 24 da API) impôs limitações às transmissões, conforme descrito em Otimização em segundo plano. O Android 8.0 (API de nível 26) torna essas limitações mais rigorosas.
- Os apps destinados ao Android 8.0 ou mais recente não podem mais registrar broadcast
receivers para transmissões implícitas no manifesto, a menos que a transmissão seja
restringida especificamente a esse app. Uma transmissão implícita é uma
transmissão que não tem como destino um componente específico em um app. Por
exemplo,
ACTION_PACKAGE_REPLACED
é enviada para todos os listeners registrados em todos os apps, informando que alguns pacotes no dispositivo foram substituídos. Como a transmissão é implícita, ela não será entregue a receptores registrados no manifesto em apps destinados ao Android 8.0 ou mais recente.ACTION_MY_PACKAGE_REPLACED
também é uma transmissão implícita, mas, como ela é enviada apenas para o app cujo pacote foi substituído, ela será entregue aos receptores registrados no manifesto. - Aplicativos podem continuar a se registrar para transmissões explícitas em seus manifestos.
- Os apps podem usar
Context.registerReceiver()
no tempo de execução para registrar um receptor para qualquer transmissão, seja implícita ou explícita. - As transmissões que exigem uma permissão de assinatura são isentas dessa restrição, já que são enviadas apenas para apps assinados com o mesmo certificado, e não para todos os apps no dispositivo.
Em muitos casos, os apps que já estavam registrados para uma transmissão implícita podem
ter uma funcionalidade semelhante usando um job JobScheduler
.
Por exemplo, um app de fotos de mídia social pode precisar limpar os dados de
vez em quando e preferir fazer isso quando o dispositivo estiver conectado a um carregador.
Anteriormente, o app registrava um receiver para ACTION_POWER_CONNECTED
no manifesto. Quando o app
recebia essa transmissão, ele verificava se a limpeza era necessária. Para
migrar para o Android 8.0 ou mais recente, o app remove esse receiver do
manifest. Em vez disso, o app programa um job de limpeza que é executado quando o dispositivo está
inativo e carregando.
Guia de migração
Por padrão, essas mudanças afetam apenas apps destinados ao Android 8.0 (nível 26 da API) ou mais recente. No entanto, os usuários podem ativar essas restrições para qualquer app na tela Configurações, mesmo que o app seja destinado a um nível de API anterior ao 26. Talvez seja necessário atualizar o app para estar em conformidade com as novas limitações.
Verifique como seu aplicativo usa os serviços. Se o app depender de serviços que são executados em segundo plano enquanto ele está inativo, será necessário substituí-los. Possíveis soluções incluem:
- Se o app precisar criar um serviço em primeiro plano enquanto estiver
em segundo plano, use o método
startForegroundService()
em vez destartService()
. - Se o serviço for perceptível para o usuário, torne-o um serviço de primeiro plano. Por
exemplo, um serviço que reproduz áudio precisa ser sempre um serviço em primeiro plano.
Crie o serviço usando o método
startForegroundService()
em vez destartService()
. - Encontre uma maneira de duplicar a funcionalidade do serviço com um job programado. Se o serviço não estiver fazendo algo imediatamente perceptível para o usuário, geralmente será possível usar um job programado.
- Use o FCM para ativar o app seletivamente quando eventos de rede ocorrerem, em vez de fazer a pesquisa em segundo plano.
- Adie o trabalho de segundo plano até que o aplicativo esteja naturalmente em primeiro plano.
Revise os broadcast receivers definidos no manifesto do app. Se o manifesto declara um receiver para uma transmissão implícita afetada, substitua-o. Possíveis soluções incluem:
- Crie o receptor no momento da execução chamando
Context.registerReceiver()
, em vez de declarar o receptor no manifesto. - Use um job programado para verificar a condição que teria acionado a transmissão implícita.