【问题标题】:Android jobScheduler won't stop with jobFinished(params, false)Android jobScheduler 不会停止 jobFinished(params, false)
【发布时间】:2016-09-26 02:22:54
【问题描述】:

我正在尝试创建一个 jobService。这是 onStartJob() 的样子。

@Override
public boolean onStartJob(JobParameters params) {
    Log.d(TAG, "onStartJob");
    Log.d(TAG, "Params= " + params.getJobId());
    param = params;
    jobFinished(params, false);
    //startAsync();
    return true;
}


@Override
public boolean onStopJob(JobParameters params) {
     Log.d(TAG, "onStopJob");
    return false;
}

这是应该开始工作的代码。

public void startJobScheduler(){
    Log.d(TAG, "inside startJobScheduler");
    Activity activity = this.cordova.getActivity();
    Context context = activity.getApplicationContext();


     mJobScheduler = (JobScheduler)context.getSystemService(Context.JOB_SCHEDULER_SERVICE );
     JobInfo.Builder job = new JobInfo.Builder(111, new ComponentName(context, JobSchedulerService.class));

     job.setPeriodic(60000);
     Log.d(TAG, "before mJobScheduler.schedule(job.build())");
     if( mJobScheduler.schedule( job.build() ) <= 0 ) {
         Log.d(TAG, "job schedule failed");
     }
    Log.d(TAG, "333");
}

我无法让它停下来。它只是保持每1-5分钟发射一次。我将 jobFinished(params, false) 放入 onStartJob() 并注释掉任务以在它开始后立即将其杀死,但它只是不断触发。似乎 jobFinished() 触发了某些事情,因为 onDestroy() 被调用并且我的服务被破坏了,但是随后另一个具有相同 ID 的作业进入并重新启动它。

我在清单中有 BIND_JOB_SERVICE,就像每个示例所示。

关于为什么 jobFinished(params, false) 似乎没有杀死 setPeriodic(60000) 的任何想法?

【问题讨论】:

    标签: java android service android-jobscheduler


    【解决方案1】:

    我使用了多个 JobService,为了停止一个特定的 Job,我使用了 job 的 id 来取消该 job。

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static void stopMyJob(Context context, int jobId) {
        JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
        scheduler.cancel(jobId);
    }
    

    首先我使用以下函数检查当前作业是否处于活动状态

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static boolean isJobActive(Context context, int jobId) {
        JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
        boolean hasBeenScheduled = false;
        for (JobInfo jobInfo : scheduler.getAllPendingJobs()) {
            if (jobInfo.getId() == jobId) {
                hasBeenScheduled = true;
                break;
            }
        }
        return hasBeenScheduled;
    }
    

    开始工作时,我将 id 传递给 jobInfo:

    JobInfo jobInfo = new JobInfo.Builder(jobId, componentName);
    

    同样的 jobid 我曾经通过调用我的函数 stopMyJob(context, jobID) 来停止工作。

    在大多数情况下,停止当前作业并从头开始重新启动作业很重要,如果它已经在运行,因为我将上面提到的两个功能都用作:

    if (isJobActive(activity, ANNOUNCEMENT_JOB_ID)) {
        Log.d(TAG, "Job will cancel as already exist");
        stopMessagingJob(activity, ANNOUNCEMENT_JOB_ID);
        }
        startMyJob(activity, ANNOUNCEMENT_JOB_ID);
    

    我的startMyJob(context, jobId) 看起来像:

        private static void startMyJob(final Context context, final int jobId) {
                ComponentName componentName = new ComponentName(context, MyJobService.class);
                    JobInfo jobInfo = new JobInfo.Builder(jobId, componentName)
                            .setPersisted(true).setPeriodic(TWENTY_MINUTES).build();
                    JobScheduler scheduler = (JobScheduler) context.getSystemService(JOB_SCHEDULER_SERVICE);
                    int resultCode = scheduler.schedule(jobInfo);
                    if (JobScheduler.RESULT_SUCCESS != resultCode) {
                     Log.d(TAG, "Job failed to start");
                    }
    }
    

    【讨论】:

      【解决方案2】:

      您已指定定期运行作业(每 60 秒),因此每 60~ 秒创建并执行一个新作业。 jobFinished() 特定于作业,仅表示它已完成执行。你还没有取消任何东西。

      您(当前)接受的答案适用于取消您计划的作业,但如果您想要的只是一个在 60 秒内执行然后停止的作业,您应该省略 setPeriodic() 并改用 setOverrideDeadline(60000)。该作业将在 60 秒内运行,之后将不再安排任何其他作业。

      【讨论】:

      • setOverrideDeadline(3000) 但它在奥利奥一段时间后不断重复?可能是什么原因..我没有使用setPeriodic
      【解决方案3】:

      好吧,我想知道是否其他人有这个问题。

      jobFinished() 不会停止您设置的周期性时间继续。它只是告诉作业您已完成,释放唤醒锁,因此 Android 不必强行终止作业。

      我必须做的是在我的服务中重新创建 jobScheduler 并调用 cancelAll()。您显然也可以调用 cancel(job_id)。

      jobScheduler = (JobScheduler)this.getSystemService(Context.JOB_SCHEDULER_SERVICE );
      jobScheduler.cancelAll();
      

      【讨论】:

      • 以下汤姆的回答应该是被接受的。您正在创建一个周期性工作并将其用作一次性工作,这没有任何意义,因为有一些方法可以正确地完成它。此外,您正在取消您可能已安排的所有作业,而不是您想要的。
      • 肯定会调用cancel(int),因为cancelAll() 将按预期取消与您的应用关联的所有计划作业(可能不是您想要的)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-12
      • 2012-09-30
      • 2018-02-09
      • 2023-03-12
      相关资源
      最近更新 更多