JobScheduler - Как пропустить первый запуск периодического задания?

в моем приложении я установил периодическое задание, которое запускается каждые 30 минут. Первый запуск задания происходит прямо тогда, когда я планирую это периодическое задание, что в моем случае нежелательно. Я хочу пропустить первый запуск, чтобы он запускался в первый раз через 30+ минут.

Две мои мысли о том, как подойти к этому, заключались в том, чтобы либо вообще не запускать его в течение первых 30 минут (какая-то задержка), либо пометить первое задание как выполненное еще до того, как у него появится возможность начать. К сожалению, я не нашел в JobInfo ни одного метода, который позволил бы мне сделать что-либо из этого.

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

Ниже приведен мой текущий код для планирования периодического задания:

private void scheduleJob() {
    ComponentName componentName = new ComponentName(this, myRecurringTask.class);
    JobInfo info = new JobInfo.Builder(JOB_ID, componentName)
            .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
            .setPersisted(true)
            .setPeriodic(1800000)
            .build();
    JobScheduler scheduler = (JobScheduler) getSystemService(JOB_SCHEDULER_SERVICE);
    scheduler.schedule(info);
}

Я надеюсь, что кто-то столкнулся с такой же ситуацией и может помочь мне решить ее... Спасибо!


person Spyros G    schedule 19.02.2021    source источник
comment
Начальная задержка доступна в WorkManager:stackoverflow.com/questions/51229826/   -  person Sam Chen    schedule 19.02.2021
comment
Спасибо за ваш ответ @SamChen. Я никогда раньше не слышал о WorkManager, я просто проверял его набор функций по сравнению с JobScheduler, он действительно приносит немало улучшений, но при этом сохраняет обратную совместимость. Если я не найду решения с JobScheduler, я перейду на WorkManager и обязательно буду использовать его для новых приложений!   -  person Spyros G    schedule 19.02.2021


Ответы (1)


Используйте WorkManager для планирования фоновой работы, см. введение здесь.

<сильный>1. Добавить зависимость:

implementation "androidx.work:work-runtime-ktx:2.4.0"

<сильный>2. Создать рабочий класс:

class DataRefresher(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
    override suspend fun doWork(): Result {                 //will run on background thread
        //your logic

        return try {
            //your logic

            Result.success()
        } catch (e: HttpException) {
            Result.retry()
        }
    }
}

<сильный>3. Создать класс приложения:

class DevBytesApplication : Application() {
    private val backgroundScope = CoroutineScope(Dispatchers.Default)       //standard background thread

    override fun onCreate() {                           //called when app launches, same as Activity
        super.onCreate()

        initWork()
    }

    private fun initWork() {
        backgroundScope.launch {                        //run in background, not affecting ui
            setupDataRefreshingWork()
        }
    }

    @SuppressLint("IdleBatteryChargingConstraints")
    private fun setupDataRefreshingWork() {
        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.UNMETERED)          //when using wifi
            .setRequiresBatteryNotLow(true)
            .setRequiresCharging(true)
            .setRequiresDeviceIdle(true)                    //when not running heavy task
            .build()

        val repeatingRequest = PeriodicWorkRequestBuilder<DataRefresher>(1, TimeUnit.DAYS)      //【15 minutes is minimum!!】
            .setConstraints(constraints)
            .setInitialDelay(30, TimeUnit.MINUTES)        //【initial delay!!】
            .build()

        WorkManager.getInstance(this).enqueueUniquePeriodicWork(
            DataRefresher::class.java.simpleName,               //work name
            ExistingPeriodicWorkPolicy.KEEP,                    //if new work comes in with same name, discard it
            repeatingRequest
        )
    }
}

<сильный>4. Настройте AndroidManifest:

<manifest
    xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.devbytestest">

    <application
        android:name=".DevBytesApplication"                 //【here, must!!!】
    
        ...

    </application>

</manifest>
person Sam Chen    schedule 19.02.2021
comment
Спасибо за ваш ответ. Я обязательно подумаю о переходе на WorkManager, так как в нем изначально есть именно то, что мне нужно. На данный момент я реализовал обходной путь, отслеживая время выполнения задания в SharedPreferences и пропуская действия задания при первом запуске. - person Spyros G; 19.02.2021