Как запускать службу каждые 30 минут навсегда с помощью Firebase JobDispatcher?

До сих пор я использовал AlarmManager для отправки HTTP-запроса каждые 30 минут. Но недавно я столкнулся с предупреждением в консоли Google Play: Чрезмерные пробуждения. Когда я прочитал подробности предупреждения, в нем говорилось, что AlarmManager чрезмерно пробуждает устройства.

Затем я исследовал, что еще я мог бы использовать для отправки запроса каждые 30 минут. В результате я нашел эту документацию. Рекомендуется использовать JobScheduler или JobDispatcher. Прежде всего, я пытался использовать JobScheduler, но для этого требовался API 21, что мне не подходит. Мне нужно поддерживать устройства из API 16 в моем текущем проекте. Тогда я решил использовать JobDispatcher.

Это мой JobService:

public class MyJobService extends JobService {

    @Override
    public boolean onStartJob(final JobParameters params) {
        Log.d("JobDispatcherLog", params.getTag()+ " STARTED");
        jobFinished(params, true);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        Log.d("JobDispatcherLog", params.getTag()+ " STOPPED");
        return false;
    }

}

Здесь я создаю задание, которое должно запускать службу каждые 30 минут.

    FirebaseJobDispatcher dispatcher =
            new FirebaseJobDispatcher(new GooglePlayDriver(this));

    RetryStrategy retryStrategy =
            dispatcher.newRetryStrategy(
                    RetryStrategy.RETRY_POLICY_LINEAR, 1800, 86400);

    Job job = dispatcher.newJobBuilder()
            .setService(MyJobService.class)
            .setTag("very-important-job")
            .setLifetime(Lifetime.FOREVER)
            .setReplaceCurrent(true)
            .setRetryStrategy(retryStrategy)
            .setConstraints(Constraint.ON_ANY_NETWORK)
            .build();

    dispatcher.mustSchedule(job);

Я протестировал этот код и получил следующий результат в LogCat:

03-16 18:01:08.540 D/JobDispatcherLog: very-important-job STARTED 
03-16 18:43:41.747 D/JobDispatcherLog: very-important-job STARTED 
03-16 20:12:01.361 D/JobDispatcherLog: very-important-job STARTED

Как видите, он не запускается каждые 30 минут.

Мой вопрос: это нормальное поведение для JobDispatcher? Как запустить службу ровно каждые 30 минут? Если это невозможно, что еще я могу использовать для реализации ранее указанной функции?


person Joe Rakhimov    schedule 16.03.2018    source источник
comment
Диспетчер тревог, как вы уже упоминали, если вы хотите, чтобы задачи запускались в определенное время, например, событие календаря. Но если вам не нужно, чтобы задачи выполнялись точно по расписанию, вам подойдет планировщик заданий.   -  person Raghunandan    schedule 16.03.2018
comment
Обратите внимание, что указанное вами временное окно было при повторной попытке, которое применяется к невыполненному заданию и обозначает начальное и конечное время отсрочки. Наверное, не то, что вы хотели.   -  person Andy    schedule 16.03.2018


Ответы (1)


Вы можете уменьшить временной интервал, в течение которого ваше задание может быть запущено. Это может помочь вам немного контролировать запас времени, в течение которого ваша работа должна запускаться.

        // Create a new FirebaseJobDispatcher with the driver
        FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);

        // Building the Job.
        Job yourJob = dispatcher.newJobBuilder()
                .setService(YourJobService.class)           // The Job service that will execute.
                .setTag(YOUR_JOB_TAG)                       // Unique Tag.
                .setLifetime(Lifetime.FOREVER)              // To make it last "forever".
                .setRecurring(true)                         // To make it repetitive
                /* setTrigger is your time window. You can adjust the SYNC_FLEXTIME_SECONDS to reduce the window a little. But it is not guaranteed to be .*/  
                .setTrigger(Trigger.executionWindow(ALARM_INTERVAL_SECONDS, ALARM_INTERVAL_SECONDS + SYNC_FLEXTIME_SECONDS))             
                .setReplaceCurrent(true) // To make it to overwrite a previous job created with the same tag.
                .build();

ПРИМЕЧАНИЕ. Имейте в виду, что если вы собираетесь использовать FirejobDispatcher (или JobScheduler), то не будет гарантий, что ваша служба будет запускаться ровно каждые 30 минут.

Если вам нужна более точная «тревога», вы должны склониться к использованию AlarmManager + Foreground Service. Имейте в виду, что AlarmManager для Android 6 или более поздних версий будет иметь небольшую задержку (другими словами, будильник не сработает ровно через 30 минут).

person Peter Arcentales    schedule 16.03.2018