在Android中使用JobScheduler调度作业

9

我在使用新的Android API 21中的JobScheduler时遇到了任务调度的问题。以下是我用60秒间隔安排任务的代码:

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

我的JobService只在Logcat中打印运行时间,但日志显示服务在这些时刻运行:

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

奇怪的是,由于我使用了setPeriodic(60000)方法,Job 应该每 1 分钟至少执行 1 次。而且,它运行时间间隔增加的情况也很奇怪。此时时间是2015年3月18日星期三09:09:00 BRT,但 Job 没有再被执行过。

这是不是与 JobScheduler API 有关问题?(我在 Nexus 5 上运行 Android 5.0.1)

3个回答

9
时间的变化与重试作业的回避标准有关。默认设置为指数级别。我猜想,当你完成作业时,也没有正确地调用jobFinished(JobParameters params,boolean needsReschedule)。 我写了一篇博客文章,重点介绍了JobScheduler的所有小细节。强烈建议阅读。

作业调度程序运行得很好,但如果我锁定屏幕,时间间隔会不断变化。有没有适合我的解决方案? - Jaichander
工作调度程序做得不好的一件事是无法确保您的作业准确运行的时间。我认为这可能是按预期工作的情况。通过调整参数,您可能能够解决它。从技术上讲,现在应该使用WorkManager。几周前有一个Google IO演讲。https://www.youtube.com/watch?v=IrKoBFLwTN0 https://developer.android.com/reference/kotlin/androidx/work/WorkManager - MinceMan
我已经尝试过了,问题是Work Manager只允许每15分钟运行一次周期性作业,而我需要每60秒运行一次作业。有没有其他方法可以在精确的时间范围内实现这个结果?我已经发布了一个问题,请您详细说明如何在没有时间延迟的情况下完成它:https://stackoverflow.com/questions/50753823/android-i-am-facing-issue-while-setting-timertask-perodic-interval-when-app-is - Jaichander

5
我曾经遇到了同样的问题,我认为这可能与JobInfo类的内部要求有关: JobInfo源代码
    /* Minimum interval for a periodic job, in milliseconds. */
private static final long MIN_PERIOD_MILLIS = 15 * 60 * 1000L;   // 15 minutes

看起来JobInfo不允许您设置比它更小的时间间隔。


1

//以下是我在一个项目中使用的代码,它对我来说运行得很好。

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

我们按照以下指示定义了服务类:
@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;
}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接