Firebase Job Dispatcher

Questa guida illustra come pianificare il lavoro in background usando la libreria Firebase Job Dispatcher di Google.

Panoramica

Uno dei modi migliori per mantenere reattiva un'applicazione Android per l'utente è garantire che il lavoro complesso o a esecuzione lunga sia 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 a un determinato set di dati. Questo sembra benigno, ma avrebbe un impatto negativo sulla durata della batteria. L'applicazione riattiva ripetutamente il dispositivo, eleva la CPU a uno stato di alimentazione superiore, accensione delle radio, effettua le richieste di rete e quindi elabora i risultati. Si peggiora perché il dispositivo non verrà immediatamente arrestato e tornerà allo stato di inattività a basso consumo. Il lavoro in background pianificato in modo non valido può inavvertitamente mantenere il dispositivo in uno stato con requisiti di alimentazione superflui ed eccessivi. Questa attività apparentemente innocenza (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 di operazioni in background, ma di per sé non sono sufficienti per una pianificazione intelligente dei processi.

  • Servizi finalità: i servizi finalità sono ottimi per l'esecuzione del lavoro, ma non consentono di pianificare il lavoro.
  • AlarmManager: queste API consentono solo di programmare il lavoro, ma non forniscono alcun modo per eseguire effettivamente il lavoro. Inoltre, AlarmManager consente solo vincoli basati sul tempo, ovvero genera un allarme in un determinato momento o dopo che è trascorso un determinato periodo di tempo.
  • JobScheduler: JobSchedule è un'API ideale che funziona con il sistema operativo per pianificare i processi. Tuttavia, è disponibile solo per le app Android che hanno come destinazione il livello API 21 o superiore.
  • Ricevitori di trasmissione: un'app Android può configurare ricevitori broadcast 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. Anche le modifiche nel sistema operativo Android limitano il funzionamento dei ricevitori broadcast 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):

  1. Pianificazione intelligente del lavoro: è importante che quando un'applicazione esegue il lavoro in background lo fa come un buon utente. Idealmente, l'applicazione non deve richiedere l'esecuzione di un processo. L'applicazione deve invece specificare le condizioni che devono essere soddisfatte quando è possibile eseguire il processo e quindi pianificare l'esecuzione del lavoro quando vengono soddisfatte le condizioni. Ciò consente ad Android di eseguire operazioni in modo intelligente. Ad esempio, le richieste di rete possono essere in batch per l'esecuzione di tutte contemporaneamente per usare al massimo il sovraccarico necessario per la rete.
  2. 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 semplice da ripianificare se il lavoro non viene completato per qualche motivo.

Firebase Job Dispatcher è una libreria di Google che fornisce un'API Fluent per semplificare la pianificazione del lavoro in background. Deve essere la sostituzione di Google Cloud Manager. Firebase Job Dispatcher è costituito dalle API seguenti:

  • È Firebase.JobDispatcher.JobService una classe astratta che deve essere estesa con la logica che verrà eseguita nel processo in background.
  • Dichiara Firebase.JobDispatcher.JobTrigger quando deve essere avviato il processo. Questo valore viene in genere espresso come intervallo di tempo, ad esempio attendere almeno 30 secondi prima di avviare il processo, ma eseguire il processo entro 5 minuti.
  • Contiene informazioni sulle operazioni da eseguire quando un processo non Firebase.JobDispatcher.RetryStrategy viene eseguito correttamente. La strategia di ripetizione dei tentativi specifica il tempo di attesa prima di provare a eseguire di nuovo il processo.
  • È un valore facoltativo che descrive una condizione che deve essere soddisfatta prima che il processo possa essere eseguito, ad esempio il dispositivo si trova in una rete non misurata o Firebase.JobDispatcher.Constraint in ricarica.
  • è un'API che unifica le API precedenti in a un'unità di lavoro che Firebase.JobDispatcher.Job può essere pianificata da JobDispatcher . La Job.Builder classe viene utilizzata per creare un'istanza di un oggetto Job .
  • Un usa le tre API precedenti per pianificare il lavoro con il sistema operativo e fornire un modo per annullare i Firebase.JobDispatcher.JobDispatcher processi, se necessario.

Per pianificare l'utilizzo con Firebase Job Dispatcher, un'applicazione Xamarin.Android deve incapsulare il codice in un tipo che estende la JobService classe. JobService dispone di tre metodi del ciclo di vita che possono essere chiamati durante la durata del processo:

  • bool OnStartJob(IJobParameters parameters) : questo metodo è il punto in cui si verificherà il lavoro e deve essere sempre implementato. Viene eseguito nel thread principale. Questo metodo restituirà true se è presente del lavoro rimanente o se il lavoro è stato false eseguito.
  • bool OnStopJob(IJobParameters parameters) : viene chiamato quando il processo viene arrestato per qualche motivo. Deve restituire se true il processo deve essere riprogrammato per un secondo momento.
  • JobFinished(IJobParameters parameters, bool needsReschedule) : questo metodo viene chiamato al termine JobService di qualsiasi lavoro asincrono.

