お前たちのJobSchedulerの使い方は間違っている

More than 1 year has passed since last update.


何が間違っているのか

主要な日本語解説記事にてJobService.jobFinished(JobParameters, boolean)の呼び出し方がほぼ間違っている1

以下のように記述されていることがあるが、これは誤りである。

@override

public boolean onStopJob(JobParameters params) {
jobFinished(params, false);
return false;
}

同様に、jobFinishedを呼ぶとonStopJobが呼ばれるという記事もあるが、それも誤りである。


Javadocを読む

jobFinishedは、Javadocによると、


Call this to inform the JobScheduler that the job has finished its work. When the system receives this message, it releases the wakelock being held for the job.


と書いてある。

訳すと、「このメソッドを呼ぶことで、JobSchedulerにジョブが完了したことを通知する。システムがこの通知を受けると、このジョブのために取得していたwakelockを手放す。」となる。

つまり、jobFinished()が呼ばれたら登録されたジョブの実行は終わったとAndroidは解釈してロックを手放すよ、ということ。

onStopJobについては、Javadocにこのように書いてある。


This method is called if the system has determined that you must stop execution of your job even before you've had a chance to call jobFinished(JobParameters, boolean).

This will happen if the requirements specified at schedule time are no longer met. For example you may have requested WiFi with JobInfo.Builder.setRequiredNetworkType(int), yet while your job was executing the user toggled WiFi. Another example is if you had specified JobInfo.Builder.setRequiresDeviceIdle(boolean), and the phone left its idle maintenance window.


意訳すると、「このメソッドは、あなたがjobFinished()を呼ぶ機会を得る前(つまりジョブの実行が完了する前)に実行中のジョブを止める必要がある場合に呼ばれます。これは、ある特定の条件でのジョブの呼び出しをJobSchedulerに依頼していたため、その条件を満たした際にジョブが呼び出されたが、その実行途中で条件が破られた際に発生します。

たとえば、WiFi接続時のジョブの呼び出しをJobSchedulerに依頼していた場合に、WiFi接続になったためにジョブが呼び出されたが、ジョブの実行中にWiFi接続が切られた場合などです。」となる。

つまり、このメソッドが呼ばれた際の期待値は「実行中のジョブを止めること」であって、「ジョブが完了したことを通知すること(jobFinishedを呼ぶこと)」ではない。


正しい処理

onStopJob()が呼ばれた際にはジョブを止めましょう。

@override

public boolean onStopJob(JobParameters params) {
stopYourJobImmediately();
return false;
}

wakelockはonStopJobメソッドにてreturnした段階で手放してくれるので、気にしなくて良いです。


Once this method returns, the system releases the wakelock that it is holding on behalf of the job.



google様のサンプルコードは・・・?

googlesamplesを見ると、

    @Override

public boolean onStopJob(JobParameters params) {
// Stop tracking these job parameters, as we've 'finished' executing.
sendMessage(MSG_COLOR_STOP, params.getJobId());
Log.i(TAG, "on stop job: " + params.getJobId());

// Return false to drop the job.
return false;
}

MSG_COLOR_STOPというメッセージを送って処理を止めています。

当然、jobFinished()なんて呼んでないですね。





  1. "Android JobScheduler onStopJob"で検索して1ページ目に出てくる日本語記事4つのうち、3つが誤り。1つが実装不足。つまり全滅。