Job Scheduler not running within set interval

廉价感情. 提交于 2019-11-30 13:12:34

I was having this problem and after review some blogs and the official documentation, I realised that JobScheduler is having difference behavior on Android N(24 and 25). JobScheduler works with a minimum periodic of 15 mins.

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static void setJobScheduler(Context context){
        Log.v(TAG, "Job Scheduler is starting");
        JobScheduler jobScheduler = (JobScheduler)context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
        ComponentName serviceName = new ComponentName(context, JobService.class);
        JobInfo jobInfo;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N){
            jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
                    .setPeriodic(900000)
                    .build();
        }else{
            jobInfo = new JobInfo.Builder(JOB_ID, serviceName)
                    .setPeriodic(Constants.TIME_INTERVAL)
                    .build();
        }
        jobScheduler.schedule(jobInfo);
    }

Instead of setPeriodic(int) use setMinimumLatency(int) with setOverrideDeadline(int). These two methods will adjust the interval of your JobScheduler.

You should call jobFinished(jobParams,needResheduleBoolean);, after this call only the job will execute again, this is how the job knows it has finished execution so can start once more.

JobInfo.Builder builder = new JobInfo.Builder(1,new ComponentName(getPackageName(), JobSchedulerService.class.getName()));

builder.setPeriodic(3000);


Edited

MainActivity.java

public class MainActivity extends Activity {

    private JobScheduler mJobScheduler;
    private Button mScheduleJobButton;
    private Button mCancelAllJobsButton;

    @Override
    protected void onCreate( Bundle savedInstanceState ) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );
        mJobScheduler = (JobScheduler) getSystemService( Context.JOB_SCHEDULER_SERVICE );
        mScheduleJobButton = (Button) findViewById( R.id.schedule_job );
        mCancelAllJobsButton = (Button) findViewById( R.id.cancel_all );

        mScheduleJobButton.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                JobInfo.Builder builder = new JobInfo.Builder( 1,
                        new ComponentName( getPackageName(), JobSchedulerService.class.getName() ) );

                builder.setPeriodic( 3000 );


                if( mJobScheduler.schedule( builder.build() ) <= 0 ) {
                    //If something goes wrong
                }
            }
        });

        mCancelAllJobsButton.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick( View v ) {
                mJobScheduler.cancelAll();
            }
        });
    }
}

just need to change

new JobInfo.Builder(1, new ComponentName(this, UpdateDatabaseService.class))

to

new JobInfo.Builder( 1, new ComponentName( getPackageName(), JobSchedulerService.class.getName() ) )

builder.setPeriodic( 3000 ); will set JobInfo in 3000 ms schedule and called after every 3 seconds.

JobSchedulerService.java

public class JobSchedulerService extends JobService {

    private Handler mJobHandler = new Handler( new Handler.Callback() {
        @Override
        public boolean handleMessage( Message msg ) {
            Toast.makeText( getApplicationContext(), "JobService task running", Toast.LENGTH_SHORT ).show();
            jobFinished( (JobParameters) msg.obj, false );
            return true;
        }
    } );

    @Override
    public boolean onStartJob(JobParameters params ) {
        mJobHandler.sendMessage( Message.obtain( mJobHandler, 1, params ) );
        return true;
    }

    @Override
    public boolean onStopJob( JobParameters params ) {
        mJobHandler.removeMessages( 1 );
        return false;
    }

}

AndroidManifest.xml

<service android:name=".JobSchedulerService"
            android:permission="android.permission.BIND_JOB_SERVICE" />

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <Button
        android:id="@+id/schedule_job"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Schedule Job"/>

    <Button
        android:id="@+id/cancel_all"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Cancel All"/>

</LinearLayout>

From android documentation of setPeriodic ,

setPeriodic (long intervalMillis) : Specify that this job should recur with the provided interval, not more than once per period. You have no control over when within this interval this job will be executed, only the guarantee that it will be executed at most once within this interval.

so it is clearly mentioned that it is not necessary that job will run during this time. If you want to run a job at some periodic specific time , then you shoulf better use AlarmManager Api with setRepeating() method . Follow this link below for your requirements .

https://developer.android.com/training/scheduling/alarms.html#set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!