Per pianificare un processo, l'applicazione crea un'istanza di un JobDispatcher oggetto . Viene quindi usato un oggetto per creare un oggetto , fornito all'oggetto che tenterà di pianificare Job.BuilderJobJobDispatcher l'esecuzione del processo.

Questa guida descrive come aggiungere Firebase Job Dispatcher a un'applicazione Xamarin.Android e usarlo per pianificare il lavoro in background.

Requisiti

Firebase Job Dispatcher richiede l'API Android di livello 9 o superiore. La libreria Firebase Job Dispatcher si basa su alcuni componenti forniti da Google Play Services; il dispositivo deve avere Google Play Services installato.

Uso della libreria Firebase Job Dispatcher in Xamarin.Android

Per iniziare a usare Firebase Job Dispatcher, aggiungere prima di tutto il pacchetto NuGet Xamarin.Firebase.JobDispatcher al progetto Xamarin.Android. Cercare nel NuGet Gestione pacchetti il pacchetto Xamarin.Firebase.JobDispatcher ,che è ancora in versione non definitiva.

Dopo aver aggiunto la libreria Firebase Job Dispatcher, creare una classe e pianificarne l'esecuzione JobService con un'istanza di FirebaseJobDispatcher .

Creazione di un jobservice

Tutte le operazioni eseguite dalla libreria Firebase Job Dispatcher devono essere eseguite in un tipo che estende la Firebase.JobDispatcher.JobService classe astratta. La creazione JobService di è molto simile alla creazione di un con il framework Service Android:

  1. Estendere la JobService classe
  2. Decorare la sottoclasse con ServiceAttribute . Anche se non è strettamente necessario, è consigliabile impostare in modo esplicito il Name parametro per facilitare il debug di JobService .
  3. Aggiungere un IntentFilter oggetto per dichiarare nella classe JobServiceIntentFilter. Ciò consente anche alla libreria Firebase Job Dispatcher di individuare e richiamare JobService .

Il codice seguente è un esempio del più semplice per JobService un'applicazione, usando la TPL per eseguire in modo asincrono alcune operazioni:

[Service(Name = "com.xamarin.fjdtestapp.DemoJob")]
[IntentFilter(new[] {FirebaseJobServiceIntent.Action})]
public class DemoJob : JobService
{
    static readonly string TAG = "X:DemoService";

    public override bool OnStartJob(IJobParameters jobParameters)
    {
        Task.Run(() =>
        {
            // Work is happening asynchronously (code omitted)
                       
        });

        // Return true because of the asynchronous work
        return true;  
    }

    public override bool OnStopJob(IJobParameters jobParameters)
    {
        Log.Debug(TAG, "DemoJob::OnStartJob");
        // nothing to do.
        return false;
    }
}

Creazione di un FirebaseJobDispatcher

Prima di poter programmare qualsiasi lavoro, è necessario creare un Firebase.JobDispatcher.FirebaseJobDispatcher oggetto . è FirebaseJobDispatcher responsabile della pianificazione di un oggetto JobService . Il frammento di codice seguente è un modo per creare un'istanza di FirebaseJobDispatcher :

// This is the "Java" way to create a FirebaseJobDispatcher object
IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);

Nel frammento di codice precedente la classe è che consente all'oggetto di interagire con alcune DELLE API di pianificazione GooglePlayDriverFirebaseJobDispatcher Google Play Services nel dispositivo. Il parametro context è qualsiasi Context Android, ad esempio un'attività . Attualmente è GooglePlayDriver l'unica IDriver implementazione nella libreria Firebase Job Dispatcher.

L'associazione Xamarin.Android per Firebase Job Dispatcher fornisce un metodo di estensione per creare un oggetto FirebaseJobDispatcher da Context :

FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();

Dopo aver FirebaseJobDispatcher creato un'istanza di , è possibile creare ed Job eseguire il codice nella classe JobService . JobL'oggetto viene creato da un oggetto e verrà illustrato nella sezione Job.Builder successiva.

Creazione di firebase.JobDispatcher.Job con Job.Builder

La Firebase.JobDispatcher.Job classe è responsabile dell'incapsulamento dei metadati necessari per eseguire un oggetto JobService . Contiene informazioni quali qualsiasi vincolo che deve essere soddisfatto prima dell'esecuzione del processo, se è ricorrente o qualsiasi trigger che causerà l'esecuzione JobJob del processo. Come minimo, un deve avere un tag (una stringa univoca che identifica il processo in ) e il tipo di che Job deve essere JobFirebaseJobDispatcherJobService eseguito. Firebase Job Dispatcher crea un'istanza JobService di quando è il momento di eseguire il processo. Un Job oggetto viene creato usando un'istanza della classe Firebase.JobDispatcher.Job.JobBuilder .

