我正在使用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()时,该错误可能导致作业运行两次:请参见herehere

关于Firebase JobDispatcher呢?

我看到Firebase JobDispatcher带有 Trigger.NOW trigger(“意味着作业应在其运行时约束得到满足后立即运行”)。如果JobScheduler本身不支持此功能,那也许就是这样的方法?我被Firebase JobDispatcher推迟了,因为它似乎正在使用大锤破解螺母……而且看来Firebase完全是关于云消息传递等的,与本地任务调度相去甚远(应该是完全是本地关注的问题)。它似乎需要Google Play服务,这对于本地任务调度来说似乎完全没有必要。此外,如果Firebase立即触发触发,并且Firebase仅针对Android L +使用JobScheduler,那么一定可以直接使用JobScheduler直接执行此操作,而无需依赖Firebase吗?

编辑:我现在已经尝试过了,甚至Trigger.NOW也不能保证立即响应...实际上,我发现我的设备上几乎有30秒的延迟,这很奇怪。

失败了...

目前,我看到的确保立即执行(如果满足约束)的唯一方法是不使用JobScheduler

或者也许手动检查初始约束,如果满足所有约束,则以setOverrideDeadline()为0运行作业,否则,不使用setOverrideDeadline()运行它。

仅仅具有控制JobScheduler本身的时间的能力似乎似乎更可取,就像您可以使用setWindow() AlarmManager 方法可以控制的那样。

最佳答案

作业调度程序用于调度作业:定期触发,具有延迟或对其他作业的限制。
如果您想立即解雇工作,则无需安排时间,只需启动它即可。

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

关于android - JobScheduler : controlling delay from constraints being met to job being run,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39363839/

10-10 09:25