Répartiteur de travail Firebase

Ce guide explique comment planifier le travail en arrière-plan à l’aide de la bibliothèque Firebase Job Dispatcher de Google.

Vue d’ensemble

L’une des meilleures façons de maintenir une application Android réactive pour l’utilisateur consiste à s’assurer que le travail complexe ou de longue durée est effectué en arrière-plan. Toutefois, il est important que le travail en arrière-plan n’affecte pas négativement l’expérience de l’utilisateur avec l’appareil.

Par exemple, un travail en arrière-plan peut interroger un site web toutes les trois ou quatre minutes pour rechercher les modifications apportées à un jeu de données particulier. Cela semble bénin, mais il aurait un impact désastreux sur l’autonomie de la batterie. L’application réveille à plusieurs reprises l’appareil, élève le processeur à un état d’alimentation plus élevé, met sous tension les radios, effectue les requêtes réseau, puis traite les résultats. Cela empire, car l’appareil ne met pas immédiatement hors tension et revient à l’état d’inactivité à faible consommation d’énergie. Un travail en arrière-plan mal planifié peut maintenir par inadvertance l’appareil dans un état avec des besoins d’alimentation inutiles et excessifs. Cette activité apparemment innocente (interrogation d’un site web) rendra l’appareil inutilisable dans un laps de temps relativement court.

Android fournit les API suivantes pour faciliter l’exécution du travail en arrière-plan, mais elles ne sont pas suffisantes à elles seules pour la planification intelligente des travaux.

  • Services d’intention : les services d’intention sont parfaits pour effectuer le travail, mais ils ne fournissent aucun moyen de planifier le travail.
  • AlarmManager : ces API autorisent uniquement la planification du travail, mais ne fournissent aucun moyen d’effectuer réellement le travail. En outre, AlarmManager autorise uniquement les contraintes temporelles, ce qui signifie déclencher une alarme à un certain moment ou après l’expiration d’un certain laps de temps.
  • JobScheduler : JobSchedule est une EXCELLENTE API qui fonctionne avec le système d’exploitation pour planifier des travaux. Toutefois, il n’est disponible que pour les applications Android qui ciblent le niveau d’API 21 ou supérieur.
  • Récepteurs de diffusion : une application Android peut configurer des récepteurs de diffusion pour effectuer un travail en réponse à des événements ou des intentions à l’échelle du système. Toutefois, les récepteurs de diffusion ne fournissent aucun contrôle sur le moment où le travail doit être exécuté. Les modifications apportées au système d’exploitation Android limitent également le moment où les récepteurs de diffusion fonctionneront ou les types de travail auxquels ils peuvent répondre.

Il existe deux fonctionnalités clés permettant d’effectuer efficacement un travail en arrière-plan (parfois appelé travail en arrière-plan ou travail) :

  1. Planification intelligente du travail : lorsqu’une application effectue un travail en arrière-plan, il est important qu’elle le fasse en tant que bon citoyen. Dans l’idéal, l’application ne doit pas exiger l’exécution d’un travail. Au lieu de cela, l’application doit spécifier les conditions qui doivent être remplies pour le moment où le travail peut s’exécuter, puis planifier ce travail pour s’exécuter lorsque les conditions sont remplies. Cela permet à Android d’effectuer intelligemment le travail. Par exemple, les requêtes réseau peuvent être traitées par lot pour qu’elles s’exécutent toutes en même temps afin d’utiliser au maximum la surcharge liée à la mise en réseau.
  2. Encapsulation du travail : le code permettant d’effectuer le travail en arrière-plan doit être encapsulé dans un composant discret qui peut être exécuté indépendamment de l’interface utilisateur et qui sera relativement facile à replanifier si le travail échoue pour une raison quelconque.

Firebase Job Dispatcher est une bibliothèque de Google qui fournit une API Fluent pour simplifier la planification du travail en arrière-plan. Il est destiné à remplacer Google Cloud Manager. Firebase Job Dispatcher se compose des API suivantes :

  • Un Firebase.JobDispatcher.JobService est une classe abstraite qui doit être étendue avec la logique qui s’exécutera dans le travail en arrière-plan.
  • un Firebase.JobDispatcher.JobTrigger indique quand le travail doit être démarré. Cela est généralement exprimé sous la forme d’une fenêtre de temps, par exemple, attendre au moins 30 secondes avant de commencer le travail, mais exécuter le travail dans les 5 minutes.
  • Un Firebase.JobDispatcher.RetryStrategy contient des informations sur ce qui doit être fait lorsqu’un travail ne parvient pas à s’exécuter correctement. La stratégie de nouvelle tentative spécifie le temps d’attente avant d’essayer de réexécuter le travail.
  • Un Firebase.JobDispatcher.Constraint est une valeur facultative qui décrit une condition qui doit être remplie pour que le travail puisse s’exécuter, par exemple si l’appareil se trouve sur un réseau non délimité ou en cours de chargement.
  • est Firebase.JobDispatcher.Job une API qui unifie les API précédentes dans dans une unité de travail qui peut être planifiée par le JobDispatcher. La Job.Builder classe est utilisée pour instancier un Job.
  • Un Firebase.JobDispatcher.JobDispatcher utilise les trois API précédentes pour planifier le travail avec le système d’exploitation et pour fournir un moyen d’annuler des travaux, si nécessaire.

