планировщик заданий в android N с интервалом менее 15 минут

Часть моего вопроса, как я могу настроить работу с интервалом менее 15 минут в "Нуге", была ответом на "метель" в его ответе:
Планировщик заданий не работает на Android N
Он объяснил проблему и предложил использовать следующее обходное решение:

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

Однако, используя

  .setMinimumLatency(REFRESH_INTERVAL)    

только начинает работу один раз;
но как мне получить периодичность с периодом около 30 секунд на устройстве nougat android (не используя обработчик или диспетчер аварийных сигналов)?

Ответ 1

Если кто-то все еще пытается преодолеть ситуацию,

Вот обходной путь для> = Android N (Если вы хотите установить периодическое задание ниже 15 минут)

Убедитесь, что используется только setMinimumLatency. Кроме того, если вы выполняете задание, которое занимает много времени, следующее задание будет запланировано в, текущее время завершения работы JOB + PROVIDED_TIME_INTERVAL

.SetPeriodic(long millis) хорошо работает для уровня API ниже 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);
  }

ОБНОВЛЕНИЕ: Если вы планируете повторять свое повторное задание в режиме "Доза" и думая о JobScheduler, FYI: JobSchedulers не могут работать в режиме "Дозировка".

Я не обсуждал о Dozing, потому что мы говорили о JobScheduler. Спасибо, @Elletlar, за то, что некоторые могут подумать, что он будет работать, даже если приложение находится в режиме доз, что не так.

Для режима доза AlarmManager по-прежнему дает лучшее решение. Вы можете использовать setExactAndAllowWhileIdle(), если вы хотите выполнять периодическую работу в определенный период времени или использовать setAndAllowWhileIdle(), если вы гибки.

Вы также можете установить userAlarmClock(), поскольку устройство всегда выходит из режима доз для будильника и снова возвращается в режим доз. Другой способ - использовать FCM.

Ссылка: Ограничения на дозу

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

Ответ 2

Я боролся с тем же, когда хотел настроить Job для обновления небольшой части данных. Я выяснил, что решение этой проблемы может создать Job еще раз с тем же идентификатором после того, как я вызвал jobFinished(JobParameters, boolean). Я думаю, что он должен работать каждый раз на главной теме.

Моя функция установки Job выглядит так:

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

Когда я заканчиваю свою работу после первого вызова Job я call в основной теме

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

Это еще раз изменит мою работу еще на такое же количество времени на одном и том же идентификаторе. Когда устройство находится в режиме ожидания, вам все равно придется принимать во внимание отсутствие блокировки слежения в дозе, чтобы ваша работа не запускалась так часто, как вы хотите. Он упоминается в https://developer.android.com/about/versions/nougat/android-7.0-changes.html

Если устройство находится в неподвижном состоянии в течение некоторого времени после входа в Doze, система применяет остальные ограничения Doze к PowerManager.WakeLock, AlarmManager alarms, GPS и Wi-Fi. Независимо от того, применяются ли некоторые или все ограничения Doze, система пробуждает устройство для кратковременных окон обслуживания, в течение которых приложениям разрешен доступ к сети и может выполнять любые отложенные задания/синхронизировать.