Sempre que um aplicativo é executado em segundo plano, ele consome parte dos recursos limitados do dispositivo, como a RAM. Isso pode resultar em uma experiência reduzida para o usuário, especialmente se ele estiver usando um aplicativo que consuma muitos recursos, como um jogo ou um vídeo. Para aprimorar a experiência do usuário, o Android 8.0 (API de nível 26) restringe o que os aplicativos podem fazer durante a execução em segundo plano. Este documento descreve as mudanças no sistema operacional e como você pode atualizar seu aplicativo para que ele funcione adequadamente com as novas restrições.
Visão geral
Muitos aplicativos e serviços do Android podem ser executados simultaneamente. Por exemplo, um usuário pode jogar em uma janela, navegar na Web em outra e usar um terceiro aplicativo para reproduzir música. Quanto mais aplicativos são executados ao mesmo tempo, maior será a carga para o sistema. Se mais aplicativos ou serviços forem executados em segundo plano, isso deixará o sistema sobrecarregado, o que pode resultar em uma experiência reduzida para o usuário. Por exemplo, o aplicativo de música pode ser desligado repentinamente.
Para diminuir a chance desses problemas, o Android 8.0 estabelece restrições sobre o que os aplicativos podem fazer enquanto os usuários não estão interagindo diretamente com eles. Os aplicativos são limitados de duas maneiras:
Restrições de serviços em segundo plano: enquanto um aplicativo está ocioso, há limites para o uso dos serviços em segundo plano. Isso não se aplica aos serviços em primeiro plano, que são mais evidentes para o usuário.
Restrições de transmissão: com exceções limitadas, os aplicativos não podem usar os manifestos para registrar-se em transmissões implícitas. Os aplicativos ainda poderão se registrar para essas transmissões no tempo de execução e usar o manifesto para registro em transmissões explícitas direcionadas especificamente a eles.
Na maioria dos casos, os aplicativos podem contornar essas restrições usando jobs JobScheduler
. Essa abordagem permite que um aplicativo
realize atividades quando ele não está sendo executado ativamente, mas ainda dá ao sistema
liberdade para programar esses jobs de uma forma que não afete a experiência
do usuário. O Android 8.0 oferece diversas melhorias para JobScheduler
que facilitam a substituição de serviços e
broadcast receivers com jobs programados. Para saber mais, consulte
Melhorias no JobScheduler.
Restrições de serviços em segundo plano
Os serviços executados em segundo plano podem consumir recursos do dispositivo, gerando uma experiência ruim para o usuário. Para mitigar esse problema, o sistema aplica diversas restrições aos serviços.
O sistema distingue entre aplicativos de primeiro plano e de segundo plano. A definição de segundo plano para fins de restrições de serviço é diferente da definição usada pelo gerenciamento de memória. Um aplicativo pode estar no segundo plano em termos de gerenciamento de memória, mas em primeiro plano em termos da capacidade de iniciar serviços. Um aplicativo será considerado como estando em primeiro plano se qualquer uma das condições a seguir for verdadeira:
- Ele tem uma atividade visível, independentemente de ela estar em andamento ou pausada.
- Ele tem um serviço de primeiro plano.
- Outro aplicativo está conectado a ele, seja por vinculação de um
dos serviços ou pelo uso de um dos provedores de conteúdo. Por exemplo,
o aplicativo estará em primeiro plano se outro aplicativo se vincular ao:
- IME
- Serviço de plano de fundo
- Detector de notificações
- Serviço de voz ou texto
Se nenhuma dessas condições for verdadeira, o aplicativo será considerado como estando em segundo plano.
Observação: essas regras não afetam os serviços vinculados. Se o aplicativo definir um serviço vinculado, outros componentes poderão ser vinculados a esse serviço, independentemente do seu aplicativo estar ou não em primeiro plano.
Enquanto um aplicativo está em primeiro plano, ele pode criar e executar serviços de primeiro
e segundo plano livremente. Quando um aplicativo passa para o segundo plano, ele tem
uma janela de vários minutos em que ainda tem permissão para criar e usar
serviços. No final dessa janela, o aplicativo é considerado como ocioso. No
momento, o sistema interrompe os serviços em segundo plano do aplicativo, como se ele
tivesse chamado os métodos Service.stopSelf()
dos serviços.
Em certas circunstâncias, um aplicativo de segundo plano é colocado em uma lista de permissões temporária por alguns minutos. Enquanto estiver nessa lista, ele poderá iniciar serviços sem restrições, e os serviços em segundo plano poderão ser executados. Um aplicativo é colocado na lista de permissões quando ele gerencia uma tarefa visível para o usuário, por exemplo:
- Gerenciar uma mensagem do Firebase Cloud Messaging (FCM) de alta prioridade.
- Receber uma transmissão, como uma mensagem SMS/MMS.
- Executar um
PendingIntent
de uma notificação. - Iniciar um
VpnService
antes que o aplicativo VPN se promova para o primeiro plano.
Observação:
IntentService
é um serviço e, por isso, está sujeito
às novas restrições dos serviços em segundo plano. Como resultado, muitos aplicativos que dependem de
IntentService
não funcionam corretamente quando direcionados para o Android
8.0 ou superior. Por esse
motivo, o Android
Support Library 26.0.0 apresenta uma nova classe
JobIntentService
, que oferece
a mesma funcionalidade de IntentService
, mas usa jobs em vez de
serviços ao executar o Android 8.0 ou superior.
Em muitos casos, seu aplicativo pode substituir 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 aplicativo não esteja
em execução no primeiro plano. Anteriormente, o aplicativo usava um serviço em segundo plano, que
verificava o armazenamento em nuvem do aplicativo. Para migrar para o Android 8.0 (nível de API 26),
o desenvolvedor substitui o serviço em segundo plano por um job programado, que é
iniciado periodicamente, consulta o servidor e é desativado.
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 ao primeiro plano.
Com o Android 8.0, há um problema: o sistema não permite que um aplicativo
em segundo plano crie um serviço desse tipo. Por esse motivo, o Android 8.0 introduz
o novo método startForegroundService()
para iniciar um novo serviço no
primeiro plano. Depois que o sistema criar o
serviço, o aplicativo tem cinco segundos para chamar o método startForeground()
do serviço para mostrar a nova
notificação visível ao usuário do serviço. Se o aplicativo não chamar startForeground()
dentro do
limite de tempo, o sistema interromperá o serviço e declarará que o aplicativo está
ANR.
Restrições de transmissão
Se um aplicativo se registra para receber transmissões, o receptor do aplicativo consome recursos sempre que a transmissão é enviada. Isso pode causar problemas se muitos aplicativos se registraram 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 aplicativos consumam recursos rapidamente, prejudicando a experiência do usuário. Para mitigar esse problema, o Android 7.0 (API de nível 24) estabeleceu restrições para transmissões, conforme descrito em Otimização do segundo plano. O Android 8.0 (API de nível 26) torna essas limitações mais rigorosas.
- Os aplicativos direcionados ao Android 8.0 ou superior não podem mais registrar
broadcast receivers para
transmissões implícitas nos manifestos. Uma transmissão implícita é aquela
que não é direcionada especificamente ao aplicativo. Por exemplo, o
ACTION_PACKAGE_REPLACED
é uma transmissão implícita, pois ele é enviado a todos os detectores registrados, informando que alguns pacotes no dispositivo foram substituídos. Entretanto, oACTION_MY_PACKAGE_REPLACED
não é uma transmissão implícita porque ele é enviado somente ao aplicativo cujo pacote foi substituído, não importando quantos outros aplicativos tenham detectores registrados para a transmissão em questão. - Os aplicativos podem continuar a se registrar para transmissões explícitas nos manifestos.
- Os aplicativos podem usar o
Context.registerReceiver()
no tempo de execução para registrar um receptor para qualquer transmissão, seja ela implícita ou explícita. - Essas restrições não se aplicam a transmissões que exigem uma permissão de assinatura, já que elas são enviadas somente para aplicativos assinados com o mesmo certificado, não para todos os aplicativos no dispositivo.
Em muitos casos, aplicativos que foram anteriormente registrados para uma transmissão implícita podem
aplicar uma funcionalidade semelhante ao usar um job JobScheduler
.
Por exemplo, um aplicativo social de fotos pode precisar limpar os dados de
tempos em tempos e preferir fazer isso quando o dispositivo estiver conectado a um carregador.
Anteriormente, o aplicativo registrava um receptor para ACTION_POWER_CONNECTED
no manifesto. Quando o aplicativo
recebia essa transmissão, ele verificava se a limpeza era necessária. Na
migração para o Android 8.0 ou superior, o aplicativo remove esse receptor do
manifesto. Em vez disso, ele programa um job de limpeza que é executado quando o dispositivo está
ocioso e sendo carregado.
Guia de migração
Por padrão, essas alterações se aplicam somente a aplicativos que segmentam o Android 8.0 (API de nível 26) ou superior. No entanto, os usuários podem ativar essas restrições para qualquer aplicativo na tela Configurações, mesmo que o aplicativo seja direcionado a um nível de API menor que 26. Talvez você precise atualizar o aplicativo para atender às novas limitações.
Verifique como seu aplicativo usa os serviços. Caso seu aplicativo utilize serviços que são executados em segundo plano enquanto ele está ocioso, será preciso substituí-los. Possíveis soluções incluem:
- Caso o aplicativo precise criar um serviço em primeiro plano enquanto está
em segundo plano, use o método
startForegroundService()
em vez destartService()
. - Caso o serviço seja perceptível para o usuário, torne-o um serviço em primeiro plano. Por
exemplo, um serviço que reproduz áudio deve ser sempre em primeiro plano.
Crie o serviço usando o método
startForegroundService()
em vez destartService()
. - Encontre uma forma de duplicar a funcionalidade do serviço com um job programado. Se o serviço não estiver fazendo algo que possa ser percebido de imediato pelo usuário, em geral será possível usar um job programado.
- Use o FCM para ativar seu aplicativo seletivamente quando ocorrerem eventos de rede em vez de realizar pesquisas no segundo plano.
- Adie o trabalho em segundo plano até que o aplicativo esteja naturalmente em primeiro plano.
Analise os broadcast receivers definidos no manifesto do seu aplicativo. Caso seu manifesto declare um receptor para uma transmissão implícita, você precisará substituí-lo. Possíveis soluções incluem:
- Crie o receptor no tempo de execução chamando
Context.registerReceiver()
em vez de declarar o receptor no manifesto. - Use um job programado para verificar a condição que acionaria a transmissão implícita.