Pour planifier le travail avec firebase Job Dispatcher, une application Xamarin.Android doit encapsuler le code dans un type qui étend la JobService classe. JobService a trois méthodes de cycle de vie qui peuvent être appelées pendant la durée de vie du travail :

  • bool OnStartJob(IJobParameters parameters) : cette méthode est l’endroit où le travail se produit et doit toujours être implémenté. Il s’exécute sur le thread main. Cette méthode retourne true s’il reste du travail ou false si le travail est effectué.
  • bool OnStopJob(IJobParameters parameters) : elle est appelée lorsque le travail est arrêté pour une raison quelconque. Elle doit être retournée true si le travail doit être replanifié pour plus tard.
  • JobFinished(IJobParameters parameters, bool needsReschedule) : cette méthode est appelée lorsque le JobService a terminé tout travail asynchrone.

Pour planifier un travail, l’application instancie un JobDispatcher objet. Ensuite, un Job.Builder est utilisé pour créer un Job objet, qui est fourni à qui JobDispatcher va essayer et planifier l’exécution du travail.

Ce guide explique comment ajouter firebase Job Dispatcher à une application Xamarin.Android et l’utiliser pour planifier le travail en arrière-plan.

Spécifications

Le répartiteur de travaux Firebase nécessite le niveau d’API Android 9 ou supérieur. La bibliothèque Firebase Job Dispatcher s’appuie sur certains composants fournis par les services Google Play ; Les services Google Play doivent être installés sur l’appareil.

Utilisation de la bibliothèque Firebase Job Dispatcher dans Xamarin.Android

Pour commencer à utiliser firebase Job Dispatcher, ajoutez d’abord le package NuGet Xamarin.Firebase.JobDispatcher au projet Xamarin.Android. Recherchez le package Xamarin.Firebase.JobDispatcher dans le Gestionnaire de package NuGet (qui est toujours en préversion).

Après avoir ajouté la bibliothèque Firebase Job Dispatcher, créez une JobService classe, puis planifiez-la FirebaseJobDispatcherpour qu’elle s’exécute avec un instance du .

Création d’un jobservice

Tout le travail effectué par la bibliothèque Firebase Job Dispatcher doit être effectué dans un type qui étend la Firebase.JobDispatcher.JobService classe abstraite. La création d’un JobService est très similaire à la création d’un Service avec l’infrastructure Android :

  1. Étendre la classe JobService
  2. Décorez la sous-classe avec .ServiceAttribute Bien qu’il ne soit pas strictement obligatoire, il est recommandé de définir explicitement le Name paramètre pour faciliter le débogage du JobService.
  3. Ajoutez un IntentFilter pour déclarer dans JobService le AndroidManifest.xml. Cela permet également à la bibliothèque Firebase Job Dispatcher de localiser et d’appeler le JobService.

Le code suivant est un exemple du plus simple JobService pour une application, en utilisant la TPL pour effectuer un travail de manière asynchrone :

[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;
    }
}

Création d’un FirebaseJobDispatcher

Avant qu’un travail puisse être planifié, il est nécessaire de créer un Firebase.JobDispatcher.FirebaseJobDispatcher objet. est FirebaseJobDispatcher responsable de la planification d’un JobService. L’extrait de code suivant permet de créer un instance du FirebaseJobDispatcher:

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

Dans l’extrait de code précédent, la GooglePlayDriver classe is qui permet d’interagir FirebaseJobDispatcher avec certaines API de planification dans Google Play Services sur l’appareil. Le paramètre context est n’importe quel android Context, tel qu’une activité. Actuellement, est GooglePlayDriver la seule IDriver implémentation dans la bibliothèque Firebase Job Dispatcher.

La liaison Xamarin.Android pour firebase Job Dispatcher fournit une méthode d’extension pour créer un FirebaseJobDispatcher à partir de :Context

FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();

