Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scheduling Jobs with JobScheduler in Android

I have a problem with jobs schedules with JobScheduler in new Android API 21. This is the code what I schedule the job with 60 seconds interval like below:

ComponentName serviceName = new ComponentName(this, MyJobService.class);
JobInfo jobInfo = new JobInfo.Builder(0, serviceName)
        .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
        .setPeriodic(60000)
        .build();

My JobService only print the time of runtime in Logcat, but the log show that service run in this moments:

03-18 08:37:26.334: I/JOB(32662): Wed Mar 18 08:37:26 BRT 2015
03-18 08:37:56.364: I/JOB(32662): Wed Mar 18 08:37:56 BRT 2015
03-18 08:39:21.418: I/JOB(32662): Wed Mar 18 08:39:21 BRT 2015
03-18 08:41:51.670: I/JOB(32662): Wed Mar 18 08:41:51 BRT 2015
03-18 08:45:52.192: I/JOB(32662): Wed Mar 18 08:45:52 BRT 2015
03-18 08:54:20.678: I/JOB(32662): Wed Mar 18 08:54:20 BRT 2015

It's strange because the Job it should execute at least 1 time within 1 minute as I set with setPeriodic(60000) method. It is also curious how the interval increases between runs. At this moment the time is Wed Mar 18 09:09:00 BRT 2015 and the Job don't be executed more.

Is it a problem with JobScheduler API? (I'm running in Nexus 5 with Android 5.0.1)

like image 535
lucasb.aquino Avatar asked Mar 18 '15 12:03

lucasb.aquino


3 Answers

The time changing has to do with the Back-off Criteria for retrying jobs. By default it is set to exponential. I'm guessing that your also not correctly finishing your job when your done with it by calling jobFinished(JobParameters params, boolean needsReschedule).

I wrote a blog post which focus' on all of the little things with the JobScheduler. I highly recommend reading it.

like image 146
MinceMan Avatar answered Nov 14 '22 15:11

MinceMan


I had the same problem and I think it might be connected with the internal requirements of JobInfo class:

Source code for JobInfo

    /* Minimum interval for a periodic job, in milliseconds. */
private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L;   // 15 minutes

It looks like JobInfo won't allow you to put interval smaller than that.

like image 34
Mateusz Wlodarczyk Avatar answered Nov 14 '22 14:11

Mateusz Wlodarczyk


//Below are the code I am using in my one of the project and it is working fine for me.

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public void scheduleJob(Context context) {
        //https://kb.sos-berlin.com/pages/viewpage.action?pageId=3638048
        //Scheduler uses UTC times for all its internal operations. This ensures a continual flow of operation without breaks or repetitions regardless of any changes in local time.
        JobInfo.Builder builder = new JobInfo.Builder(JOB_ID, new ComponentName(context, MyService.class));//JobSchedulerService.class.getName()));
        builder.setPersisted(true); //persist across device reboots

        builder.setPeriodic((120 * 60 * 1000)); //run once after 2 hours seconds

        builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); // only if wifi avaiblable so they are not using bandwith
        builder.setRequiresDeviceIdle(false); // run not only if the device is idle
        builder.setRequiresCharging(false); // run not only if the device is charging

       // android.os.PersistableBundle bundle = new android.os.PersistableBundle();
        // bundle.putString(WEB_SERVICE_URL, "http://example.com?upload.php");
        //   builder.setExtras(bundle);

        //builder.setBackoffCriteria(1600, JobInfo.BACKOFF_POLICY_LINEAR);
        //BACKOFF_POLICY_LINEAR After one failure retry at 1 * your value, then at 2 * (your value), then 3 * (your value) and so on
        //BACKOFF_POLICY_EXPONENTIAL After one failure retry at your value, then at (your value)^2, (your value)^3 and so on
        //builder.setMinimumLatency(5 * 1000); //latency
        //builder.setOverrideDeadline(50 * 1000); //wait for criteria to be met, in 50 seconds if they have not then run anyways


        int test = jobScheduler.schedule(builder.build());
        if (test <= 0) {
            Utility.showDialog(context, "Service Error", "Service is not responding");
            //If something goes wrong
        }
    }

We have defined service class per instructed below:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class MyService extends JobService {

    @Override
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public boolean onStartJob(final JobParameters params) {

        Log.e(TAG, "onStartJob");

        String month = "3";
        String year = "2018";           
MyAsync myAsync = new MyAsync(MyService.this, arraydata, month, year, new SyncAsyncListener() {
                    @Override
                    public void onDataSuccess() {
                        try {
                            jobFinished(params, result);
                        } catch (Exception e) {

                        }
                    }
                });

                myAsync.execute();
            }
    return result;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
    return false;
}
}
like image 1
Ramapati Maurya Avatar answered Nov 14 '22 14:11

Ramapati Maurya