Restrições do sistema para trabalho em segundo plano

Os processos em segundo plano podem consumir muita memória e bateria. Por exemplo, uma a transmissão implícita pode iniciar vários processos em segundo plano registrados para ouvi-lo, mesmo que esses processos possam não fazer muito trabalho. Isso pode ter impacto significativo no desempenho do dispositivo e na experiência do usuário.

Para evitar restrições do sistema, use a API certa para seu em segundo plano. A A documentação Visão geral das tarefas em segundo plano ajuda você a escolher a API certa para suas necessidades.

Restrições iniciadas pelo usuário

Se um app apresentar alguns dos maus comportamentos descritos no Android vitals: o sistema solicitará que o usuário restrinja o acesso desse aplicativo aos recursos do sistema.

Se o sistema perceber que um aplicativo está consumindo recursos em excesso, ele notificará o usuário e dá a ele a opção de restringir as ações do aplicativo. Os comportamentos que podem acionar o aviso incluem:

  1. Wake locks em excesso: um wake lock parcial mantido por uma hora quando a tela está desativado
  2. Excesso de serviços em segundo plano: se o app for direcionado a níveis de API anteriores ao 26 e tem muitos serviços em segundo plano

As restrições precisas impostas são determinadas pelo fabricante do dispositivo. Para exemplo, em builds do AOSP, os apps restritos não podem executar jobs, acionar alarmes nem usar na rede, exceto quando o app está em primeiro plano.

Restrições para o recebimento de transmissões de atividade de rede

Os apps não recebem transmissões do CONNECTIVITY_ACTION quando são registrados em no manifesto, e os processos que dependem dessa transmissão não será iniciado. Isso pode causar um problema para apps que querem escutar a rede muda ou executa atividades de rede em massa quando o dispositivo se conecta a uma uma rede ilimitada. Há várias soluções para contornar essa restrição existem no framework do Android, mas escolher o caminho certo depende do que você quer que seu app realize.

Agendar trabalho em conexões ilimitadas

Ao criar um WorkRequest, adicione um NetworkType.UNMETERED Constraint.

fun scheduleWork(context: Context) {
    val workManager = WorkManager.getInstance(context)
    val workRequest = OneTimeWorkRequestBuilder<MyWorker>()
       .setConstraints(
           Constraints.Builder()
               .setRequiredNetworkType(NetworkType.UNMETERED)
               .build()
           )
       .build()

    workManager.enqueue(workRequest)
}

Quando as condições para o trabalho forem atendidas, o app receberá um callback para ser executado O método doWork() na classe Worker especificada.

Monitorar a conectividade de rede enquanto o app está em execução

Os apps em execução ainda podem detectar CONNECTIVITY_CHANGE com uma registrou BroadcastReceiver. No entanto, a API ConnectivityManager fornece um método mais robusto para solicitar um callback somente quando a rede especificada quando as condições são atendidas.

Os objetos NetworkRequest definem os parâmetros do callback de rede em termos de NetworkCapabilities. Você cria objetos NetworkRequest com a classe NetworkRequest.Builder. registerNetworkCallback Em seguida, transmite o objeto NetworkRequest para o sistema. Quando a rede se as condições forem atendidas, o aplicativo receberá um retorno de chamada para executar o método onAvailable() definido na ConnectivityManager.NetworkCallback.

O aplicativo continua a receber callbacks até o aplicativo sair ou chamar unregisterNetworkCallback().

Restrições para o recebimento de transmissões de imagens e vídeos

Os apps não podem enviar nem receber ACTION_NEW_PICTURE ou ACTION_NEW_VIDEO. Essa restrição ajuda a aliviar impactos no desempenho e na experiência do usuário quando vários apps precisam ser ativados para para processar uma nova imagem ou vídeo.

Determinar quais autoridades de conteúdo acionaram trabalhos

O WorkerParameters permite que o app receba informações úteis sobre o que autoridades de conteúdo e URIs acionaram o trabalho:

List<Uri> getTriggeredContentUris()

Retorna uma lista de URIs que acionaram o trabalho. Este campo ficará vazio se nenhum URI acionou o trabalho (por exemplo, o trabalho foi acionado devido a um prazo ou algum outro motivo), ou se o número de URIs alterados for maior que 50.

List<String> getTriggeredContentAuthorities()

Retorna uma lista de strings de autoridades de conteúdo que acionaram o trabalho. Se a lista retornada não estiver vazia, use getTriggeredContentUris() para recuperar os detalhes sobre quais URIs mudaram.

O exemplo de código a seguir substitui o método CoroutineWorker.doWork() e registra as autoridades de conteúdo e os URIs que acionaram o job:

class MyWorker(
    appContext: Context,
    params: WorkerParameters
): CoroutineWorker(appContext, params)
    override suspend fun doWork(): Result {
        StringBuilder().apply {
            append("Media content has changed:\n")
            params.triggeredContentAuthorities
                .takeIf { it.isNotEmpty() }
                ?.let { authorities ->
                    append("Authorities: ${authorities.joinToString(", ")}\n")
                    append(params.triggeredContentUris.joinToString("\n"))
                } ?: append("(No content)")
            Log.i(TAG, toString())
        }
        return Result.success()
    }
}

Testar o app com restrições do sistema

otimizar seus apps para serem executados em dispositivos com pouca memória ou em condições de pouca memória; podem melhorar o desempenho e a experiência do usuário. Como remover dependências em segundo plano e broadcast receivers implícitos registrados no manifesto podem ajudar seu app funcionam melhor nesses dispositivos. É recomendável otimizar o app para ser executado sem o uso desses processos em segundo plano.

Alguns outros comandos do Android Debug Bridge (adb) podem ajudar a testar o app. com esses processos em segundo plano desativados:

  • Para simular condições em que transmissões implícitas e serviços em segundo plano são indisponível, digite este comando:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND ignore

  • Para reativar transmissões implícitas e serviços em segundo plano, digite o seguinte: comando:

    $ adb shell cmd appops set <package_name> RUN_IN_BACKGROUND allow

Otimizar ainda mais seu app

Para conhecer outras boas maneiras de otimizar suas tarefas em segundo plano do seu modelo, consulte Otimizar o uso da bateria para APIs de agendamento de tarefas. na documentação do Google Cloud.