67 votes

Quels outils sont disponibles pour tester JobScheduler?

Nous implémentons un Job via JobScheduler pour le chargement en arrière-plan des données. Le travail sera déclenché environ une fois par jour. Quels sont les outils disponibles pour tester cette fonctionnalité (éventuellement ADB)?

Les cas d'utilisation doivent permettre de simuler les conditions requises pour l'exécution d'un travail ou simplement d'indiquer spécifiquement "Exécuter ce travail" dans le cadre de notre suite de tests automatisés.

130voto

tim Points 2842

La droite.
Henning et P4u144 m'ont mis sur la bonne voie pour répondre à cette question plus en détail.

Identifier tous les emplois inscrits

Identifier votre tâche avec l' adb shell dumpsys jobscheduler commande.
Cela vous donnera une énorme sortie dans les catégories suivantes.

  • Paramètres
  • Enregistré XX Emplois
  • La connectivité
  • Alarmes
  • Inactif
  • Batterie
  • AppIdle
  • Contenu
  • L'histoire de Job
  • Dans l'attente de la file d'attente

La catégorie dont vous êtes le plus susceptible d'être intéressé est Inscrit XX Emplois. Cela vous indique combien d'emplois ont été programmées sur l'appareil.
Par exemple, votre paquet est - com.foo.bar.application vous devriez voir une entrée comme ceci:

JOB #u0a93/17: eec3709 com.foo.bar.application/com.evernote.android.job.v21.PlatformJobService
    u0a93 tag=*job*/com.foo.bar.application/com.evernote.android.job.v21.PlatformJobService
    Source: uid=u0a93 user=0 pkg=com.foo.bar.application
    JobInfo:
      Service: com.foo.bar.application/com.evernote.android.job.v21.PlatformJobService
      PERIODIC: interval=+15m0s0ms flex=+5m0s0ms
      PERSISTED
      Requires: charging=false deviceIdle=false
      Network type: 2
      Backoff: policy=1 initial=+30s0ms
      Has early constraint
      Has late constraint
    Required constraints: TIMING_DELAY DEADLINE UNMETERED
    Satisfied constraints: CONNECTIVITY NOT_ROAMING APP_NOT_IDLE DEVICE_NOT_DOZING
    Unsatisfied constraints: TIMING_DELAY DEADLINE UNMETERED
    Earliest run time: 07:23
    Latest run time: 12:23
    Ready: false (job=false pending=false active=false user=true)

Astuce: Utilisez adb shell dumpsys jobscheduler | grep com.foo.bar.application pour filtrer rapidement la liste.

Maintenant, vous pouvez facilement identifier si votre travail a été enregistré avec les critères corrects.

FireBaseJobdispatcher

Si vous utilisez FirebaseJobDispatcher lib vous pouvez utiliser

adb shell dumpsys activity service GcmService | grep com.foo.bar.debug
    com.foo.bar.debug:0 v853
    u0|com.foo.bar.debug: 3
    (scheduled) com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="com.foo.bar.debug.job.FetchArticlesJob" trigger=window{start=10800s,end=11700s,earliest=10448s,latest=11348s} requirements=[NET_UNMETERED,DEVICE_IDLE] attributes=[PERSISTED,RECURRING] scheduled=-351s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1}
    (scheduled) com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="com.foo.bar.debug.job.FetchNotificationGroupsJob" trigger=window{start=86400s,end=129600s,earliest=86048s,latest=129248s} requirements=[NET_CONNECTED,CHARGING] attributes=[PERSISTED,RECURRING] scheduled=-351s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1}
    (scheduled) com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="com.foo.bar.debug.job.RemoveUnusedRealmArticlesJob" trigger=window{start=577980s,end=608400s,earliest=521961s,latest=552381s} requirements=[NET_ANY] attributes=[PERSISTED,RECURRING] scheduled=-56018s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1}
    (finished) [com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver:com.foo.bar.debug.job.UpdateNotificationGroupJob,u0]
    (finished) [com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver:com.foo.bar.debug.job.UpdatePushTokenJob,u0]
    (finished) [com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver:com.foo.bar.debug.job.FetchArticlesJob,u0]

pour vérifier si votre service a été planifié ou exécuté.

La Force de votre tâche à exécuter

Lors de la création d'un Job , vous obtenez un JOB_ID retournée.
Utilisez cette JOB_ID de la force de l'exécution du travail.
Vous pouvez le faire en utilisant l' adb shell cmd jobscheduler run de commande, (nécessite Android 7.1 ou supérieur).

