Scheduling A Periodic Background Job Using Android Work Manager

Written by jaikherajani | Published 2021/02/04
Tech Story Tags: android | android-app-development | android-development | android-mobile-app | android-tutorial | android-app-tutorials | app-development | mobile-app-developers

TLDRvia the TL;DR App

šŸŽÆ Objective

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

šŸ¤” What is 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

1. Create an android project with an Empty activity. SelectĀ Launcher ActivityĀ and Generate layout file options.
2. 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 latest available version of this library, please referĀ this page.

šŸ‘‰šŸ¼ Create a Worker class

1. Create a new classĀ 
MyWorker
Ā and it should extendĀ 
Worker
.
2. Create a parameterized constructor :
public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }
3. Override and implement theĀ 
doWork()
Ā method :
@NonNull
    @Override
    public Result doWork() {
        return null;
    }
4. Create a new static integer variable called count.
5. 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 asynchronous task I will write another tutorial.
6. 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

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

            }
        });
3. Inside theĀ onClickListener(), assuming that we don't want to run this job when battery is low, create Constraints for the job :
Constraints constraints = new Constraints.Builder()
                        .setRequiresBatteryNotLow(true)
                        .build();
šŸ’” Constraints as the name implies are set of conditions that must be satisfied for the job to execute. For more details please referĀ this link.
4. Create a periodic work request, we need to specify our worker class, time and its unit in which our task will be execute at least once as long as the constraints are satisfied.
PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest.Builder(MyWorker.class, 15, TimeUnit.MINUTES)
                        .setConstraints(constraints)
                        .build();
5. 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Ā 
periodicWorkRequest
Ā object that we have created previously. We'll display a toast on the screen to notify 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 :
šŸ‘€ Observe in the logcat :
āŒš After some time we see :
šŸ““ After a reboot, we again see :

šŸ„³ Good work. Mission Accomplished!

šŸ’½ Code can be downloaded from here : github.com/jaikherajani/AndroidWorkerManager

Written by jaikherajani | Likes to code and build apps.
Published by HackerNoon on 2021/02/04