Sempre que um app é executado em segundo plano, ele consome alguns dos recursos limitados do dispositivo, como a RAM. Isso pode resultar em uma experiência do usuário prejudicada, especialmente se o usuário 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 sobre o que os apps podem fazer durante a execução em segundo plano. Este documento descreve as mudanças no sistema operacional e como você pode atualizar seu app para que ele funcione bem com as novas limitações.
Informações gerais
Muitos aplicativos e serviços do Android podem ser executados simultaneamente. Por exemplo, um usuário pode jogar em uma janela enquanto navega na Web em outra e usar um terceiro app para tocar música. Quanto mais aplicativos são executados ao mesmo tempo, mais carga é colocada no sistema. Se outros apps ou serviços estiverem em execução em segundo plano, isso sobrecarregará o sistema, o que pode resultar em uma experiência ruim para o usuário. Por exemplo, o app de música pode ser desligado de repente.
Para reduzir a chance desses problemas, o Android 8.0 estabelece limitações sobre o 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ço em segundo plano: enquanto um app está inativo, há limites para o uso de serviços em segundo plano. Isso não se aplica aos serviços em primeiro plano, que são mais perceptíveis pelo usuário.
Limitações de transmissão: com exceções limitadas, os apps não podem usar o manifesto para se registrar em transmissões implícitas. Eles ainda podem se registrar para essas transmissões no momento da execução e usar o manifesto para registrar-se em transmissões explícitas e direcionadas especificamente ao app.
Na maioria dos casos, os apps podem contornar essas limitações usando
jobs de JobScheduler
. Essa abordagem permite que um app
realize o trabalho quando não estiver em execução ativamente, mas ainda dá ao sistema
liberdade para programar esses jobs de uma maneira que não afete a experiência
do usuário. O Android 8.0 oferece várias melhorias para o 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 executados em segundo plano podem consumir recursos do dispositivo, possivelmente resultando em uma experiência pior para o usuário. Para atenuar esse problema, o sistema aplica várias limitações aos serviços.
O sistema distingue entre apps em primeiro plano e em 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 no que diz respeito ao gerenciamento de memória, mas está em primeiro plano no que diz respeito à 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 a ele, seja vinculado a um dos
serviços dele ou usando um dos provedores de conteúdo. Por exemplo,
o app vai estar em primeiro plano se outro app se vincular ao seguinte:
- 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 e
segundo plano livremente. Quando um app entra em segundo plano, ele tem uma
janela de vários minutos em que ainda tem permissão para criar e usar
serviços. No final da janela, 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 visível para o usuário, por exemplo:
- Processamento de uma mensagem do Firebase Cloud Messaging (FCM) de alta prioridade.
- Receber uma transmissão, como uma mensagem SMS/MMS.
- Executar um
PendingIntent
em uma notificação. - Iniciar uma
VpnService
antes de o app de VPN se promover para o primeiro plano.
Em muitos casos, seu app pode substituir serviços em segundo plano por jobs do 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 normal de criar um serviço em primeiro plano
era criar um serviço em segundo plano e promovê-lo para o primeiro plano.
No Android 8.0, há um problema: 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 introduz
o novo método startForegroundService()
para iniciar um novo serviço em
primeiro plano. Depois que o sistema criar
o serviço, o app terá cinco segundos para chamar o método [startForeground()
](/reference/android/app/Service#startForeground(int, android.app.Notification) do serviço para mostrar a
notificação visível ao usuário do novo serviço. Se o app não chamar startForeground()
dentro do
limite de tempo, o sistema interromperá o serviço e declarará o app como
ANR.
Limitações da transmissão
Se um app se registrar para receber transmissões, o receptor dele 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 sucessão, prejudicando a experiência do usuário. Para atenuar esse problema, o Android 7.0 (nível 24 da API) colocou limitações em 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.
- Apps direcionados ao Android 8.0 ou versões mais recentes não podem mais registrar broadcast
receivers para transmissões implícitas no manifesto, a menos que a transmissão seja
restrita especificamente a esse app. Uma transmissão implícita é uma
transmissão que não tem como alvo um componente específico em um app. Por
exemplo,
ACTION_PACKAGE_REPLACED
é enviada a todos os listeners registrados em todos os apps, informando que algum pacote no dispositivo foi substituído. Como a transmissão é implícita, ela não será entregue a receptores registrados pelo manifesto em apps direcionados ao Android 8.0 ou versões mais recentes. AACTION_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 pelo manifesto. - Aplicativos podem continuar a se registrar para transmissões explícitas em seus manifestos.
- Os apps podem usar o
Context.registerReceiver()
durante a 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 estão isentas dessa restrição, já que elas são enviadas apenas para apps assinados com o mesmo certificado, não para todos os apps no dispositivo.
Em muitos casos, os apps que foram registrados anteriormente para uma transmissão implícita podem
receber uma funcionalidade semelhante usando um job JobScheduler
.
Por exemplo, um app social de fotos 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 receptor para ACTION_POWER_CONNECTED
no manifesto. Quando o app
recebeva essa transmissão, ele verificava se a limpeza era necessária. Ao
migrar para o Android 8.0 ou versões mais recentes, o app remove esse receptor do
manifesto. 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 versões mais recentes. No entanto, os usuários podem ativar essas restrições para qualquer app na tela Configurações, mesmo que o app seja direcionado a um nível de API anterior ao 26. Talvez seja necessário atualizar o app para atender às novas limitações.
Verifique como seu aplicativo usa os serviços. Se seu app depender de serviços que são executados em segundo plano enquanto ele está ocioso, será necessário substituí-los. Possíveis soluções incluem:
- Caso seu app precise 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 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 é possível usar um job programado.
- Use o FCM para ativar seu aplicativo seletivamente quando ocorrerem eventos de rede, em vez de realizar pesquisas 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 declarar um receptor para uma transmissão implícita afetada, ele precisa ser substituído. Possíveis soluções incluem:
- Crie o receptor no momento da execução chamando
Context.registerReceiver()
, em vez de declará-lo no manifesto. - Use um job programado para verificar a condição que acionaria a transmissão implícita.