Планировщик заданий не работает в пределах заданного интервала

Я пытаюсь использовать API планировщика заданий android, и все, что я пытаюсь сделать, это запустить планировщик заданий каждые 5 секунд. Однако, когда я запускаю его, соответствующая служба ударяется каждые две минуты. У меня есть журнал, который документирует каждый раз, когда служба ударяется. Я не знаю, почему это происходит. Может ли планировщик заданий иметь минимальное время интервала. Мой код просто...

JobInfo jobInfo = new JobInfo.Builder(1, new ComponentName(this, UpdateDatabaseService.class))
            .setPeriodic(5000)
            .build();

JobScheduler jobScheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);

Проблема возникла, когда я пытался выполнять ежедневную задачу, но она вызывала бы службу несколько раз в течение этого дня и не следовала руководящим принципам времени.

Дайте мне знать, что вы думаете.

Ответ 1

У меня была эта проблема, и после просмотра некоторых блогов и официальной документации я понял, что JobScheduler имеет разное поведение на Android N (24 и 25). JobScheduler работает с минимальной периодичностью 15 минут.

@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);
    }

Ответ 2

Вместо setPeriodic(int) используйте setMinimumLatency(int) с setOverrideDeadline(int). Эти два метода отрегулируют интервал вашего JobScheduler.

Ответ 3

Вы должны позвонить jobFinished(jobParams,needResheduleBoolean);, после этого вызова будет выполняться только задание, это значит, что задание знает, что оно завершено, поэтому можно запустить еще раз.

Ответ 4

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();
            }
        });
    }
}

просто нужно изменить

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

к

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

builder.setPeriodic( 3000 ); установит JobInfo в расписании 3000 мс и вызывается через каждые 3 секунды.

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>

Ответ 5

Из документации по android setPeriodic ,

setPeriodic (long intervalMillis): Укажите, что это задание должно повторяться с указанным интервалом, не чаще одного раза за период. Вы не контролируете, когда в течение этого интервала будет выполнено это задание, а только гарантируете, что оно будет выполнено не более одного раза в течение этого интервала.

поэтому ясно сказано, что не обязательно, чтобы задание выполнялось в течение этого времени. Если вы хотите запускать задание в определенное периодическое время, лучше использовать AlarmManager Api с методом setRepeating(). Перейдите по этой ссылке ниже для ваших требований.

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

Ответ 6

Вам нужно минимум 30 секунд, чтобы ждать следующей работы