JobScheduler:控制从满足约束到运行作业的延迟

问题描述 投票:0回答:2

我正在使用 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 秒内运行作业)满足所有约束的 10 秒)。 编辑:似乎有一个恼人的错误,可能会导致使用

setOverrideDeadline()

时作业运行两次:请参阅

here
here

Firebase JobDispatcher 怎么样?

我看到

Firebase JobDispatcher

有一个 Trigger.NOW 触发器

(“意味着作业应该在满足其运行时约束后立即运行”)。如果 
JobScheduler 本身不支持的话,也许这就是要走的路?我已经被 Firebase JobDispatcher 推迟了,因为它看起来像是在使用大锤来破解坚果......而且 Firebase 似乎都是关于云消息传递等,这与本地任务调度相去甚远(这应该完全是)当地关注)。而且它似乎需要 Google Play 服务,这对于本地任务调度来说似乎完全没有必要。此外,如果 Firebase 可以立即触发,并且 Firebase 仅使用 Android L+ 的
JobScheduler
,那么肯定可以直接使用
JobScheduler
执行此操作,而不依赖 Firebase?
编辑:我现在已经尝试过这个,甚至

Trigger.NOW

也不能保证立即响应...事实上,我发现我的设备上有几乎正好 30 秒的延迟,这很奇怪。

失败了...

目前,我认为确保立即执行(如果满足约束)的唯一方法是

使用JobScheduler

或者可以手动进行初始约束检查,如果满足所有约束,则以 

setOverrideDeadline()

为 0 运行作业,否则在没有

setOverrideDeadline()
的情况下运行作业。
最好能够控制 

JobScheduler

本身的时间,就像使用

setWindow()
AlarmManager
方法一样。
    

android alarmmanager android-jobscheduler
2个回答
0
投票


-1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.