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!
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>