Giving Offline Support to the Open Event Organizer Android App

Open Event Organizer is an Android Application for Event Organizers and Entry Managers which uses Open Event API Server as a backend. The core feature of the App is to scan a QR code to validate an attendee’s check in. The App maintains a local database and syncs it with the server. The basic workflow of the attendee check in is – the App scans a QR code on an attendee’s ticket. The code scanned is processed to validate the attendee from the attendees database which is maintained locally. On finding, the App makes a check in status toggling request to the server. The server toggles the status of the attendee and sends back a response containing the updated attendee’s data which is updated in the local database. Everything described above goes well till the App gets a good network connection always which cannot be assumed as a network can go down sometimes at the event site. So to support the functionality even in the absence of the network, Orga App uses Job Schedulers which handle requests in absence of network and the requests are made when the network is available again. I will be talking about its implementation in the App through this blog.

The App uses the library Android-Job developed by evernote which handles jobs in the background. The library provides a class JobManager which does most of the part. The singleton of this class is initialized in the Application class. Job is the class which is where actually a background task is implemented. There can be more than one jobs in the App, hence the library requires to implement JobCreator interface which has create method which takes a string tag and the relevant Job is returned. JobCreator is passed to the JobManager in Application while initialization. The relevant code is:

JobManager.create(this).addJobCreator(new OrgaJobCreator());

Initialization of JobManager in Application class

public class OrgaJobCreator implements JobCreator {
   @Override
   public Job create(String tag) {
       switch (tag) {
           case AttendeeCheckInJob.TAG:
               return new AttendeeCheckInJob();
           default:
               return null;
       }
   }
}

Implementation of JobCreator

public class AttendeeCheckInJob extends Job {
   ...
   ...
   @NonNull
   @Override
   protected Result onRunJob(Params params) {
       ...
       ...
       Iterable<Attendee> attendees = attendeeRepository.getPendingCheckIns().blockingIterable();
       for (Attendee attendee : attendees) {
           try {
               Attendee toggled = attendeeRepository.toggleAttendeeCheckStatus(attendee).blockingFirst();
               ...
           } catch (Exception exception) {
               ...
               return Result.RESCHEDULE;
           }
       }
       return Result.SUCCESS;
   }

   public static void scheduleJob() {
       new JobRequest.Builder(AttendeeCheckInJob.TAG)
           .setExecutionWindow(1, 5000L)
           .setBackoffCriteria(10000L, JobRequest.BackoffPolicy.EXPONENTIAL)
           .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
           .setRequirementsEnforced(true)
           .setPersisted(true)
           .setUpdateCurrent(true)
           .build()
           .schedule();
   }
}

Job class for attendee check in job

To create a Job, these two methods are overridden. onRunJob is where the actual background job is going to run. This is the place where you implement your job logic which should be run in the background. In this method, the attendees with pending sync are fetched from the local database and the network requests are made. On failure, the same job is scheduled again. The process goes on until the job is done. scheduleJob method is where the related setting options are set. This method is used to schedule an incomplete job.

So after this implementation, the workflow described above is changed. Now on attendee is found, it is updated in local database before making any request to the server and the attendee is flagged as pending sync. Accordingly, in the UI single tick is shown for the attendee which is pending for sync with the server. Once the request is made to the server and the response is received, the pending sync flag of the attendee is removed and double tick is shown against the attendee.

Links:
1. Documentation for Android-Job Library by evernote
2. Github Repository of Android-Job Library