Il frammento di codice seguente è l'esempio più semplice di come creare un Job oggetto usando l'associazione Xamarin.Android:

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .Build();

Eseguirà Job.Builder alcuni controlli di convalida di base sui valori di input per il processo. Se non è possibile creare un oggetto , verrà generata Job.Builder un'eccezione Job . Verrà Job.Builder creato un oggetto con le impostazioni predefinite Job seguenti:

  • La durata di un oggetto (per quanto tempo verrà pianificata l'esecuzione) è solo fino al riavvio del dispositivo, una volta che il dispositivo viene JobJobJob riavviato, viene perso.
  • Un Job non è ricorrente: verrà eseguito una sola volta.
  • Verrà pianificata l'esecuzione di un oggetto Job appena possibile.
  • La strategia di ripetizione dei tentativi predefinita per un oggetto consiste nell'usare un backoff esponenziale (descritto più in dettaglio più avanti nella sezione Impostazione di JobretryStrategy)Job

Pianificazione di un processo

Dopo aver creato Job , deve essere pianificato con prima FirebaseJobDispatcher dell'esecuzione. Esistono due metodi per la pianificazione di Job un oggetto :

// This will throw an exception if there was a problem scheduling the job
dispatcher.MustSchedule(myJob);

// This method will not throw an exception; an integer result value is returned
int scheduleResult = dispatcher.Schedule(myJob);

Il valore restituito FirebaseJobDispatcher.Schedule da sarà uno dei valori integer seguenti:

  • FirebaseJobDispatcher.ScheduleResultSuccess : Job l'oggetto è stato pianificato correttamente.
  • FirebaseJobDispatcher.ScheduleResultUnknownError : si è verificato un problema sconosciuto che ha impedito Job la pianificazione di .
  • FirebaseJobDispatcher.ScheduleResultNoDriverAvailable : è stato IDriver usato un valore non valido o non è in qualche modo IDriver disponibile.
  • FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger : Trigger l'oggetto non è supportato.
  • FirebaseJobDispatcher.ScheduleResultBadService : il servizio non è configurato correttamente o non è disponibile.

Configurazione di un processo

È possibile personalizzare un processo. Di seguito sono riportati alcuni esempi di come personalizzare un processo:

  • Passaggio di parametri a un processo: un può richiedere valori aggiuntivi per eseguire il proprio lavoro, ad esempio il download di un file.
  • Imposta vincoli: può essere necessario eseguire un processo solo quando vengono soddisfatte determinate condizioni. Ad esempio, eseguire un solo Job quando il dispositivo è in carica.
  • Specificare quando deve essere eseguito un oggetto : Firebase Job Dispatcher consente alle applicazioni di specificare un'ora in cui deve essere eseguito il processo.
  • Dichiarare una strategia di ripetizione dei tentativi per i processi non riusciti: una strategia di ripetizione dei tentativi fornisce indicazioni sulle attività da eseguire con il completamento non riuscito.

Ognuno di questi argomenti verrà illustrato più di seguito nelle sezioni seguenti.

Passaggio di parametri a un processo

I parametri vengono passati a un processo creando un Bundle oggetto passato insieme al metodo Job.Builder.SetExtras :

Bundle jobParameters = new Bundle();
jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetExtras(jobParameters)
                      .Build();

BundleL'oggetto è accessibile dalla proprietà nel metodo IJobParameters.ExtrasOnStartJob :

public override bool OnStartJob(IJobParameters jobParameters)
{
    int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);
    
    // rest of code omitted
} 

Impostazione di vincoli

I vincoli consentono di ridurre i costi o lo svuotamento della batteria nel dispositivo. La Firebase.JobDispatcher.Constraint classe definisce questi vincoli come valori integer:

  • Constraint.OnUnmeteredNetwork : eseguire il processo solo quando il dispositivo è connesso a una rete non misurata. Ciò è utile per evitare che l'utente incorre in addebiti per i dati.
  • Constraint.OnAnyNetwork : eseguire il processo in qualsiasi rete a cui è connesso il dispositivo. Se specificato insieme a Constraint.OnUnmeteredNetwork , questo valore avrà la priorità.
  • Constraint.DeviceCharging : eseguire il processo solo quando il dispositivo viene ricaricato.

I vincoli vengono impostati con il Job.Builder.SetConstraint metodo :

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetConstraint(Constraint.DeviceCharging)
                      .Build();

