Sachit Wadhawan

How to Schedule Jobs in Android using FireBase Job Dispatcher?

Firebase JobDispatcher is a library for scheduling jobs

Recently I worked on a project where I needed to perform a task once after every 3 hours of using the application. I thought of using the AlarmManager for this. Later I got to know that the task should also be performed whenever the network is available. In which case, AlarmManager will not be able to take care of the additional requirement.

Although Android provides us the GcmNetworkManager for the network availability requirement, there is another challenge while using GcmNetworkManager where a user doesn’t have Google play services installed in his/her mobile. I know that it is rare that Android mobiles don’t have Google play services but I can’t take that risk. So I decided to use Android JobScheduler that is more suitable for these kinds of constraints. JobScheduler works great when our app wants to perform a specific task only in cases when-

1. User’s mobile gets connected to power supply.
2. There is a network availability.

However, JobScheduler only works with API level >=21. Our app supports the earlier versions too, so JobScheduler also wasn’t able to fulfill my requirement.

Then, I came to know about FireBase Job Dispatcher which not only works the same as Android JobScheduler but also provides compatibility for lower versions. FireBase Job Dispatcher uses the same framework as of Android JobScheduler. I am using it in my project and it’s working like a charm.

All of us know about AlarmManager which is present from Android version 1. Later we saw some changes were made to save the battery of the device and boost the performance. The biggest issue with AlarmManager is that it works on the basis of time. For this issue, Google introduced JobScheduler which works well in most of the common conditions like charging of the device, availability of the network.

But we have another condition while using JobSchedular i.e. minimum SDK version must be >=21. What about for the app having minimum SDK version <21? Don’t worry and don’t be sad, we still have options for that.

GcmNetworkManager

If your application is running on the Lollipop or above version then GcmNetworkManager will work like a charm. It is same as JobScheduler in functionality as it is also using the same framework. But for the application having support below the Lollipop, you need to have Google play services installed in the device in which application is going to run.

FireBase Job Dispatcher

This library works well if a user doesn’t have Google play services installed and wants to run the application. This library uses AlarmManager in this condition internally. For the device running on Lollipop version, it uses JobScheduler. This library also has the same framework so there is no change in functionality.

How to schedule a job using FireBase Job Dispatcher?

Google has also recommended FireBase Job Dispatcher. Please visit this link for integrating FireBase Job Dispatcher in Android Studio.

Here is the snippet of creating a job.

Driver driver = new GooglePlayDriver(context);
        FirebaseJobDispatcher firebaseJobDispatcher = new FirebaseJobDispatcher(driver);

        Job constraintReminderJob = firebaseJobDispatcher.newJobBuilder()
                .setService(ReminderService.class)
                .setTag(REMINDER_JOB_TAG)
                .setConstraints(Constraint.DEVICE_CHARGING)
                .setLifetime(Lifetime.FOREVER)
                .setRecurring(true)
                .setTrigger(Trigger.executionWindow(
                        REMINDER_INTERVAL_SECONDS,
                        REMINDER_INTERVAL_SECONDS + SYNC_FLEXTIME_SECONDS
                ))
                .setReplaceCurrent(true)
                .build();

        firebaseJobDispatcher.schedule(constraintReminderJob);

Let’s take a look at the above snippet.

Job

There are several attributes to make a job.

  • A string tag that (within your app) uniquely identifies the Job.
  • A JobService subclass that will contain all the business logic related to the Job.
  • A JobTrigger will determine that the created Job is now ready to execute.
  • A set of Constraints is required in order to execute the created job. By default, it is empty which means that Job will be run as soon as the JobTrigger is activated.
  • A RetryStrategy is responsible for handling the failure conditions. The default is handled using exponential backoff strategy.
  • A lifetime that specifies the time of the job in which it should remain scheduled. The
    default is to keep the Job scheduled until the next boot.
  • Bundle is for user-supplied extras. This is an optional parameter.
  • A boolean indicates whether the Job should repeat or not. The default is false which means that the scheduled Job will execute only once.
  • A boolean indicates whether the scheduled Job should replace any pre-existing Job
    with the same tag or not. The default value for this boolean flag is false.

Once your job is ready, you can use schedule() method to schedule the job.

public static void scheduleJob(Context context) {
    FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context));
    Job job = createJob(dispatcher);
    dispatcher.schedule(job);
  }

 

ReminderService.class

public class ReminderService extends JobService {

    /**
     * This asynctask will run a job once conditions are met with the constraints
     * As soon as user device gets connected with the power supply. it will generate
     * a notification showing that condition is met.
     */
    private AsyncTask mBackgroundTask;

    @Override
    public boolean onStartJob(final JobParameters jobParameters) {
        mBackgroundTask = new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] objects) {
                Context context = ReminderService.this;
                ReminderTasks.executeTasks(context, ReminderTasks.ACTION_CHARGING_REMINDER);
                Log.i("TAG", "onStartJob");
                return null;
            }

            @Override
            protected void onPostExecute(Object o) {
                /* false means, that job is done. we don't want to reschedule it*/
                jobFinished(jobParameters, false);
                Log.i("TAG", "onStartJob- OnPost");
            }
        };

        mBackgroundTask.execute();
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        if (mBackgroundTask != null) {
            mBackgroundTask.cancel(true);
        }
        Log.i("TAG", "onStopJob");
        /* true means, we're not done, please reschedule */
        return true;
    }
}

There are three methods that will be used while using FireBase Job Dispatcher.

onStartJob(JobParameters params)-This is the initial method that will be invoked when a job is called. It runs on the main thread. It will return a Boolean which tells whether a job is remaining or not. Returning true indicates that more work is remaining. We can call jobFinished() as soon as the job is completed.

onStopJob(JobParameters params)- This method is called when your job is stopped. The job can be stopped due to various reasons like if the running constraints associated with the job are no longer satisfied. It will return a Boolean which tells whether a job should be tried again or not. If returned true, then the framework will put up this job again for execution.

jobFinished(JobParameters params, boolean needsReschedule)-When job has been offloaded to a new thread, it should be called explicitly.

Cancel a Job

A job can be canceled using cancel() method by passing the tag as the argument.

dispatcher.cancel("my-unique-tag");

 

If you need to cancel all the jobs for your application package then call cancelAll() method.

dispatcher.cancelAll();

 

That’s all about FireBase Job Dispatcher. Hope you have fun using it!

References

  1. https://www.diycode.cc/projects/firebase/firebase-jobdispatcher-android
  2. https://github.com/firebase/firebase-jobdispatcher-android