Partager via


Planificateur de travaux Android

Ce guide explique comment planifier le travail en arrière-plan à l’aide de l’API Planificateur de travaux Android, qui est disponible sur les appareils Android exécutant Android 5.0 (niveau d’API 21) et versions ultérieures.

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.
  • 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 avec le système d’exploitation qui effectuera le travail lorsque les conditions sont remplies. Cela permet à Android d’exécuter le travail pour garantir une efficacité maximale sur l’appareil. 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.

Android Job Scheduler est une infrastructure intégrée au système d’exploitation Android qui fournit une API Fluent pour simplifier la planification du travail en arrière-plan. Le planificateur de travaux Android se compose des types suivants :

  • Le Android.App.Job.JobScheduler est un service système qui est utilisé pour planifier, exécuter et, si nécessaire, annuler des travaux pour le compte d’une application Android.
  • Un Android.App.Job.JobService est une classe abstraite qui doit être étendue avec la logique qui exécutera le travail sur le thread main de l’application. Cela signifie que le est responsable de JobService la façon dont le travail doit être effectué de manière asynchrone.
  • Un Android.App.Job.JobInfo objet contient les critères pour guider Android quand le travail doit s’exécuter.

Pour planifier le travail avec android Job Scheduler, une application Xamarin.Android doit encapsuler le code dans une classe 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(Paramètres JobParameters) : cette méthode est appelée par pour effectuer le JobScheduler travail et s’exécute sur le thread main de l’application. Il est de la responsabilité du JobService d’effectuer le travail de manière asynchrone et de retourner true s’il reste du travail ou false si le travail est effectué.

    Lorsque le JobScheduler appelle cette méthode, il demande et conserve un wakelock à partir d’Android pendant la durée du travail. Une fois le travail terminé, il est de la responsabilité du JobService d’indiquer le JobScheduler de ce fait en appelant la JobFinished méthode (décrite ci-dessous).

  • JobFinished(Paramètres JobParameters, bool needsReschedule) : cette méthode doit être appelée par le JobService pour indiquer JobScheduler que le travail est effectué. Si JobFinished n’est pas appelé, le JobScheduler ne supprime pas le verrouillage du wakelock, ce qui entraîne une décharge inutile de la batterie.

  • bool OnStopJob(Paramètres JobParameters) : elle est appelée lorsque le travail est arrêté prématurément par Android. Elle doit retourner true si le travail doit être replanifié en fonction des critères de nouvelle tentative (décrits plus en détail ci-dessous).

Il est possible de spécifier des contraintes ou des déclencheurs qui contrôlent quand un travail peut ou doit s’exécuter. Par exemple, il est possible de limiter un travail pour qu’il ne s’exécute que lorsque l’appareil est en cours de chargement ou pour démarrer un travail lorsqu’une photo est prise.

Ce guide explique en détail comment implémenter une JobService classe et la planifier avec .JobScheduler

Spécifications

Le planificateur de travaux Android nécessite le niveau d’API Android 21 (Android 5.0) ou supérieur.

Utilisation du planificateur de travaux Android

Il existe trois étapes pour utiliser l’API Android JobScheduler :

  1. Implémentez un type JobService pour encapsuler le travail.
  2. Utilisez un JobInfo.Builder objet pour créer l’objet JobInfo qui contiendra les critères pour exécuter JobScheduler le travail.
  3. Planifiez le travail à l’aide de JobScheduler.Schedule.

Implémenter un JobService

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

  1. Étendez la JobService classe .
  2. Décorez la sous-classe avec le ServiceAttribute et définissez le Name paramètre sur une chaîne composée du nom du package et du nom de la classe (voir l’exemple suivant).
  3. Définissez la Permission propriété sur sur la ServiceAttribute chaîne android.permission.BIND_JOB_SERVICE.
  4. Remplacez la OnStartJob méthode, en ajoutant le code pour effectuer le travail. Android appelle cette méthode sur le thread main de l’application pour exécuter le travail. Travail qui prendra plus de temps que quelques millisecondes doivent être effectuées sur un thread pour éviter de bloquer l’application.
  5. Lorsque le travail est terminé, le JobService doit appeler la JobFinished méthode . Cette méthode indique JobService au que le JobScheduler travail est effectué. L’échec de l’appel JobFinished entraîne la JobService mise en place de demandes inutiles sur l’appareil, ce qui raccourcit l’autonomie de la batterie.
  6. Il est judicieux de remplacer également la OnStopJob méthode . Cette méthode est appelée par Android lorsque le travail est arrêté avant d’être terminé et offre à la JobService possibilité de supprimer correctement toutes les ressources. Cette méthode doit retourner true s’il est nécessaire de replanifier le travail ou false s’il n’est pas souhaitable de réexécuter le travail.

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

