【问题标题】:Android Job Scheduler - Schedule Job to execute immediately and exactly onceAndroid Job Scheduler - 安排作业立即执行一次
【发布时间】:2017-08-15 11:45:29
【问题描述】:

我正在尝试使用 android 作业调度程序来安排作业立即执行一次。

        JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);

        jobScheduler.cancel(1);

        PersistableBundle bundle = new PersistableBundle();
        bundle.putInt(JobFlags.KEY_PERIODIC_SYNC_JOB, JobFlags.JOB_TYPE_INITIAL_FETCH);

        jobScheduler.schedule(new JobInfo.Builder(1,
                new ComponentName(context, SyncJobLollipop.class))
                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                .setExtras(bundle)
                .setMinimumLatency(10)
                .setOverrideDeadline(24 * 3600 * 1000)
                .build());

但它运行了大约 3 4 次。这里有什么问题?

这是作业类本身:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class SyncJobLollipop extends JobService implements JobFinishedListener {

    @Inject
    SyncJobBackend jobBackend;

    private JobParameters jobParameters;

    @Override
    public boolean onStartJob(JobParameters jobParameters) {
        ((MyApplication)getApplication()).getAppComponent().inject(this);
        this.jobParameters = jobParameters;
        PersistableBundle bundle = jobParameters.getExtras();
        int type = bundle.getInt(JobFlags.KEY_PERIODIC_SYNC_JOB);
        jobBackend.onStartJob(type, this);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters jobParameters) {
        jobBackend.onStopJob();
        return false;
    }

    @Override
    public void onJobFinished(boolean success) {
        jobFinished(jobParameters, !success);
    }

}

P.S.:我已经检查过我每次都使用错误值完成作业。

【问题讨论】:

  • 你确定jobScheduler.schedule 只被调用一次吗?
  • 是的。它只被调用一次。我在 Android N 上。
  • @dumb_terminal 你的包中有JobFlags.KEY_PERIODIC_SYNC_JOB,我猜它是periodic
  • 我同意这个名字很混乱,但这与让它定期无关,所有与时间表相关的代码都在这里发布。 @Merka

标签: android android-jobscheduler


【解决方案1】:

要只运行一次作业,您应该在后台工作程序中运行 onStartJob(...) 中的代码,并在调用 onStopJob(...) 时删除其回调。

public class SyncJobLollipop extends JobService {
    final Handler workHandler = new Handler();
    Runnable workRunnable;

    @Override
    public boolean onStartJob(JobParameters params) {
        workRunnable = new Runnable() {
            @Override
            public void run() {
                // do your work here,
                // such as jobBackend.onStartJob(type, this)

                boolean reschedule = false;
                jobFinished(params, reschedule);
            }};
        workHandler.post(workRunnable);
        return true;
    }

    @Override
    public boolean onStopJob(JobParameters params) {
        workHandler.removeCallbacks(workRunnable);
        return false;
    }
}

要立即运行它,您应该将“最小延迟”和“覆盖期限”都设置为 1。

jobScheduler.schedule(new JobInfo.Builder(1,
            new ComponentName(context, SyncJobLollipop.class))
            .setExtras(bundle)
            .setMinimumLatency(1)
            .setOverrideDeadline(1)
            .build());

请注意,操作系统的 Doze 模式可能会将 JobScheduler 任务推迟到“维护期”或设备以其他方式唤醒。但是,上面的代码只会在 Doze 模式的 /outside/ 运行,所以作业应该几乎没有延迟地调度。

【讨论】:

  • onJobStart 是否保证在调用 jobScheduler.schedule 后立即运行?
  • 我也添加了关于setOverrideDeadline的部分。是的,它会立即运行。
猜你喜欢
  • 1970-01-01
  • 2012-02-22
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
相关资源
最近更新 更多