Agendador de trabalhos do Android
Este guia discute como agendar o trabalho em segundo plano usando a API do Agendador de Trabalho android, que está disponível em dispositivos Android que executam o Android 5.0 (nível de API 21) e superior.
Visão geral
Uma das melhores maneiras de manter um aplicativo Android responsivo ao usuário é garantir que o trabalho complexo ou de execução longa seja executado em segundo plano. No entanto, é importante que o trabalho em segundo plano não afete negativamente a experiência do usuário com o dispositivo.
Por exemplo, um trabalho em segundo plano pode sondar um site a cada três ou quatro minutos para consultar alterações em um conjunto de dados específico. Isso parece benigno, no entanto, teria um impacto desastroso na duração da bateria. O aplicativo ativará repetidamente o dispositivo, elevará a CPU para um estado de energia mais alto, ligará os rádios, fará as solicitações de rede e, em seguida, processará os resultados. Ele fica pior porque o dispositivo não desligará imediatamente e retornará ao estado ocioso de baixa potência. O trabalho em segundo plano mal agendado pode inadvertidamente manter o dispositivo em um estado com requisitos de energia desnecessários e excessivos. Essa atividade aparentemente inocente (sondar um site) tornará o dispositivo inutilizável em um período relativamente curto de tempo.
O Android fornece as SEGUINTEs APIs para ajudar na execução do trabalho em segundo plano, mas por si só elas não são suficientes para agendamento de trabalho inteligente.
- Serviços de Intenção – os Serviços de Intenção são ótimos para executar o trabalho, no entanto, eles não fornecem nenhuma maneira de agendar o trabalho.
- AlarmManager – essas APIs só permitem que o trabalho seja agendado, mas não fornecem nenhuma maneira de realmente executar o trabalho. Além disso, o AlarmManager só permite restrições baseadas em tempo, o que significa gerar um alarme em um determinado momento ou após um determinado período de tempo ter decorrido.
- Receptores de Difusão – um aplicativo Android pode configurar receptores de transmissão para executar o trabalho em resposta a eventos ou Intenções em todo o sistema. No entanto, os receptores de transmissão não fornecem nenhum controle sobre quando o trabalho deve ser executado. Também as alterações no sistema operacional Android restringirão quando os receptores de transmissão funcionarem ou os tipos de trabalho aos quais eles podem responder.
Há dois recursos importantes para executar com eficiência o trabalho em segundo plano (às vezes chamado de trabalho em segundo plano ou trabalho):
- Agendamento inteligente do trabalho – é importante que, quando um aplicativo está fazendo um trabalho em segundo plano, ele o faça como um bom cidadão. O ideal é que o aplicativo não exija que um trabalho seja executado. Em vez disso, o aplicativo deve especificar condições que devem ser atendidas para quando o trabalho pode ser executado e, em seguida, agendar esse trabalho com o sistema operacional que executará o trabalho quando as condições forem atendidas. Isso permite que o Android execute o trabalho para garantir a máxima eficiência no dispositivo. Por exemplo, as solicitações de rede podem ser executadas em lote para serem executadas ao mesmo tempo para fazer uso máximo da sobrecarga envolvida com a rede.
- Encapsulando o trabalho – o código para executar o trabalho em segundo plano deve ser encapsulado em um componente discreto que pode ser executado independentemente da interface do usuário e será relativamente fácil de reagendar se o trabalho não for concluído por algum motivo.
O Agendador de Trabalhos do Android é uma estrutura interna do sistema operacional Android que fornece uma API fluente para simplificar o agendamento de trabalho em segundo plano. O Agendador de Trabalhos do Android consiste nos seguintes tipos:
- O
Android.App.Job.JobScheduler
é um serviço do sistema usado para agendar, executar e, se necessário, cancelar trabalhos em nome de um aplicativo Android. - Uma
Android.App.Job.JobService
é uma classe abstrata que deve ser estendida com a lógica que executará o trabalho no thread main do aplicativo. Isso significa que oJobService
é responsável por como o trabalho deve ser executado de forma assíncrona. - Um
Android.App.Job.JobInfo
objeto contém os critérios para orientar o Android quando o trabalho deve ser executado.
Para agendar o trabalho com o Agendador de Trabalho do Android, um aplicativo Xamarin.Android deve encapsular o código em uma classe que estende a JobService
classe. JobService
tem três métodos de ciclo de vida que podem ser chamados durante o tempo de vida do trabalho:
bool OnStartJob(parâmetros JobParameters) – esse método é chamado pelo para executar o
JobScheduler
trabalho e é executado no thread main do aplicativo. É responsabilidade doJobService
executar o trabalho de forma assíncrona e retornartrue
se houver trabalho restante oufalse
se o trabalho for feito.Quando o
JobScheduler
chamar esse método, ele solicitará e reterá um wakelock do Android durante o trabalho. Quando o trabalho for concluído, é responsabilidade doJobService
informar oJobScheduler
fato por meio da chamada do método (descrito aJobFinished
seguir).JobFinished(Parâmetros JobParameters, bool needsReschedule) – Esse método deve ser chamado pelo
JobService
para informarJobScheduler
que o trabalho foi feito. SeJobFinished
não for chamado, oJobScheduler
não removerá o wakelock, causando esvaziamento desnecessário da bateria.bool OnStopJob(parâmetros JobParameters) – isso é chamado quando o trabalho é interrompido prematuramente pelo Android. Ele deverá retornar
true
se o trabalho deve ser reagendado com base nos critérios de repetição (discutidos abaixo com mais detalhes).
É possível especificar restrições ou gatilhos que controlarão quando um trabalho pode ou deve ser executado. Por exemplo, é possível restringir um trabalho para que ele só seja executado quando o dispositivo estiver carregando ou para iniciar um trabalho quando uma imagem for tirada.
Este guia discutirá detalhadamente como implementar uma JobService
classe e agendá-la com o JobScheduler
.
Requisitos
O Agendador de Trabalhos do Android requer o nível 21 da API do Android (Android 5.0) ou superior.
Usando o Agendador de Trabalhos do Android
Há três etapas para usar a API JobScheduler do Android:
- Implemente um tipo JobService para encapsular o trabalho.
- Use um
JobInfo.Builder
objeto para criar oJobInfo
objeto que manterá os critérios para oJobScheduler
executar o trabalho. - Agende o trabalho usando
JobScheduler.Schedule
.
Implementar um JobService
Todo o trabalho executado pela biblioteca do Agendador de Trabalhos do Android deve ser feito em um tipo que estenda a Android.App.Job.JobService
classe abstrata. A criação de um JobService
é muito semelhante à criação de um Service
com a estrutura do Android:
- Estenda a
JobService
classe . - Decore a subclasse com o
ServiceAttribute
e defina oName
parâmetro como uma cadeia de caracteres composta pelo nome do pacote e pelo nome da classe (consulte o exemplo a seguir). - Defina a
Permission
propriedade noServiceAttribute
para a cadeia de caracteresandroid.permission.BIND_JOB_SERVICE
. - Substitua o
OnStartJob
método , adicionando o código para executar o trabalho. O Android invocará esse método no thread main do aplicativo para executar o trabalho. Trabalho que levará mais tempo para que alguns milissegundos sejam executados em um thread para evitar o bloqueio do aplicativo. - Quando o trabalho é feito, o
JobService
deve chamar oJobFinished
método . Esse método é comoJobService
informa que oJobScheduler
trabalho é feito. A falha na chamadaJobFinished
resultará naJobService
colocação de demandas desnecessárias no dispositivo, reduzindo a duração da bateria. - É uma boa ideia também substituir o
OnStopJob
método . Esse método é chamado pelo Android quando o trabalho está sendo desligado antes de ser concluído e oferece aJobService
oportunidade de descartar corretamente todos os recursos. Esse método deverá retornartrue
se for necessário reagendar o trabalho oufalse
se não for desejável executar novamente o trabalho.
O código a seguir é um exemplo do mais simples JobService
para um aplicativo, usando o TPL para executar de forma assíncrona algum trabalho:
[Service(Name = "com.xamarin.samples.downloadscheduler.DownloadJob",
Permission = "android.permission.BIND_JOB_SERVICE")]
public class DownloadJob : JobService
{
public override bool OnStartJob(JobParameters jobParams)
{
Task.Run(() =>
{
// Work is happening asynchronously
// Have to tell the JobScheduler the work is done.
JobFinished(jobParams, false);
});
// Return true because of the asynchronous work
return true;
}
public override bool OnStopJob(JobParameters jobParams)
{
// we don't want to reschedule the job if it is stopped or cancelled.
return false;
}
}
Criando um JobInfo para agendar um trabalho
Os aplicativos Xamarin.Android não instanciam um JobService
diretamente, em vez disso, passarão um JobInfo
objeto para o JobScheduler
. O JobScheduler
criará uma instância do objeto solicitado JobService
, agendando e executando o JobService
de acordo com os metadados no JobInfo
. Um JobInfo
objeto deve conter as seguintes informações:
- JobId – esse é um
int
valor usado para identificar um trabalho para oJobScheduler
. Reutilizá-lo atualizará todos os trabalhos existentes. O valor deve ser exclusivo para o aplicativo. - JobService – esse parâmetro é um
ComponentName
que identifica explicitamente o tipo que oJobScheduler
deve usar para executar um trabalho.
Este método de extensão demonstra como criar um com um JobInfo.Builder
Android Context
, como uma Atividade:
public static class JobSchedulerHelpers
{
public static JobInfo.Builder CreateJobBuilderUsingJobId<T>(this Context context, int jobId) where T:JobService
{
var javaClass = Java.Lang.Class.FromType(typeof(T));
var componentName = new ComponentName(context, javaClass);
return new JobInfo.Builder(jobId, componentName);
}
}
// Sample usage - creates a JobBuilder for a DownloadJob and sets the Job ID to 1.
var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1);
var jobInfo = jobBuilder.Build(); // creates a JobInfo object.
Um recurso avançado do Agendador de Trabalhos do Android é a capacidade de controlar quando um trabalho é executado ou em quais condições um trabalho pode ser executado. A tabela a seguir descreve alguns dos métodos em JobInfo.Builder
que permitem que um aplicativo influencie quando um trabalho pode ser executado:
Método | Descrição |
---|---|
SetMinimumLatency |
Especifica que um atraso (em milissegundos) que deve ser observado antes de um trabalho ser executado. |
SetOverridingDeadline |
Declara que o trabalho deve ser executado antes dessa vez (em milissegundos) ter decorrido. |
SetRequiredNetworkType |
Especifica os requisitos de rede para um trabalho. |
SetRequiresBatteryNotLow |
O trabalho só poderá ser executado quando o dispositivo não estiver exibindo um aviso de "bateria baixa" para o usuário. |
SetRequiresCharging |
O trabalho só pode ser executado quando a bateria está carregando. |
SetDeviceIdle |
O trabalho será executado quando o dispositivo estiver ocupado. |
SetPeriodic |
Especifica que o trabalho deve ser executado regularmente. |
SetPersisted |
O trabalho deve perisistá-lo entre reinicializações de dispositivo. |
O SetBackoffCriteria
fornece algumas diretrizes sobre quanto tempo o JobScheduler
deve esperar antes de tentar executar um trabalho novamente. Há duas partes para os critérios de retirada: um atraso em milissegundos (valor padrão de 30 segundos) e um tipo de retirada que deve ser usado (às vezes chamado de política de retirada ou política de repetição). As duas políticas são encapsuladas na Android.App.Job.BackoffPolicy
enumeração :
BackoffPolicy.Exponential
– Uma política de retirada exponencial aumentará o valor de retirada inicial exponencialmente após cada falha. Na primeira vez que um trabalho falhar, a biblioteca aguardará o intervalo inicial especificado antes de reagendar o trabalho – exemplo, 30 segundos. Na segunda vez que o trabalho falhar, a biblioteca aguardará pelo menos 60 segundos antes de tentar executar o trabalho. Após a terceira tentativa com falha, a biblioteca aguardará 120 segundos e assim por diante. Esse é o valor padrão.BackoffPolicy.Linear
– Essa estratégia é uma retirada linear que o trabalho deve ser reagendado para ser executado em intervalos definidos (até que seja bem-sucedido). A retirada linear é mais adequada para o trabalho que deve ser concluído o mais rápido possível ou para problemas que rapidamente se resolve.
Para obter mais detalhes sobre como criar um JobInfo
objeto, leia a documentação do Google para a JobInfo.Builder
classe .
Passando parâmetros para um trabalho por meio do JobInfo
Os parâmetros são passados para um trabalho criando um PersistableBundle
que é passado junto com o Job.Builder.SetExtras
método :
var jobParameters = new PersistableBundle();
jobParameters.PutInt("LoopCount", 11);
var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1)
.SetExtras(jobParameters)
.Build();
O PersistableBundle
é acessado da Android.App.Job.JobParameters.Extras
propriedade no OnStartJob
método de um JobService
:
public override bool OnStartJob(JobParameters jobParameters)
{
var loopCount = jobParams.Extras.GetInt("LoopCount", 10);
// rest of code omitted
}
Agendando um trabalho
Para agendar um trabalho, um aplicativo Xamarin.Android obterá uma referência ao serviço do JobScheduler
sistema e chamará o JobScheduler.Schedule
método com o JobInfo
objeto que foi criado na etapa anterior. JobScheduler.Schedule
retornará imediatamente com um dos dois valores inteiros:
- JobScheduler.ResultSuccess – O trabalho foi agendado com êxito.
- JobScheduler.ResultFailure – O trabalho não pôde ser agendado. Normalmente, isso é causado por parâmetros conflitantes
JobInfo
.
Esse código é um exemplo de agendamento de um trabalho e notificar o usuário sobre os resultados da tentativa de agendamento:
var jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
var scheduleResult = jobScheduler.Schedule(jobInfo);
if (JobScheduler.ResultSuccess == scheduleResult)
{
var snackBar = Snackbar.Make(FindViewById(Android.Resource.Id.Content), Resource.String.jobscheduled_success, Snackbar.LengthShort);
snackBar.Show();
}
else
{
var snackBar = Snackbar.Make(FindViewById(Android.Resource.Id.Content), Resource.String.jobscheduled_failure, Snackbar.LengthShort);
snackBar.Show();
}
Cancelando um trabalho
É possível cancelar todos os trabalhos que foram agendados ou apenas um único trabalho usando o JobsScheduler.CancelAll()
método ou o JobScheduler.Cancel(jobId)
método :
// Cancel all jobs
jobScheduler.CancelAll();
// to cancel a job with jobID = 1
jobScheduler.Cancel(1)
Resumo
Este guia discutiu como usar o Agendador de Trabalho do Android para executar o trabalho de forma inteligente em segundo plano. Ele discutiu como encapsular o trabalho a ser executado como um JobService
e como usar o JobScheduler
para agendar esse trabalho, especificando os critérios com um JobTrigger
e como as falhas devem ser tratadas com um RetryStrategy
.