Création d’un JobInfo pour planifier un travail

Les applications Xamarin.Android n’instancient pas un JobService directement, mais passent un JobInfo objet au JobScheduler. instancie JobScheduler l’objet demandéJobService, en planifiant et en exécutant en JobService fonction des métadonnées dans .JobInfo Un JobInfo objet doit contenir les informations suivantes :

  • JobId : il s’agit d’une int valeur utilisée pour identifier un travail dans le JobScheduler. La réutilisation de cette valeur met à jour tous les travaux existants. La valeur doit être unique pour l’application.
  • JobService : ce paramètre est un ComponentName qui identifie explicitement le type que le JobScheduler doit utiliser pour exécuter un travail.

Cette méthode d’extension montre comment créer un JobInfo.Builder avec un android Context, tel qu’une activité :

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.

Une fonctionnalité puissante du planificateur de travaux Android est la possibilité de contrôler quand un travail s’exécute ou dans quelles conditions un travail peut s’exécuter. Le tableau suivant décrit certaines des méthodes sur JobInfo.Builder qui permettent à une application d’influencer le moment où un travail peut s’exécuter :

Méthode Description
SetMinimumLatency Spécifie qu’un délai (en millisecondes) doit être observé avant l’exécution d’un travail.
SetOverridingDeadline Déclare que le travail doit s’exécuter avant l’expiration de ce délai (en millisecondes).
SetRequiredNetworkType Spécifie la configuration réseau requise pour un travail.
SetRequiresBatteryNotLow Le travail ne peut s’exécuter que lorsque l’appareil n’affiche pas d’avertissement de « batterie faible » à l’utilisateur.
SetRequiresCharging Le travail ne peut s’exécuter que lorsque la batterie est en cours de chargement.
SetDeviceIdle Le travail s’exécute lorsque l’appareil est occupé.
SetPeriodic Spécifie que le travail doit être exécuté régulièrement.
SetPersisted Le travail doit faire l’objet d’un redémarrage d’appareil à l’autre.

Le SetBackoffCriteria fournit des conseils sur la durée pendant laquelle le JobScheduler doit attendre avant d’essayer d’exécuter à nouveau un travail. Il existe deux parties dans les critères d’interruption : un délai en millisecondes (valeur par défaut de 30 secondes) et le type d’annulation à utiliser (parfois appelé stratégie d’interruption ou stratégie de nouvelle tentative). Les deux stratégies sont encapsulées dans l’enum Android.App.Job.BackoffPolicy :

  • BackoffPolicy.Exponential – 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 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. Il s'agit de la valeur par défaut.
  • BackoffPolicy.Linear : 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.

Pour plus d’informations sur la création d’un JobInfo objet, consultez la documentation de Google pour la JobInfo.Builder classe.

Passage de paramètres à un travail via JobInfo

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

var jobParameters = new PersistableBundle();
jobParameters.PutInt("LoopCount", 11);

var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1)
                     .SetExtras(jobParameters)
                     .Build();

Le PersistableBundle est accessible à partir de la Android.App.Job.JobParameters.Extras propriété dans la OnStartJob méthode d’un JobService:

public override bool OnStartJob(JobParameters jobParameters)
{
    var loopCount = jobParams.Extras.GetInt("LoopCount", 10);
    
    // rest of code omitted
} 

Planification d’un travail

Pour planifier un travail, une application Xamarin.Android obtient une référence au JobScheduler service système et appelle la méthode avec l’objet JobInfoJobScheduler.Schedule créé à l’étape précédente. JobScheduler.Schedule retourne immédiatement avec l’une des deux valeurs entières :

  • JobScheduler.ResultSuccess : le travail a été planifié avec succès.
  • JobScheduler.ResultFailure : le travail n’a pas pu être planifié. Cela est généralement dû à des paramètres en JobInfo conflit.

Ce code est un exemple de planification d’un travail et de notification à l’utilisateur des résultats de la tentative de planification :

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();
}

Annulation d’un travail

Il est possible d’annuler tous les travaux qui ont été planifiés, ou simplement un seul travail à l’aide de la JobsScheduler.CancelAll() méthode ou de la JobScheduler.Cancel(jobId) méthode :

// Cancel all jobs
jobScheduler.CancelAll(); 

// to cancel a job with jobID = 1
jobScheduler.Cancel(1)

Résumé

Ce guide explique comment utiliser le planificateur de travaux Android pour effectuer un travail en arrière-plan de manière intelligente. Il a expliqué comment encapsuler le travail à effectuer en tant JobService que et comment utiliser pour JobScheduler planifier ce travail, en spécifiant les critères avec un JobTrigger et comment les échecs doivent être gérés avec un RetryStrategy.