Fornisce JobTrigger al sistema operativo indicazioni sull'avvio del processo. Dispone JobTrigger di una finestra di JobTrigger che definisce un'ora pianificata per l'esecuzione Job di . La finestra di esecuzione ha un valore della finestra iniziale e un valore della finestra finale. La finestra iniziale è il numero di secondi che il dispositivo deve attendere prima di eseguire il processo e il valore della finestra finale è il numero massimo di secondi di attesa prima di eseguire Job .

È JobTrigger possibile creare un oggetto con il metodo Firebase.Jobdispatcher.Trigger.ExecutionWindow . Ad Trigger.ExecutionWindow(15,60) esempio, significa che il processo deve essere eseguito tra 15 e 60 secondi da quando è pianificato. Il Job.Builder.SetTrigger metodo viene usato per

JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);
Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetTrigger(myTrigger)
                      .Build();

L'impostazione predefinita per un processo è rappresentata dal valore , che specifica che un processo deve essere eseguito il prima JobTriggerTrigger.Now possibile dopo la pianificazione.

Impostazione di retryStrategy

Viene usato per specificare la quantità di ritardo che un dispositivo deve usare prima di provare Firebase.JobDispatcher.RetryStrategy a eseguire nuovamente un processo non riuscito. Un dispone di un criterio , che definisce l'algoritmo di base temporale che verrà usato per pianificare nuovamente il processo non riuscito e una finestra di esecuzione che specifica una finestra in cui deve essere pianificato RetryStrategy il processo. RetryStrategy Questa finestra di riprogrammazione è definita da due valori. Il primo valore è il numero di secondi di attesa prima di riprogrammare il processo (il valore di backoff iniziale) e il secondo è il numero massimo di secondi prima che il processo deve essere eseguito (il valore di backoff massimo).

I due tipi di criteri di ripetizione dei tentativi sono identificati da questi valori int:

  • RetryStrategy.RetryPolicyExponential : un RetryStrategy.RetryPolicyExponential 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_initial interno 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. RetryStrategyL'impostazione predefinita per la libreria Firebase Job Dispatcher è rappresentata dall'oggetto RetryStrategy.DefaultExponential . Ha un backoff iniziale di 30 secondi e un backoff massimo di 3600 secondi.
  • RetryStrategy.RetryPolicyLinear : questa strategia è un RetryStrategy.RetryPolicyLinear che il processo deve essere riprogrammato per l'esecuzione a intervalli impostati (fino a quando non ha esito positivo). Il backoff lineare è ideale per operazioni che devono essere completate il prima possibile o per problemi che si risolveranno rapidamente. La libreria Firebase Job Dispatcher definisce un oggetto con una finestra di riprogrammazione di almeno 30 secondi e fino RetryStrategy.DefaultLinear a 3600 secondi.

È possibile definire un oggetto personalizzato RetryStrategy con il FirebaseJobDispatcher.NewRetryStrategy metodo . Accetta tre parametri:

  1. int policy : il int policy è uno dei valori RetryStrategy precedenti, RetryStrategy.RetryPolicyLinear o RetryStrategy.RetryPolicyExponential .
  2. int initialBackoffSeconds : il int initialBackoffSeconds è un ritardo, in secondi, necessario prima di provare a eseguire di nuovo il processo. Il valore predefinito è 30 secondi.
  3. int maximumBackoffSeconds : il int maximumBackoffSeconds massimo dichiara il numero massimo di secondi di ritardo prima di provare di nuovo a eseguire il processo. Il valore predefinito è 3600 secondi.
RetryStrategy retry = dispatcher.NewRetryStrategy(RetryStrategy.RetryPolicyLinear, initialBackoffSeconds, maximumBackoffSet);

// Create a Job and set the RetryStrategy via the Job.Builder
Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetRetryStrategy(retry)
                      .Build();

Annullamento di un processo

È possibile annullare tutti i processi pianificati o solo un singolo processo usando il FirebaseJobDispatcher.CancelAll() metodo o il metodo FirebaseJobDispatcher.Cancel(string) :

int cancelResult = dispatcher.CancelAll(); 

// to cancel a single job:

int cancelResult = dispatcher.Cancel("unique-tag-for-job");

Entrambi i metodi restituiranno un valore integer:

  • FirebaseJobDispatcher.CancelResultSuccess : il processo è stato annullato correttamente.
  • FirebaseJobDispatcher.CancelResultUnknownError : un errore ha impedito l'annullamento del processo.
  • FirebaseJobDispatcher.CancelResult.NoDriverAvailable : non FirebaseJobDispatcher è in grado di annullare il processo perché non è disponibile alcun IDriver valido.

Riepilogo

Questa guida illustra come usare Firebase Job Dispatcher per eseguire in modo intelligente il lavoro in background. Viene illustrato come incapsulare il lavoro da eseguire come e come usare per pianificare il lavoro, specificando i criteri con e come gestire gli errori con JobServiceFirebaseJobDispatcherJobTriggerRetryStrategy .