2017-09-11 5 views
3

J'ai un travail périodique que je veux exécuter et il est implémenté avec l'aide de la bibliothèque d'emplois Android d'Evernote.Le travail programmé s'exécute plusieurs fois dans Evernote - AndroidJob

Ce que je souhaite accomplir est de mettre à jourMyLocation ever 15 mins.

Le problème est que toutes les 15 minutes, le travail semble s'exécuter plusieurs fois.

Je l'ai testé à l'aide d'un dispositif de OnePlus3 et de débogage, j'ai observé que le LocationUpdateJob.schedule() est appelée une seule fois, ce qui est correct, mais le LocationUpdateJob.onRunJob() est appelé plusieurs fois, ce qui est incorrect, mais ne doit être appelée une fois toutes les 15 minutes .

En outre, illegalStateExceptions sont levées à partir de certains périphériques, selon crashlytics. Cette exception particulière se produit uniquement sur les appareils Android 7.

Voici le crash du rapport d'accident:

Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.mydomain.myapp/MainActivity}: java.lang.IllegalStateException: Apps may not schedule more than 100 distinct jobs 
     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2947) 
     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3008) 
     at android.app.ActivityThread.-wrap14(ActivityThread.java) 
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650) 
     at android.os.Handler.dispatchMessage(Handler.java:102) 
     at android.os.Looper.loop(Looper.java:154) 
     at android.app.ActivityThread.main(ActivityThread.java:6688) 
     at java.lang.reflect.Method.invoke(Method.java) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 
Caused by java.lang.IllegalStateException: Apps may not schedule more than 100 distinct jobs 
     at android.os.Parcel.readException(Parcel.java:1701) 
     at android.os.Parcel.readException(Parcel.java:1646) 
     at android.app.job.IJobScheduler$Stub$Proxy.schedule(IJobScheduler.java:158) 
     at android.app.JobSchedulerImpl.schedule(JobSchedulerImpl.java:42) 
     at com.evernote.android.job.v21.JobProxy21.schedule(SourceFile:198) 
     at com.evernote.android.job.v21.JobProxy21.plantPeriodic(SourceFile:92) 
     at com.evernote.android.job.JobManager.scheduleWithApi(SourceFile:282) 
     at com.evernote.android.job.JobManager.schedule(SourceFile:240) 
     at com.evernote.android.job.JobRequest.schedule(SourceFile:366) 
     at com.mydomain.myapp.service.locationUpdate.LocationUpdateJob.schedule(SourceFile:33) 
     at com.mydomain.myapp.activities.HubActivity.onLoginSuccess(SourceFile:173) 
     at com.mydomain.myapp.activities.HubActivity.onCreate(SourceFile:115) 
     at android.app.Activity.performCreate(Activity.java:6912) 
     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1126) 
     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2900) 
     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3008) 
     at android.app.ActivityThread.-wrap14(ActivityThread.java) 
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1650) 
     at android.os.Handler.dispatchMessage(Handler.java:102) 
     at android.os.Looper.loop(Looper.java:154) 
     at android.app.ActivityThread.main(ActivityThread.java:6688) 
     at java.lang.reflect.Method.invoke(Method.java) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1468) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1358) 

Voici mon code:

Applicataion classe

@Override 
public void onCreate() { 
//init things.... 
JobManager 
      .create(this) 
      .addJobCreator(new LocationUpdateJobCreator()); 
} 

LocationUpdateJobCreator

public class LocationUpdateJobCreator implements JobCreator { 

    @Override 
    public Job create(String s) { 
     switch (s) { 
      case LocationUpdateJob.TAG: 
       return new LocationUpdateJob(); 
      default: 
       return null; 
     } 
    } 
} 

MainActivity:

private void onLogin() { 
    // do other things... 
    LocationUpdateJob.schedule(); 
} 

LocationUpdateJob

public class LocationUpdateJob extends Job { 

    public static final String TAG = "LocationUpdateJob"; 
    private static int jobId = -1; 


    public static void schedule() { 
     final long INTERVAL = 900000L; 
     final long FLEX = 300000L; 
     jobId = new JobRequest 
       .Builder(LocationUpdateJob.TAG) 
       .setPeriodic(INTERVAL, FLEX) 
       .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED) 
       .build() 
       .schedule(); 
    } 


    public static void stop() { 
     JobManager 
       .instance() 
       .cancel(jobId); 
    } 


    @NonNull 
    @Override 
    protected Result onRunJob(Params params) { 
     updateLocation(); 
     return Result.SUCCESS; 
    } 
} 

Je fourchue projet d'échantillonnage de l'Evernote, mais ils font exactement les mêmes étapes, mais je ne pouvais pas comprendre ce que je suis faire différemment.

Répondre

6

J'ai trouvé la réponse à l'ensemble. Je réponds à cela, au cas où quelqu'un d'autre serait confronté au même problème.

Ok, donc selon ma logique ci-dessus, voici ce qui se passait:

1) L'utilisateur ouvre l'application pour première fois, un travail est prévu dans le système d'exploitation, qui court jusqu'à l'infini.

2) L'utilisateur se ferme et ouvre à nouveau l'application, un autre travail est planifié dans le système d'exploitation. 3) Par la 101ème fois que l'utilisateur ouvre l'application, il y a maintenant 100 jobs planifiés et l'application va programmer le 101ème job, ce qui crée une exception, car Android ne permet qu'une application de programmer 100 jobs (dans les nouveaux systèmes d'exploitation versions).

Alors, qu'est-ce que j'ai fait pour résoudre ce problème?

Je modifié mon schedule() pour ressembler à ce qui suit:

public static void schedule() { 
    final long INTERVAL = 900000L; 
    final long FLEX = 300000L; 
    jobId = new JobRequest 
        .Builder(LocationUpdateJob.TAG) 
        .setPeriodic(INTERVAL, 300000L) 
        .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED) 
        .setPersisted(true) 
        .setUpdateCurrent(true) 
        .build() 
        .schedule(); 
} 

Ce qui est différent ici, de l'ancienne façon dont je Planifié est: .setUpdateCurrent(true)

Alors qu'est-ce qui fait est, chaque fois qu'un travail est planifié avec une balise, il remplace tous les travaux existants par la même balise, avec le nouveau travail. Par conséquent, un seul travail doit être exécuté avec cette balise, c'est-à-dire que le tag du travail est rendu unique.

Il y a une explication très brève et bonne here, s'il vous plaît lisez-la.