I have written a complete tutorials series on WorkManager. In this series, we explained about WorkManager, How’s it’s working, and explained how run tasks under specific conditions using WorkManager. In this tutorial, I’m going to explain how to schedule a recurring or repetitive task in Android. In other words, In this article, we learn about cron job in android.
WorkManager?
WorkManager is a task scheduler, it makes easy to specify the asynchronous task. The Work Manager API helps create the task and hand it to the Work Manager to run immediately or at an appropriate time as mentioned.
Types of work supported by WorkManager
WorkManager is support two type work. OneTimeWorkRequest and PeriodicWorkRequest.
1. OneTimeWorkRequest
As per name OneTimeWorkRequest for non-repeating work. Mean if you want to enqueue requests for one time only then we used this WorkRequest.
2. PeriodicWorkRequest
This WorkRequest used for repeating or recurring works. In Simple words, PeriodicWorkRequest works as cron job in android. In other words, you want to perform some repetitive task in Android than we use PeriodicWorkRequest. This type of work is repeating multiple times until it is
Understand with Demo Application for cron job in android
1. Let’s open android studio and create a new projects.
Now I’m going to demonstrate, how to scheduling recurring task in Android? How to enqueue the job and cancel the enqueue work? Go to file menu and create a new project with EmptyActivity template and add WorkManager dependency.
implementation "android.arch.work:work-runtime:1.0.1"
2. Create a subclass of Worker class
Create a java class in src folder and extends Worker class. After that doWork() override methods and define work here.
package com.wave.periodicworkrequest; import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.os.Build; import android.support.annotation.NonNull; import android.support.v4.app.NotificationCompat; import androidx.work.Data; import androidx.work.Worker; import androidx.work.WorkerParameters; public class MyWorker extends Worker { private static final String WORK_RESULT = "work_result"; public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); } @NonNull @Override public Result doWork() { Data taskData = getInputData(); String taskDataString = taskData.getString(MainActivity.MESSAGE_STATUS); showNotification("WorkManager", taskDataString != null ? taskDataString : "Message has been Sent"); Data outputData = new Data.Builder().putString(WORK_RESULT, "Jobs Finished").build(); return Result.success(outputData); } private void showNotification(String task, String desc) { NotificationManager manager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); String channelId = "task_channel"; String channelName = "task_name"; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { NotificationChannel channel = new NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT); manager.createNotificationChannel(channel); } NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(), channelId) .setContentTitle(task) .setContentText(desc) .setSmallIcon(R.mipmap.ic_launcher); manager.notify(1, builder.build()); } }
3. Go to res/layout and open activity_main.xml
In this layout, we are using three resources, TextView for showing the status of work. One Button for enqueue work, second one for canceling enqueue work. open layout file and add below code
<TextView android:id="@+id/textViewWorkStatus" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:text="Work Status" app:layout_constraintBottom_toTopOf="@+id/buttonEnqueueWork" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_chainStyle="packed" /> <Button android:id="@+id/buttonEnqueueWork" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="16dp" android:layout_marginEnd="8dp" android:background="@color/colorAccent" android:padding="16dp" android:text="Enqueue Work" android:textAllCaps="false" android:textColor="#fff" app:layout_constraintBottom_toTopOf="@+id/buttonCancelWork" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textViewWorkStatus" /> <Button android:id="@+id/buttonCancelWork" android:layout_width="200dp" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="16dp" android:layout_marginEnd="8dp" android:background="@color/colorAccent" android:padding="16dp" android:text="Cancel Work" android:textAllCaps="false" android:textColor="#fff" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/buttonEnqueueWork" />
5. Open MainActivity and do following operations
- Get WorkManager instance
- Create PeriodicWorkRequest
- Get WorkInfo by Id
- Enqueue work request
- Cancel an enqueued work
5.1 Get WorkManager instance
WorkManager mWorkManager = WorkManager.getInstance();
5.2 Create PeriodicWorkRequest
WorkManager provides PeriodicWorkRequest for scheduling recurring and repetitive WorkRequest. It has the following parameter

For now, I’m creating request that be run every 15 min.
PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES).build();
5.3 Get WorkInfo by Id
mWorkManager.getWorkInfoByIdLiveData(workRequest.getId()).observe(this, new Observer<WorkInfo>() { @Override public void onChanged(@Nullable WorkInfo workInfo) { if (workInfo != null) { WorkInfo.State state = workInfo.getState(); tvWorkStatus.append(state.toString() + "\n"); } } });
5.4 Enqueue work request
btnSchedulePeriodicWork.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mWorkManager.enqueue(workRequest); } });
5.6 Cancel a enqueued work
WorkManager supports several ways to cancel a enqueued work

WorkManager.getInstance().cancelWorkById(workRequest.getId());
Finally, source code of MainActivity seems like
package com.wave.periodicworkrequest; import android.arch.lifecycle.Observer; import android.os.Build; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.Button; import android.widget.TextView; import java.util.concurrent.TimeUnit; import androidx.work.PeriodicWorkRequest; import androidx.work.WorkInfo; import androidx.work.WorkManager; public class MainActivity extends AppCompatActivity { public static final String MESSAGE_STATUS = "MainActivity"; Button btnEnqueueWork; Button btnCancelWork; TextView tvWorkStatus; PeriodicWorkRequest workRequest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); btnEnqueueWork = findViewById(R.id.buttonEnqueueWork); btnCancelWork = findViewById(R.id.buttonCancelWork); tvWorkStatus = findViewById(R.id.textViewWorkStatus); final WorkManager mWorkManager = WorkManager.getInstance(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { workRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES).build(); } btnEnqueueWork.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mWorkManager.enqueue(workRequest); } }); btnCancelWork.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { WorkManager.getInstance().cancelWorkById(workRequest.getId()); } }); mWorkManager.getWorkInfoByIdLiveData(workRequest.getId()).observe(this, new Observer<WorkInfo>() { @Override public void onChanged(@Nullable WorkInfo workInfo) { if (workInfo != null) { WorkInfo.State state = workInfo.getState(); tvWorkStatus.append(state.toString() + "\n"); } } }); } }
Now run the application and see, our app will the up and running. For verifying your logic, follow the step as per demo app video. If it’s helpful for you, then help me by sharing this post with all your friends who learning android app development.
Download source code
If you have any queries, feel free to ask them in the comment section below. Happy Coding 🙂
2 Comments
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
This check is not required for
workRequest = new PeriodicWorkRequest.Builder …
same question because of this condition i spent almost 2+ hours to find out error while i am debugging in below oreo devices.