Skip to content

Instantly share code, notes, and snippets.

@adavis
Last active March 2, 2019 15:18
Show Gist options
  • Save adavis/6e54e3ce48b4090ecd5e352f3ef44b09 to your computer and use it in GitHub Desktop.
Save adavis/6e54e3ce48b4090ecd5e352f3ef44b09 to your computer and use it in GitHub Desktop.
Background Jobs with Android Job and Dagger
@Singleton
@Component(
modules = {
AppModule.class, JobsModule.class
}
)
public interface AppComponent
{
Application getApplication ();
JobManager getJobManager ();
}
@Singleton
public class AppJobCreator implements JobCreator
{
@Inject
Map<String, Provider<Job>> jobs;
@Inject
AppJobCreator ()
{
}
@Override
public Job create (String tag)
{
Provider<Job> jobProvider = jobs.get( tag );
return jobProvider != null ? jobProvider.get() : null;
}
}
@Singleton
public class BookService
{
private final JobManager jobManager;
@Inject
public BookService (JobManager jobManager)
{
this.jobManager = jobManager;
}
void submitBook (String name)
{
jobManager.schedule( SendBookRequestJob.buildJobRequest( name ) );
}
}
// Job Scheduler
compile 'com.evernote:android-job:1.1.3'
compile "com.google.android.gms:play-services-gcm:$playServicesVersion"
@Module
public class JobsModule
{
@Provides
@Singleton
JobManager provideJobManager (Application application, AppJobCreator jobCreator)
{
JobManager.create( application ).addJobCreator( jobCreator );
return JobManager.instance();
}
@Provides @IntoMap
@StringKey( SendBookRequestJob.JOB_TAG )
Job provideSendBookRequestJob (BookApi api, Bus bus)
{
return new SendBookRequestJob( api, bus );
}
}
public class SendBookRequestJob extends Job
{
static final String JOB_TAG = "send_book_request_tag";
private static final String PARAM_BOOK_NAME = "book_name";
private final BookApi api;
private final Bus bus;
@Inject
SendBookRequestJob (BookApi api, Bus bus)
{
this.api = api;
this.bus = bus;
}
@NonNull
@Override
protected Result onRunJob (final Params params)
{
PersistableBundleCompat extras = params.getExtras();
String name = extras.getString( PARAM_BOOK_NAME, "" );
if ( submitRequest( name ) )
{
return Result.SUCCESS;
}
return Result.FAILURE;
}
boolean submitRequest (String name)
{
api.submitBook( name ).enqueue( new Callback<Book>()
{
@Override
public void onResponse (Call<Book> call, Response<Book> response)
{
if ( response.isSuccessful() )
{
bus.post( new SubmissionSuccessEvent( response.body() ) );
}
}
@Override
public void onFailure (Call<Place> call, Throwable t)
{
bus.post( new SubmissionErrorEvent() );
}
} );
return true;
}
public static JobRequest buildJobRequest (String name)
{
PersistableBundleCompat extras = new PersistableBundleCompat();
extras.putString( PARAM_BOOK_NAME, name );
return new JobRequest.Builder( SendBookRequestJob.JOB_TAG )
.setExecutionWindow( 5_000L, 10_000L )
.setBackoffCriteria( 20_000L, JobRequest.BackoffPolicy.EXPONENTIAL )
.setRequiredNetworkType( JobRequest.NetworkType.CONNECTED )
.setExtras( extras )
.setRequirementsEnforced( true )
.setPersisted( true )
.build();
}
}
@sergio11
Copy link

sergio11 commented Dec 1, 2016

Great example. When I use this approach on my project I get the following exception, when i run the job for second time:

FATAL EXCEPTION: pool-272-thread-1
Process: es.usal.bisite.ebikemotion, PID: 3690
java.lang.IllegalStateException: Job for tag %s was already run, a creator should always create a new Job instance
at com.evernote.android.job.JobExecutor.execute(JobExecutor.java:73)
at com.evernote.android.job.JobProxy$Common.executeJobRequest(JobProxy.java:181)
at com.evernote.android.job.v21.PlatformJobService$1.run(PlatformJobService.java:71)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment