Utilità di pianificazione di processo Android
Questa guida illustra come pianificare il lavoro in background usando l'API Dell'utilità di pianificazione processi Android, disponibile nei dispositivi Android che eseguono Android 5.0 (livello API 21) e versioni successive.
Panoramica
Uno dei modi migliori per mantenere reattiva un'applicazione Android all'utente consiste nel garantire che il lavoro complesso o a esecuzione prolungata venga eseguito in background. Tuttavia, è importante che il lavoro in background non influisca negativamente sull'esperienza dell'utente con il dispositivo.
Ad esempio, un processo in background potrebbe eseguire il polling di un sito Web ogni tre o quattro minuti per eseguire una query per le modifiche apportate a un determinato set di dati. Questo sembra benigno, tuttavia avrebbe un impatto disastroso sulla durata della batteria. L'applicazione riattiva ripetutamente il dispositivo, eleva la CPU a uno stato di alimentazione superiore, accende le radio, effettua le richieste di rete e quindi elabora i risultati. Peggiora perché il dispositivo non si spegne immediatamente e torna allo stato di inattività a basso consumo. Il lavoro in background pianificato in modo non adeguato può inavvertitamente mantenere il dispositivo in uno stato con requisiti di alimentazione non necessari ed eccessivi. Questa attività apparentemente innocente (polling di un sito Web) rende il dispositivo inutilizzabile in un periodo di tempo relativamente breve.
Android fornisce le API seguenti per facilitare l'esecuzione del lavoro in background, ma da soli non sono sufficienti per la pianificazione intelligente dei processi.
- Servizi finalità: i servizi finalità sono ideali per l'esecuzione del lavoro, ma non consentono di pianificare il lavoro.
- AlarmManager : queste API consentono solo di pianificare il lavoro, ma non consentono di eseguire effettivamente il lavoro. Inoltre, AlarmManager consente solo vincoli basati sul tempo, il che significa generare un allarme in un determinato momento o dopo un determinato periodo di tempo è trascorso.
- Ricevitori di trasmissione: un'app Android può configurare ricevitori di trasmissione per eseguire operazioni in risposta a eventi o finalità a livello di sistema. Tuttavia, i ricevitori di trasmissione non forniscono alcun controllo su quando deve essere eseguito il processo. Inoltre, le modifiche apportate al sistema operativo Android limiteranno quando i ricevitori di trasmissione funzioneranno o i tipi di lavoro a cui possono rispondere.
Esistono due funzionalità chiave per eseguire in modo efficiente il lavoro in background (talvolta definito processo in background o processo):
- Pianificazione intelligente del lavoro : è importante che quando un'applicazione esegue il lavoro in background che lo fa come un buon cittadino. Idealmente, l'applicazione non deve richiedere l'esecuzione di un processo. L'applicazione deve invece specificare le condizioni che devono essere soddisfatte per quando il processo può essere eseguito e quindi pianificare il processo con il sistema operativo che eseguirà il lavoro quando vengono soddisfatte le condizioni. In questo modo Android può eseguire il processo per garantire la massima efficienza nel dispositivo. Ad esempio, le richieste di rete possono essere raggruppate per l'esecuzione contemporaneamente per sfruttare al massimo il sovraccarico necessario per la rete.
- Incapsulamento del lavoro : il codice per eseguire il lavoro in background deve essere incapsulato in un componente discreto che può essere eseguito indipendentemente dall'interfaccia utente e sarà relativamente facile da riprogrammare se il lavoro non viene completato per qualche motivo.
L'Utilità di pianificazione processi Android è un framework integrato nel sistema operativo Android che fornisce un'API Fluent per semplificare la pianificazione del lavoro in background. L'Utilità di pianificazione processi Android è costituita dai tipi seguenti:
Android.App.Job.JobScheduler
è un servizio di sistema usato per pianificare, eseguire e, se necessario, annullare i processi per conto di un'applicazione Android.- È
Android.App.Job.JobService
una classe astratta che deve essere estesa con la logica che eseguirà il processo nel thread principale dell'applicazione. Ciò significa che èJobService
responsabile del modo in cui il lavoro deve essere eseguito in modo asincrono. - Un
Android.App.Job.JobInfo
oggetto contiene i criteri per guidare Android quando il processo deve essere eseguito.
Per pianificare l'uso dell'Utilità di pianificazione processi Android, un'applicazione Xamarin.Android deve incapsulare il codice in una classe che estende la JobService
classe . JobService
ha tre metodi del ciclo di vita che possono essere chiamati durante la durata del processo:
bool OnStartJob(Parametri JobParameters): questo metodo viene chiamato da
JobScheduler
per eseguire il lavoro ed eseguito sul thread principale dell'applicazione. È responsabilità dell'utenteJobService
eseguire in modo asincrono il lavoro e restituiretrue
se è presente un lavoro rimanente ofalse
se il lavoro viene eseguito.Quando chiama
JobScheduler
questo metodo, richiederà e manterrà un wakelock da Android per la durata del processo. Al termine del processo, è responsabilità dell'utenteJobService
indicare questoJobScheduler
fatto chiamando ilJobFinished
metodo (descritto di seguito).JobFinished(Parametri JobParameters, bool needsReschedule): questo metodo deve essere chiamato da
JobService
per indicareJobScheduler
che il lavoro è stato eseguito. SeJobFinished
non viene chiamato, ilJobScheduler
non rimuoverà il wakelock, causando inutili scaricamento della batteria.bool OnStopJob(Parametri JobParameters): viene chiamato quando il processo viene arrestato prematuramente da Android. Deve restituire
true
se il processo deve essere riprogrammato in base ai criteri di ripetizione dei tentativi (descritti di seguito in modo più dettagliato).
È possibile specificare vincoli o trigger che controllano quando un processo può o deve essere eseguito. Ad esempio, è possibile vincolare un processo in modo che venga eseguito solo quando il dispositivo viene ricaricato o per avviare un processo quando viene scattata un'immagine.
Questa guida illustra in dettaglio come implementare una JobService
classe e pianificarla con .JobScheduler
Requisiti
L'Utilità di pianificazione processi Android richiede il livello API Android 21 (Android 5.0) o versione successiva.
Uso dell'utilità di pianificazione dei processi Android
Esistono tre passaggi per l'uso dell'API JobScheduler Android:
- Implementare un tipo JobService per incapsulare il lavoro.
- Utilizzare un
JobInfo.Builder
oggetto per creare l'oggettoJobInfo
che conterrà i criteri per l'esecuzioneJobScheduler
del processo. - Pianificare il processo usando
JobScheduler.Schedule
.
Implementare un jobService
Tutte le operazioni eseguite dalla libreria dell'Utilità di pianificazione processi Android devono essere eseguite in un tipo che estende la Android.App.Job.JobService
classe astratta. La creazione di un JobService
oggetto è molto simile alla creazione di un Service
con il framework Android:
- Estendere la classe
JobService
. - Decorare la sottoclasse con
ServiceAttribute
e impostare ilName
parametro su una stringa costituita dal nome del pacchetto e dal nome della classe (vedere l'esempio seguente). - Impostare la
Permission
proprietà sull'oggettoServiceAttribute
sulla stringaandroid.permission.BIND_JOB_SERVICE
. - Eseguire l'override del
OnStartJob
metodo aggiungendo il codice per eseguire il lavoro. Android richiamerà questo metodo sul thread principale dell'applicazione per eseguire il processo. Il lavoro che richiederà più tempo per alcuni millisecondi deve essere eseguito su un thread per evitare di bloccare l'applicazione. - Al termine del lavoro, deve
JobService
chiamare ilJobFinished
metodo . Questo metodo indicaJobService
che ilJobScheduler
lavoro viene eseguito. La mancata chiamataJobFinished
comporterà l'inserimentoJobService
di richieste non necessarie sul dispositivo, riducendo la durata della batteria. - È consigliabile eseguire anche l'override del
OnStopJob
metodo . Questo metodo viene chiamato da Android quando il processo viene arrestato prima del completamento e offre laJobService
possibilità di eliminare correttamente le risorse. Questo metodo deve restituiretrue
se è necessario riprogrammare il processo ofalse
se non è consigliabile eseguire nuovamente il processo.
Il codice seguente è un esempio del più semplice JobService
per un'applicazione, usando il TPL per eseguire in modo asincrono alcune operazioni:
[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;
}
}
Creazione di un elemento JobInfo per pianificare un processo
Le applicazioni Xamarin.Android non creano un'istanza diretta di , JobService
ma passano un JobInfo
oggetto a JobScheduler
. Verrà JobScheduler
creata un'istanza dell'oggetto richiesto JobService
, della pianificazione e dell'esecuzione di JobService
in base ai metadati in JobInfo
. Un JobInfo
oggetto deve contenere le informazioni seguenti:
- JobId : valore
int
usato per identificare un processo inJobScheduler
. Il riutilizzo di questo valore aggiornerà tutti i processi esistenti. Il valore deve essere univoco per l'applicazione. - JobService : questo parametro è un
ComponentName
oggetto che identifica in modo esplicito il tipo daJobScheduler
usare per eseguire un processo.
Questo metodo di estensione illustra come creare un JobInfo.Builder
oggetto con un oggetto Android Context
, ad esempio un'attività:
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.
Una potente funzionalità dell'Utilità di pianificazione processi Android è la possibilità di controllare quando un processo viene eseguito o in quali condizioni può essere eseguito un processo. La tabella seguente descrive alcuni dei metodi su JobInfo.Builder
che consentono a un'app di influenzare quando un processo può essere eseguito:
metodo | Descrizione |
---|---|
SetMinimumLatency |
Specifica che un ritardo (in millisecondi) che deve essere osservato prima dell'esecuzione di un processo. |
SetOverridingDeadline |
Dichiara che il processo deve essere eseguito prima che sia trascorso questo tempo (in millisecondi). |
SetRequiredNetworkType |
Specifica i requisiti di rete per un processo. |
SetRequiresBatteryNotLow |
Il processo può essere eseguito solo quando il dispositivo non visualizza un avviso di "batteria insufficiente" all'utente. |
SetRequiresCharging |
Il processo può essere eseguito solo quando la batteria è carica. |
SetDeviceIdle |
Il processo verrà eseguito quando il dispositivo è occupato. |
SetPeriodic |
Specifica che il processo deve essere eseguito regolarmente. |
SetPersisted |
Il processo deve essere perisist tra i riavvii del dispositivo. |
SetBackoffCriteria
Fornisce alcune indicazioni su quanto tempo JobScheduler
deve attendere prima di provare a eseguire di nuovo un processo. Esistono due parti dei criteri di backoff: un ritardo in millisecondi (valore predefinito di 30 secondi) e tipo di backoff da usare (talvolta definito criterio di backoff o criteri di ripetizione dei tentativi). I due criteri sono incapsulati nell'enumerazione Android.App.Job.BackoffPolicy
:
BackoffPolicy.Exponential
: un criterio di backoff esponenziale aumenterà il valore di backoff iniziale in modo esponenziale dopo ogni errore. La prima volta che un processo ha esito negativo, la libreria attenderà l'intervallo iniziale specificato prima di riprogrammare il processo, ad esempio 30 secondi. La seconda volta che il processo ha esito negativo, la libreria attenderà almeno 60 secondi prima di provare a eseguire il processo. Dopo il terzo tentativo non riuscito, la libreria attenderà 120 secondi e così via. Questo è il valore predefinito.BackoffPolicy.Linear
: questa strategia è un backoff lineare che il processo deve essere riprogrammato per l'esecuzione a intervalli impostati (fino a quando non riesce). Il backoff lineare è più adatto per il lavoro che deve essere completato il prima possibile o per i problemi che si risolvono rapidamente.
Per altri dettagli sulla creazione di un JobInfo
oggetto, leggere la documentazione di Google per la JobInfo.Builder
classe.
Passaggio di parametri a un processo tramite JobInfo
I parametri vengono passati a un processo creando un PersistableBundle
oggetto passato insieme al Job.Builder.SetExtras
metodo :
var jobParameters = new PersistableBundle();
jobParameters.PutInt("LoopCount", 11);
var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1)
.SetExtras(jobParameters)
.Build();
L'oggetto PersistableBundle
Android.App.Job.JobParameters.Extras
è accessibile dalla proprietà nel OnStartJob
metodo di un JobService
oggetto :
public override bool OnStartJob(JobParameters jobParameters)
{
var loopCount = jobParams.Extras.GetInt("LoopCount", 10);
// rest of code omitted
}
Programmazione di un processo
Per pianificare un processo, un'applicazione Xamarin.Android otterrà un riferimento al JobScheduler
servizio di sistema e chiamerà il JobScheduler.Schedule
metodo con l'oggetto JobInfo
creato nel passaggio precedente. JobScheduler.Schedule
restituirà immediatamente con uno dei due valori integer:
- JobScheduler.ResultSuccess : il processo è stato pianificato correttamente.
- JobScheduler.ResultFailure : impossibile pianificare il processo. Questo è in genere causato da parametri in conflitto
JobInfo
.
Questo codice è un esempio di pianificazione di un processo e notifica all'utente dei risultati del tentativo di pianificazione:
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();
}
Annullamento di un processo
È possibile annullare tutti i processi pianificati o solo un singolo processo usando il JobsScheduler.CancelAll()
metodo o il JobScheduler.Cancel(jobId)
metodo :
// Cancel all jobs
jobScheduler.CancelAll();
// to cancel a job with jobID = 1
jobScheduler.Cancel(1)
Riepilogo
Questa guida ha illustrato come usare l'Utilità di pianificazione processi Android per eseguire in modo intelligente il lavoro in background. Ha illustrato come incapsulare il lavoro da eseguire come e JobService
come usare JobScheduler
per pianificare il lavoro, specificando i criteri con un JobTrigger
e come gestire gli errori con un oggetto RetryStrategy
.