web-dev-qa-db-fra.com

planificateur de tâches sous Android N avec un intervalle inférieur à 15 minutes

Une partie de ma question, comment je peux créer un travail avec un intervalle inférieur à 15 minutes dans "Nougat", a été répondu par "Blizzard" dans sa réponse ici:
Le planificateur de tâches ne fonctionne pas sur Android N
Il a expliqué le problème et a suggéré d'utiliser la solution de contournement suivante: 

JobInfo jobInfo;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
  jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
      .setMinimumLatency(REFRESH_INTERVAL)
      .setExtras(bundle).build();
} else {
  jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
      .setPeriodic(REFRESH_INTERVAL)
      .setExtras(bundle).build();
}    

Cependant, en utilisant le

  .setMinimumLatency(REFRESH_INTERVAL)    

commence juste le travail une fois;
mais comment l’obtenir périodique avec une période d’environ 30 secondes sur un appareil Android nougat (sans gestionnaire ni gestionnaire d’alarmes)?

17
tomseitz

Si quelqu'un essaie encore de surmonter la situation,

Voici une solution de contournement pour> = Android N (si vous souhaitez définir un travail périodique inférieur à 15 minutes) 

Vérifiez que seul setMinimumLatency est utilisé. De même, si vous exécutez une tâche qui prend beaucoup de temps, le prochain travail sera planifié à, Heure de fin du travail actuel + PROVIDED_TIME_INTERVAL

.SetPeriodic (long millis) fonctionne bien pour le niveau API inférieur à Android N

@Override
public boolean onStartJob(final JobParameters jobParameters) {
    Log.d(TAG,"Running service now..");
    //Small or Long Running task with callback

    //Reschedule the Service before calling job finished
    if(Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
              scheduleRefresh();

    //Call Job Finished
    jobFinished(jobParameters, false );

    return true;
}

@Override
public boolean onStopJob(JobParameters jobParameters) {
    return false;
}

private void scheduleRefresh() {
  JobScheduler mJobScheduler = (JobScheduler)getApplicationContext()
                    .getSystemService(JOB_SCHEDULER_SERVICE);
  JobInfo.Builder mJobBuilder = 
  new JobInfo.Builder(YOUR_JOB_ID,
                    new ComponentName(getPackageName(), 
                    GetSessionService.class.getName()));

  /* For Android N and Upper Versions */
  if (Android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      mJobBuilder
                .setMinimumLatency(60*1000) //YOUR_TIME_INTERVAL
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY);
  }

UPDATE: Si vous envisagez d'exécuter votre travail en mode Doze et pensez à JobScheduler, FYI: les JobSchedulers ne sont pas autorisés à s'exécuter en mode Doze. 

Je n'ai pas discuté de Dozing parce que nous parlions de JobScheduler. Merci, @Elletlar, pour avoir signalé que certains pourraient penser qu'elle s'exécutera même lorsque l'application est en mode veille, ce qui n'est pas le cas. 

Pour le mode assoupi, AlarmManager fournit toujours la meilleure solution. Vous pouvez utiliser setExactAndAllowWhileIdle () si vous souhaitez exécuter votre travail périodique à une heure précise ou utiliser setAndAllowWhileIdle () si vous êtes flexible. 

Vous pouvez également utiliser setAlarmClock () en tant que périphérique quitte toujours le mode assoupi pour le réveil et repasse en mode assoupi. Une autre façon consiste à utiliser FCM. 

Référence: Doze Restrictions

https://developer.Android.com/training/monitoring-device-state/doze-standby

7
MRah

J'ai eu du mal avec la même chose quand je voulais configurer Job pour actualiser une petite partie des données. J'ai découvert que la solution à ce problème peut être de configurer Job une fois de plus avec le même identifiant après que j'ai appelé jobFinished(JobParameters, boolean). Je pense que cela devrait fonctionner à chaque fois sur le fil principal. 

Ma fonction pour configurer Job ressemble à ceci:

JobInfo generateRefreshTokenJobInfo(long periodTime){
    JobInfo.Builder jobBuilder = new JobInfo.Builder(1L, new ComponentName(mContext, JobService.class));
    jobBuilder.setMinimumLatency(periodTime);
    jobBuilder.setOverrideDeadline((long)(periodTime * 1.05));
    jobBuilder.setRequiresDeviceIdle(false);
    return jobBuilder.build();
}

Quand je finis mon travail après le premier appel de Job j'appelle en thread principal 

jobFinished(mJobParameters, true);
registerRefreshJob(5*60*1000L);

Cela replanifiera mon travail une fois de plus pour le même temps sur le même identifiant. Lorsque l'appareil est à l'état inactif, vous devez toujours tenir compte de l'absence de verrouillage du réveil afin que votre travail ne soit pas démarré aussi souvent que vous le souhaitez. Il est mentionné dans https://developer.Android.com/about/versions/nougat/Android-7.0-changes.html

Si le périphérique est immobile pendant un certain temps après avoir entré Doze, le système applique le reste des restrictions Doze aux analyses PowerManager.WakeLock, AlarmManager, GPS et Wi-Fi. Que des restrictions Doze ou toutes les restrictions soient appliquées, le système active le périphérique pour de brèves fenêtres de maintenance, pendant lesquelles les applications sont autorisées à accéder au réseau et à exécuter toutes les tâches/synchronisations différées.

0
Changeling