Une fois que le FirebaseJobDispatcher a été instancié, il est possible de créer un et d’exécuter Job le code dans la JobService classe . est Job créé par un Job.Builder objet et sera abordé dans la section suivante.

Création d’un fichier Firebase.JobDispatcher.Job avec Job.Builder

La Firebase.JobDispatcher.Job classe est chargée d’encapsuler les métadonnées nécessaires à l’exécution d’un JobService. UnJob contient des informations telles que les contraintes qui doivent être remplies avant que le travail puisse s’exécuter, si le Job est récurrent, ou des déclencheurs qui entraînent l’exécution du travail. Au minimum, un Job doit avoir une balise (chaîne unique qui identifie le travail au FirebaseJobDispatcher) et le type du JobService qui doit être exécuté. Le répartiteur de travaux Firebase instancie le JobService quand il est temps d’exécuter le travail. Un Job est créé à l’aide d’un instance de la Firebase.JobDispatcher.Job.JobBuilder classe .

L’extrait de code suivant est l’exemple le plus simple de création d’un Job à l’aide de la liaison Xamarin.Android :

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

effectue Job.Builder des vérifications de validation de base sur les valeurs d’entrée du travail. Une exception est levée s’il n’est pas possible pour le Job.Builder de créer un Job. Crée Job.Builder un Job avec les valeurs par défaut suivantes :

  • La durée de vie d’un Job(la durée d’exécution planifiée) est uniquement jusqu’au redémarrage de l’appareil, une fois que l’appareil redémarre, est Job perdu.
  • Un Job n’est pas récurrent : il ne s’exécute qu’une seule fois.
  • Un Job sera planifié pour s’exécuter dès que possible.
  • La stratégie de nouvelle tentative par défaut pour un Job consiste à utiliser une interruption exponentielle (décrite plus en détail ci-dessous dans la section Définition d’une stratégie de nouvelle tentative)

Planification d’un travail

Après avoir créé le Job, il doit être planifié avec avant FirebaseJobDispatcher son exécution. Il existe deux méthodes pour planifier un Job:

// 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);

La valeur retournée par FirebaseJobDispatcher.Schedule est l’une des valeurs entières suivantes :

  • FirebaseJobDispatcher.ScheduleResultSuccessJob: a été correctement planifié.
  • FirebaseJobDispatcher.ScheduleResultUnknownError : un problème inconnu s’est produit, ce qui a empêché la Job planification de.
  • FirebaseJobDispatcher.ScheduleResultNoDriverAvailable : un non valide IDriver a été utilisé ou le n’était IDriver en quelque sorte pas disponible.
  • FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger : n’a Trigger pas été pris en charge.
  • FirebaseJobDispatcher.ScheduleResultBadService : le service n’est pas configuré correctement ou n’est pas disponible.

Configuration d’un travail

Il est possible de personnaliser un travail. Voici quelques exemples de personnalisation d’un travail :

Chacune de ces rubriques sera abordée plus en détail dans les sections suivantes.

Passage de paramètres à un travail

Les paramètres sont passés à un travail en créant un Bundle qui est transmis avec la Job.Builder.SetExtras méthode :

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

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

Le Bundle est accessible à partir de la IJobParameters.Extras propriété sur la OnStartJob méthode :

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

Définition de contraintes

Les contraintes peuvent aider à réduire les coûts ou à vider la batterie sur l’appareil. La Firebase.JobDispatcher.Constraint classe définit ces contraintes en tant que valeurs entières :

  • Constraint.OnUnmeteredNetwork : exécutez le travail uniquement lorsque l’appareil est connecté à un réseau non délimité. Cela est utile pour empêcher l’utilisateur d’encourir des frais de données.
  • Constraint.OnAnyNetwork : exécutez le travail sur n’importe quel réseau auquel l’appareil est connecté. Si elle est spécifiée avec Constraint.OnUnmeteredNetwork, cette valeur est prioritaire.
  • Constraint.DeviceCharging : exécutez le travail uniquement lorsque l’appareil est en cours de chargement.

Les contraintes sont définies avec la Job.Builder.SetConstraint méthode :

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

Le JobTrigger fournit des conseils au système d’exploitation sur le moment où le travail doit démarrer. Un JobTrigger a une fenêtre d’exécution qui définit une heure planifiée pour le moment où doit s’exécuter Job . La fenêtre d’exécution a une valeur de fenêtre de début et une valeur de fenêtre de fin . La fenêtre de début est le nombre de secondes pendant lesquelles l’appareil doit attendre avant d’exécuter le travail, et la valeur de la fenêtre de fin est le nombre maximal de secondes à attendre avant d’exécuter le Job.

