提问人:drmrbrewer 提问时间:9/7/2016 最后编辑:Communitydrmrbrewer 更新时间:3/16/2023 访问量:3041
JobScheduler:控制从满足约束到作业运行的延迟
JobScheduler: controlling delay from constraints being met to job being run
问:
我正在使用 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
触发器(“意味着作业应在满足其运行时约束后立即运行”)。如果本机不支持此功能,也许这就是要走的路?我被 Firebase JobDispatcher 推迟了,因为它似乎在用大锤敲碎坚果......而且 Firebase 似乎都是关于云消息传递等的,这与本地任务调度相去甚远(这应该完全是本地关注的问题)。而且它似乎需要 Google Play 服务,这对于本地任务调度来说似乎完全没有必要。此外,如果 Firebase 可以立即触发它,而 Firebase 只用于 Android L+,那么肯定可以在不依赖 Firebase 的情况下直接执行此操作吗?JobScheduler
JobScheduler
JobScheduler
编辑:我现在已经尝试过了,甚至不能保证立即响应......事实上,我发现我的设备上几乎正好有 30 秒的延迟,这很奇怪。Trigger.NOW
如果做不到这一点......
目前,我能看到确保立即执行(如果满足约束条件)的唯一方法是不使用 .JobScheduler
Or maybe do the initial constraints check manually, and run the job with a of 0 if all constraints are met, otherwise run it without .setOverrideDeadline()
setOverrideDeadline()
It would seem far preferable just to have the ability to control the timing of itself, a bit like you can with the setWindow()
method of .JobScheduler
AlarmManager
答:
A job scheduler is to schedule jobs: triggering periodically, with delay or with constraints to other jobs. If you want to fire a job instantly, it doesn't need to bee scheduled, just launch it.
ConnectivityManager cm =
(ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnectedOrConnecting()) {
// If there is connectivity, Launch the job directly here
} else {
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);
}
评论
JobScheduler
JobService
JobScheduler
Service
JobService
startService()
JobService
onStartJob()
startService()
JobParameters
startService()
onStartJob()
null
JobParameters