Androidジョブスケジューラを使用して、ジョブをすぐに1回だけ実行するようにスケジュールしようとしています。
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
jobScheduler.cancel(1);
PersistableBundle bundle = new PersistableBundle();
bundle.putInt(JobFlags.KEY_PERIODIC_SYNC_JOB, JobFlags.JOB_TYPE_INITIAL_FETCH);
jobScheduler.schedule(new JobInfo.Builder(1,
new ComponentName(context, SyncJobLollipop.class))
.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
.setExtras(bundle)
.setMinimumLatency(10)
.setOverrideDeadline(24 * 3600 * 1000)
.build());
しかし、それは約3〜4回実行されます。ここで何が問題になっていますか?
ジョブクラス自体は次のとおりです。
@RequiresApi(api = Build.VERSION_CODES.Lollipop)
public class SyncJobLollipop extends JobService implements JobFinishedListener {
@Inject
SyncJobBackend jobBackend;
private JobParameters jobParameters;
@Override
public boolean onStartJob(JobParameters jobParameters) {
((MyApplication)getApplication()).getAppComponent().inject(this);
this.jobParameters = jobParameters;
PersistableBundle bundle = jobParameters.getExtras();
int type = bundle.getInt(JobFlags.KEY_PERIODIC_SYNC_JOB);
jobBackend.onStartJob(type, this);
return true;
}
@Override
public boolean onStopJob(JobParameters jobParameters) {
jobBackend.onStopJob();
return false;
}
@Override
public void onJobFinished(boolean success) {
jobFinished(jobParameters, !success);
}
}
PS:私は毎回false値でjobFinishedを呼び出していることを確認しました。
ジョブを1回だけ実行するには、バックグラウンドワーカーのonStartJob(...)
でコードを実行し、onStopJob(...)
が呼び出されたときにそのコールバックを削除する必要があります。
public class SyncJobLollipop extends JobService {
final Handler workHandler = new Handler();
Runnable workRunnable;
@Override
public boolean onStartJob(JobParameters params) {
workRunnable = new Runnable() {
@Override
public void run() {
// do your work here,
// such as jobBackend.onStartJob(type, this)
boolean reschedule = false;
jobFinished(params, reschedule);
}};
workHandler.post(workRunnable);
return true;
}
@Override
public boolean onStopJob(JobParameters params) {
workHandler.removeCallbacks(workRunnable);
return false;
}
}
すぐに実行するには、「最小レイテンシ」と「オーバーライド期限」の両方を1に設定する必要があります。
jobScheduler.schedule(new JobInfo.Builder(1,
new ComponentName(context, SyncJobLollipop.class))
.setExtras(bundle)
.setMinimumLatency(1)
.setOverrideDeadline(1)
.build());
オペレーティングシステムのDozeモードは、「メンテナンス期間」またはデバイスが他の方法で起動されるまでJobSchedulerタスクを延期する可能性があることに注意してください。ただし、上記のコードはDozeモードの/ outside /でのみ実行されるため、ジョブはほとんど遅延なくスケジュールする必要があります。