Un JobTrigger peut être créé avec la Firebase.Jobdispatcher.Trigger.ExecutionWindow méthode . Par exemple Trigger.ExecutionWindow(15,60) , cela signifie que le travail doit s’exécuter entre 15 et 60 secondes à partir du moment où il est planifié. La Job.Builder.SetTrigger méthode est utilisée pour

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

La valeur par défaut JobTrigger d’un travail est représentée par la valeur Trigger.Now, qui spécifie qu’un travail doit être exécuté dès que possible après avoir été planifié..

Définition d’une stratégie retryStrategy

Est Firebase.JobDispatcher.RetryStrategy utilisé pour spécifier le délai qu’un appareil doit utiliser avant d’essayer de réexécuter un travail ayant échoué. Un RetryStrategy a une stratégie, qui définit l’algorithme de base de temps qui sera utilisé pour planifier à nouveau le travail ayant échoué, et une fenêtre d’exécution qui spécifie une fenêtre dans laquelle le travail doit être planifié. Cette fenêtre de rééchelonnement est définie par deux valeurs. La première valeur est le nombre de secondes à attendre avant de rééchelonner le travail (valeur d’interruption initiale ), et la deuxième est le nombre maximal de secondes avant que le travail ne s’exécute (valeur d’interruption maximale ).

Les deux types de stratégies de nouvelle tentative sont identifiés par ces valeurs int :

  • RetryStrategy.RetryPolicyExponential – Une stratégie de backoff exponentiel augmente la valeur de backoff initiale de façon exponentielle après chaque échec. La première fois qu’un travail échoue, la bibliothèque attend l’intervalle de _initial spécifié avant de rééchelonner le travail ( exemple 30 secondes). La deuxième fois que le travail échoue, la bibliothèque attend au moins 60 secondes avant d’essayer d’exécuter le travail. Après la troisième tentative ayant échoué, la bibliothèque attendra 120 secondes, et ainsi de suite. La valeur par défaut RetryStrategy de la bibliothèque Firebase Job Dispatcher est représentée par l’objet RetryStrategy.DefaultExponential . Il a une interruption initiale de 30 secondes et une interruption maximale de 3600 secondes.
  • RetryStrategy.RetryPolicyLinear : cette stratégie est une interruption linéaire que le travail doit être replanifié pour s’exécuter à des intervalles définis (jusqu’à ce qu’il réussisse). L’interruption linéaire est mieux adaptée aux travaux qui doivent être effectués dès que possible ou aux problèmes qui se résolvent rapidement. La bibliothèque Firebase Job Dispatcher définit un RetryStrategy.DefaultLinear qui a une fenêtre de replanification d’au moins 30 secondes et jusqu’à 3600 secondes.

Il est possible de définir un personnalisé RetryStrategy avec la FirebaseJobDispatcher.NewRetryStrategy méthode . Elle prend trois paramètres :

  1. int policy : la stratégie est l’une des valeurs précédentes RetryStrategy , RetryStrategy.RetryPolicyLinearou RetryStrategy.RetryPolicyExponential.
  2. int initialBackoffSeconds : l’interruption initiale est un délai, en secondes, qui est nécessaire avant d’essayer de réexécuter le travail. La valeur par défaut est de 30 secondes.
  3. int maximumBackoffSeconds : la valeur d’interruption maximale déclare le nombre maximal de secondes à retarder avant d’essayer de réexécuter le travail. La valeur par défaut est 3600 secondes.
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();

Annulation d’un travail

Il est possible d’annuler tous les travaux qui ont été planifiés, ou simplement une seule tâche à l’aide de la FirebaseJobDispatcher.CancelAll() méthode ou de la FirebaseJobDispatcher.Cancel(string) méthode :

int cancelResult = dispatcher.CancelAll(); 

// to cancel a single job:

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

L’une ou l’autre méthode retourne une valeur entière :

  • FirebaseJobDispatcher.CancelResultSuccess : le travail a été annulé avec succès.
  • FirebaseJobDispatcher.CancelResultUnknownError : une erreur a empêché l’annulation du travail.
  • FirebaseJobDispatcher.CancelResult.NoDriverAvailableFirebaseJobDispatcher: ne peut pas annuler le travail, car il n’y a pas de valide IDriver disponible.

Résumé

Ce guide explique comment utiliser firebase Job Dispatcher pour effectuer intelligemment un travail en arrière-plan. Il a expliqué comment encapsuler le travail à effectuer en tant que JobService et comment utiliser pour FirebaseJobDispatcher planifier ce travail, en spécifiant les critères avec un JobTrigger et comment gérer les échecs avec un RetryStrategy.