web-dev-qa-db-ja.com

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()に入れて、タスクをコメントアウトして、開始直後にそれを強制終了しようと試みましたが、それだけで発火し続けます。 onDestroy()が呼び出されてサービスが破棄されたため、jobFinished()が何かを起動したようですが、別のジョブが同じIDで着信し、すべてのバックアップを開始します。

すべての例が示すように、マニフェストにBIND_JOB_SERVICEがあります。

JobFinished(params、false)がsetPeriodic(60000)を強制終了しないように見える理由に関するアイデアはありますか?

11
Daniel Braun

さて、誰か他の人がこの問題を抱えているなら、私はそれを理解しました。

jobFinished()は、設定した定期的な時間の継続を停止しません。ウェイクロックを解放するために終了したことをジョブに通知するだけなので、Androidはジョブを強制終了する必要はありません。

私がしなければならなかったのは、私のサービスでjobSchedulerを再作成し、cancelAll()を呼び出すことでした。どうやらcancel(job_id)を呼び出すこともできます。

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

ジョブを定期的に(60秒ごとに)実行するように指定したため、60秒ごとに新しいジョブが作成されて実行されます。 jobFinished()はジョブに固有であり、単に実行が完了したことを示します。何もキャンセルしていません。

(現在)受け入れられている回答は、スケジュールされたジョブをキャンセルするために機能しますが、60秒以内に実行されて停止するジョブだけが必要な場合は、setPeriodic()を省略し、代わりにsetOverrideDeadline(60000)を使用する必要があります。 。ジョブは60秒以内に実行され、それ以降はスケジュールされません。

17
Tom

複数のJobServiceを使用していて、1つの特定のジョブを停止するために、ジョブのIDを使用してジョブをキャンセルしました。

_@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にIDを渡します。

_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");
                }
}
_
1
HAXM