Par exemple, votre paquet est - com.foo.bar.application et de la JOB_ID a été 1. Vous pouvez maintenant exécuter votre tâche via adb

adb shell cmd jobscheduler run -f com.foo.bar.application 1

N'oubliez pas l' -f option, car cela force l'exécution du travail, même si les restrictions ne sont pas respectées.

Evernote Android Travail Lib

Dernier point, mais certainement pas moins.
L'utilisation de la magnifique bibliothèque de Evernote pour cela.
Il permet de faciliter le portage de l' JobScheduler sur le bas de l'API niveaux en utilisant soit JobScheduler, GcmNetworkManager ou AlarmManager selon votre niveau API.

Edit 24/08

Même mieux d'utiliser le firebase emploi répartiteur de la bibliothèque.

Le Firebase JobDispatcher est une bibliothèque pour la planification des tâches en arrière-plan de votre application Android. Il fournit un JobScheduler-compatible API qui fonctionne sur toutes les versions récentes d'Android (API de niveau 9+) qui ont Google Play services est installé.

J'espère que cela a aidé.

Merci

19voto

Henning Points 509

Avec la commande adb shell dumpsys jobscheduler vous obtenir des informations sur les actuellement prévue et active de l'emploi.

J'ai remarqué que la sortie de la commande diffère grandement entre Android 6 et 7. Avec un Android 5 dispositif de sortie est très court et parfois cryptique. La partie la plus intéressante avec le régime enregistré d'emplois est à construire ici et repris ci-dessous pour plus de commodité, ce qui devrait aider à la déchiffrer:

@Override
public String toString() {
    return String.valueOf(hashCode()).substring(0, 3) + ".."
            + ":[" + job.getService()
            + ",jId=" + job.getId()
            + ",u" + getUserId()
            + ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
            + "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
            + ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
            + ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures
            + ",P=" + job.isPersisted()
            + (isReady() ? "(READY)" : "")
            + "]";
}

Android 7 périphériques d'autre part, ont une très longue sortie avec plus détaillée et mieux lisible informations. Il y a aussi plus de fonctionnalités, comme une histoire. L'inconvénient est que vous devez trouver les parties intéressantes de la première.

Je n'ai pas trouvé un moyen de forcer l'exécution d'un travail bien, il y a une demande de fonctionnalité pour elle. Voir la réponse de p4u144.

17voto

p4u144 Points 254

Départ en Android 7.0, il y a un nouveau cmd adb shell. Et en 7.1 (uniquement dans l'aperçu pour le moment), l' adb shell cmd jobscheduler a été ajouté comme vous pouvez le voir ici, à force de courir votre JobScheduler. L'aide à dit:

Job scheduler (jobscheduler) commandes: aide Imprimer ce texte d'aide.

run [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID Déclencher l'exécution immédiate de l'un spécifique de la tâche planifiée. Options: -f ou --force: exécuter le travail, même si les contraintes techniques telles que la connectivité ne sont pas réunies pour l'instant -u ou --utilisateur: spécifiez l'utilisateur de la tâche à exécuter; la valeur par défaut est le principal ou le système de l'utilisateur

-1voto

Maragues Points 9461

Cela fonctionne pour moi, sans la nécessité d'utiliser des commandes adb. Il nécessite minSdk 21

 @RunWith(AndroidJUnit4.class)
@TargetApi(VERSION_CODES.LOLLIPOP)
public abstract class BaseJobServiceTest {

  protected final Context context() {
    return InstrumentationRegistry.getTargetContext();
  }

  protected final void launchJobAndWait(JobInfo jobInfo) throws InterruptedException {
    JobScheduler scheduler = (JobScheduler) context().getSystemService(Context.JOB_SCHEDULER_SERVICE);

    scheduler.schedule(jobInfo);

    while (jobExecutionPending(scheduler, jobInfo)) {
      Thread.sleep(50);
    }
  }

  private boolean jobExecutionPending(JobScheduler scheduler, JobInfo jobInfo) {
    if (VERSION.SDK_INT >= VERSION_CODES.N) {
      return scheduler.getPendingJob(jobInfo.getId()) != null;
    }

    List<JobInfo> scheduledJobs = scheduler.getAllPendingJobs();
    for (int i = 0, size = scheduledJobs.size(); i < size; i++) {
      if (scheduledJobs.get(i).getId() == jobInfo.getId()) {
        return true;
      }
    }

    return false;
  }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X