JobScheduler - How to skip first job run of periodic job?

白昼怎懂夜的黑 提交于 2021-02-20 03:31:14

问题


in my app i have set a periodic job that is set to run every 30 minutes. The first job run occurs right when I do schedule that periodic job, which is not wanted in my case. What I want is to skip the first run so that it will run for the first time after 30+ minutes.

My two thoughts on how to approach this was to either have it not run at all for the first 30 minutes somehow (some kind of delay), or mark the first job run as done before even having the chance to start. Unfortunately I have not found any method in JobInfo that would allow me to do any of those.

Another workaround that would fulfill my needs would be to somehow limit the jobs to only occur while app is in the background. It does not entirely solve the issue but it could serve as a workaround in my case.

Following is my current code for scheduling the periodic job:

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

I hope someone has run into the same situation and can help me resolve it... Thank you!


回答1:


Use WorkManager for scheduling backgound work, see introduction here.

1. Add Dependency:

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

2. Create Worker Class:

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. Create Application Class:

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. Setup AndroidManifest:

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

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

    </application>

</manifest>


来源:https://stackoverflow.com/questions/66277590/jobscheduler-how-to-skip-first-job-run-of-periodic-job

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!