我正在使用 JobScheduler 来安排作业。主要是我将它用于该.setRequiredNetworkType()
方法,它允许您指定您只希望在建立网络连接(或更具体地说是未计量连接)时安排作业。
我正在使用以下非常简单的代码来安排我的工作:
PersistableBundle extras = new PersistableBundle();
extras.putInt("anExtraInt", someInt);
int networkConstraint = useUnmetered ? JobInfo.NETWORK_TYPE_UNMETERED : JobInfo.NETWORK_TYPE_ANY;
ComponentName componentName = new ComponentName(context, MyJobService.class);
JobInfo jobInfo = new JobInfo.Builder(jobId, componentName)
.setRequiredNetworkType(networkConstraint)
.setExtras(extras)
.build();
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.schedule(jobInfo);
因此,调度只有一个约束:网络连接(可能是“任意”或“未计量”)。
问题的简短版本
如何指定满足所有约束并实际运行作业的最大延迟,例如“在网络连接后 2 秒内运行作业”?
加长版(含杂文)
问题
我发现在某些设备上,如果在已经满足网络约束的时间段内安排了作业,则作业将立即运行(或者速度足够快以被用户感知)。
但是在其他设备上,即使已经有合适的网络连接可用(以便作业可以立即运行),在实际运行之前也会有很大的延迟。因此,如果这是对用户操作的响应,则给人的印象是什么都没有发生,并且应用程序已损坏。
现在,我很清楚这可能是出于JobScheduler
……由系统来安排作业以最适合其他需求,并且不能保证作业会在所有约束条件下立即运行满意。
但是,如果需要,能够对其进行一些控制会很好。因此,对于按计划进行的工作,无需用户参与,让系统完全控制精确的时间是很好的。
但是在作业响应用户操作的情况下,我希望作业立即运行......假设网络连接在那里。(如果没有连接,则可以显示一条消息,说明当网络连接恢复时将执行该操作,JobScheduler
然后确保在网络恢复时作业运行。)
setOverrideDeadline() 不是解决方案吗?
我可以看到JobInfo.Builder
确实有一个setOverrideDeadline()
方法,这几乎是我想要的。但这指定了从调度作业时开始的最大延迟(即,即使不满足所有约束,也要在 10 秒内运行作业),而不是从满足所有约束时(即在所有约束后 10 秒内运行作业)满足约束)。
编辑:似乎有一个烦人的错误,它可能导致在使用时作业运行两次setOverrideDeadline()
:请参阅此处和此处。
Firebase JobDispatcher 呢?
我看到Firebase JobDispatcher有一个Trigger.NOW
触发器(“意味着作业应在其运行时约束得到满足后立即运行”)。JobScheduler
如果本机不支持这一点,也许这就是要走的路?我被 Firebase JobDispatcher 推迟了,因为它似乎是在使用大锤来解决问题......而且 Firebase 似乎都是关于云消息传递等,这与本地任务调度相距甚远(应该是完全本地关注)。而且它似乎需要 Google Play 服务,这对于本地任务调度来说似乎完全没有必要。此外,如果使用 Firebase 可以立即触发,并且 Firebase 仅JobScheduler
用于 Android L+,那么肯定可以直接使用JobScheduler
不依赖 Firebase?
编辑:我现在已经尝试过了,甚至Trigger.NOW
不能保证立即响应......事实上,我发现我的设备上几乎正好有 30 秒的延迟,这很奇怪。
做不到...
目前,我能看到确保立即执行(如果满足约束)的唯一方法是不使用JobScheduler
.
或者可能手动进行初始约束检查,setOverrideDeadline()
如果满足所有约束,则使用 0 运行作业,否则运行不带setOverrideDeadline()
.
拥有控制自身时间的能力似乎要好得多JobScheduler
,有点像你可以使用的setWindow()
方法AlarmManager
。