How to schedule a periodic background job using work manager in android?

ยท

7 min read

๐ŸŽฏ Objective

We will perform a very simple task of printing a number in the logs every 15 minutes with the help of the work manager.

๐Ÿค” What is the work manager?

Work Manager is a simple library for doing any deferrable background work reliably. Here, a background task which doesn't needs to be executed at an exact moment is considered to be deferrable and by reliably I mean that the task should be executed even if the user exits the app or the device restarts.

๐Ÿ‘จ๐Ÿฝโ€๐Ÿ’ป Let's code

โš ๏ธ Pre-requisites

  • Create an android project with an Empty activity. Select Launcher Activity and Generate layout file options.

  • Verify you have google() in Project level build.gradle file. If not please add it. The result should look as below :

allprojects {
    repositories {
        google()

        // If you're using a version of Gradle lower than 4.1, you must instead use:
        // maven {
        //     url 'https://maven.google.com'
        // }
        // An alternative URL is 'https://dl.google.com/dl/android/maven2/'
    }
}

๐Ÿ‘‰๐Ÿผ Import library

In Module level build.gradle file paste the following the line of code :

implementation "androidx.work:work-runtime:2.5.0"

For the latest available version of this library, please refer to this page.

๐Ÿ‘‰๐Ÿผ Create a Worker class

  • Create a new class MyWorker and it should extend Worker.

  • Create a parameterized constructor.

public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }
  • Override and implement the doWork() method
@NonNull
    @Override
    public Result doWork() {
        return null;
    }
  • Create a new static integer variable called count.

  • Inside the doWork(), increase value of count and also print the value in log :

count++;
Log.d("MyWorker","worker called - "+count+" time(s)");

๐Ÿ’ก doWork() is the method where we need to perform the actual background task, this method gets executed on a background thread. It is good for doing Synchronous tasks. For the asynchronous task, I will write another tutorial.

  • Return Result.success().

We've written our worker class and the final class should look similar to :

public class MyWorker extends Worker {

    private static int count = 0;

    public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {
        count++;
        Log.d("MyWorker", "worker called - " + count + " time(s)");
        return Result.success();
    }
}

๐Ÿ‘‰๐Ÿผ Create UI

  • In activity_main.xml create a Button inside the LinearLayout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    tools:context=".MainActivity"
    android:layout_margin="16dp">

    <Button
        android:id="@+id/trigger_job"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="Trigger Job" />

</LinearLayout>

๐Ÿ‘‰๐Ÿผ Start worker on button press

  • In MainActivity, create a Button type variable and map it to xml button using findViewById() :
Button scheduleJob = findViewById(R.id.trigger_job);
  • Set a new onClickListener() on button :
scheduleJob.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        });
  • Inside the onClickListener(), assuming that we don't want to run this job when the battery is low, create Constraints for the job :
Constraints constraints = new Constraints.Builder()
                        .setRequiresBatteryNotLow(true)
                        .build();

๐Ÿ’ก Constraints as the name implies are a set of conditions that must be satisfied for the job to execute. For more details please refer this link.

  • Create a periodic work request, we need to specify our worker class, time, and time unit in which our task will be executed at least once as long as the constraints are satisfied.
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
                        .setConstraints(constraints)
                        .build();
  • Enqueue this periodic work request. We need to provide a unique name to be used by this worker, whether to replace or keep the pending (uncompleted) request, and the periodicWorkRequest object that we have created previously. We'll display a toast on the screen to notify the user that work has been scheduled.
WorkManager workManager = WorkManager.getInstance(getApplicationContext());
                workManager.enqueueUniquePeriodicWork("Counter", ExistingPeriodicWorkPolicy.KEEP,periodicWorkRequest);
                Toast.makeText(MainActivity.this, "๐ŸŽ‰ Scheduled job!", Toast.LENGTH_SHORT).show();

The MainActivity class will look similar to this :

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button scheduleJob = findViewById(R.id.trigger_job);
        scheduleJob.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Constraints constraints = new Constraints.Builder()
                        .setRequiresBatteryNotLow(true)
                        .build();

                PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
                        .setConstraints(constraints)
                        .build();

                WorkManager workManager = WorkManager.getInstance(getApplicationContext());
                workManager.enqueueUniquePeriodicWork("Counter", ExistingPeriodicWorkPolicy.KEEP,periodicWorkRequest);
                Toast.makeText(MainActivity.this, "๐ŸŽ‰ Scheduled job!", Toast.LENGTH_LONG).show();
            }
        });
    }
}

๐Ÿ’ป Let's run the code

๐Ÿ–ฑ Click the button on the UI : Screenshot_1612325827.png

๐Ÿ‘€ Observe in the logcat : Screenshot 2021-02-03 114433.png

โŒš After some time we see : Screenshot 2021-02-03 121623.png

๐Ÿ“ด After a reboot, we again see : Screenshot 2021-02-03 122424.png

๐Ÿฅณ Good work. Mission Accomplished!

๐Ÿ’ฝ Code can be downloaded from here : github.com/jaikherajani/AndroidWorkerManager