web-dev-qa-db-ja.com

Android Job Scheduler-ジョブをすぐに1回だけ実行するようにスケジュールします

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を呼び出していることを確認しました。

12
dumb_terminal

ジョブを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 /でのみ実行されるため、ジョブはほとんど遅延なくスケジュールする必要があります。

5
intrepidis