FirebaseJobDispatcher

The Firebase alternative to JobScheduler – is able to schedule tasks with complex conditions and execute them when those conditions are met. Provides compatibility all the way back to API 9 (Gingerbread). Requires Google Play Services to be installed on the target phone as it depends on GooglePlayDriver.

Add dependencies to build.gradle:

implementation 'com.firebase:firebase-jobdispatcher:0.8.5'

Create a JobService class and add the 2 obligatory overrides:

public class MyJobService extends JobService {
    @Override
    public boolean onStartJob(JobParameters job) {
        // Do some work here
        return false; // Answers the question: "Is there still work going on?"
    }

    @Override
    public boolean onStopJob(JobParameters job) { // This method is called if the system has determined that you must stop execution of your job even before you've had a chance to call jobFinished
        return false; // Answers the question: "Should this job be retried?"
    }
}

As the JobService runs on the main thread, potentially slow processes should be handed off to an AsyncTask. So alternatively:

public class MyJobService extends JobService {
    private AsyncTask mNetworkTask;
    @Override
    public boolean onStartJob(final JobParameters job) {
        mNetworkTask = new AsyncTask() {
            @Override
            protected Object doInBackground(Object[] objects) {
                // Do something
                return null;
            }

            @Override
            protected void onPostExecute(Object o) { // When your AsyncTask has finished you must inform the JobService
                jobFinished(job, false); // Second parameter tells the Jobservice whether the task needs to be rescheduled (depends on RetryStrategy, set in FirebaseJobDispatcher code below)
            }
        };
        mNetworkTask.execute();
        return true; // There is still work going on
    }

    @Override
    public boolean onStopJob(JobParameters job) { // This method is called if the system has determined that you must stop execution of your job even before you've had a chance to call jobFinished
        return false; // Answers the question: "Should this job be retried?"
    }
}

Add the service to the AndroidManifest.xml:

<service
    android:exported="false"
    android:name=".MyJobService">
    <intent-filter>
        <action android:name="com.firebase.jobdispatcher.ACTION_EXECUTE"/>
    </intent-filter>
</service>

The actual code:

FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(new GooglePlayDriver(context)); // Create a new dispatcher using the Google Play driver
Bundle myExtrasBundle = new Bundle();
myExtrasBundle.putString("some_key", "some_value");

Job myJob = dispatcher.newJobBuilder()
    .setService(MyJobService.class) // the JobService that will be called - ESSENTIAL
    .setTag("my-unique-tag") // uniquely identifies the job - ESSENTIAL
    .setRecurring(false) // one-off job
    .setLifetime(Lifetime.UNTIL_NEXT_BOOT) // don't persist past a device reboot
    .setTrigger(Trigger.executionWindow(0, 60)) // start between 0 and 60 seconds from now
    .setReplaceCurrent(false) // don't overwrite an existing job with the same tag
    .setRetryStrategy(RetryStrategy.DEFAULT_EXPONENTIAL) // retry with exponential backoff
    .setConstraints( // constraints that need to be satisfied for the job to run
        Constraint.ON_UNMETERED_NETWORK, // only run on an unmetered network
        Constraint.DEVICE_CHARGING // only run when the device is charging
    )
    .setExtras(myExtrasBundle)
    .build();

dispatcher.mustSchedule(myJob); // Throws exception if fails (ScheduleFailedException)
OR
dispatcher.schedule(myJob); // Returns one of (int value) SCHEDULE_RESULT_SUCCESS, SCHEDULE_RESULT_UNKNOWN_ERROR, SCHEDULE_RESULT_NO_DRIVER_AVAILABLE, SCHEDULE_RESULT_UNSUPPORTED_TRIGGER, SCHEDULE_RESULT_BAD_SERVICE

To cancel a job:

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

To cancel all jobs:

dispatcher.cancelAll();

ud851-Exercises-student\Lesson10-Hydration-Reminder\T10.04