Android jobScheduler не остановится на jobFinished (params, false)

Я пытаюсь создать 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(), и мой сервис уничтожается, но затем приходит другое задание с тем же идентификатором и запускает все обратно.

У меня есть BIND_JOB_SERVICE в манифесте, как показывает каждый пример.

Любые идеи о том, почему jobFinished(params, false) не убивает setPeriodic(60000)?


person Daniel Braun    schedule 27.05.2016    source источник


Ответы (3)


Вы указали, что задание запускается периодически (каждые 60 секунд), поэтому каждые 60~ секунд создается и выполняется новое задание. jobFinished() относится к заданию и просто указывает, что оно выполнено. Вы ничего не отменяли.

Ваш (в настоящее время) принятый ответ работает для отмены запланированного задания, но если все, что вам нужно, это задание, которое выполняется в течение 60 секунд, а затем останавливается, вам следует опустить setPeriodic() и вместо этого использовать setOverrideDeadline(60000). Задание будет запущено в течение 60 секунд, и после него больше не будет запланировано.

person Tom    schedule 29.06.2016
comment
setOverrideDeadline(3000) но это повторяется через определенное время на oreo? В чем может быть причина.. я не использовал setPeriodic ? - person Santanu Sur; 05.05.2018

Ну я разобрался, может у кого такая проблема.

jobFinished() не остановит установленное вами периодическое время. Он просто сообщает заданию, что вы закончили, чтобы снять блокировку пробуждения, поэтому Android не нужно принудительно завершать задание.

Что мне нужно было сделать, так это воссоздать jobScheduler в моей службе и вызвать команду cancelAll(). Вы также можете, по-видимому, вызвать отмену (job_id).

jobScheduler = (JobScheduler)this.getSystemService(Context.JOB_SCHEDULER_SERVICE );
jobScheduler.cancelAll();
person Daniel Braun    schedule 27.05.2016
comment
Ответ Тома ниже должен быть принятым. Вы создаете периодическое задание и используете его как одноразовое, что не имеет смысла, поскольку есть способы сделать это правильно. Кроме того, вы отменяете ВСЕ запланированные задания, а не то, которое хотели. - person Thomas H.; 17.10.2017
comment
определенно вызовите cancel(int), поскольку cancelAll(), как и ожидалось, отменит все запланированные задания, связанные с вашим приложением (вероятно, не то, что вы хотели бы) - person Alex.F; 23.04.2018

Я использовал несколько JobService, и чтобы остановить одно конкретное задание, я использовал идентификатор задания, чтобы отменить задание.

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

При запуске задания я передал идентификатор 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");
                }
}
person HAXM    schedule 03.04.2019