web-dev-qa-db-ja.com

Androidで定期作業マネージャーに初期遅延を設定します

24時間ごとに実行する必要があるWorkerインスタンスがありますが、これはPeriodicWorkRequest AP​​Iを考えると非常に簡単です。しかし、ここに問題があります。

ユーザーが午後8時に作業を開始した場合、翌朝の午前9時に作業マネージャーの最初のインスタンスを実行してから、24時間の定期的な制約に従う必要があります。

私は here を見て、OneTimeWorkRequest APIに使用可能なsetInitialDelay()関数があることを発見しましたが、PeriodicWork AP​​Iについて何も見つかりませんでした。

これらはいくつかのハックです。たとえば、最初の遅延でOneTimeWorkを使用し、そこからPeriodicWorkをスケジュールすることができますが、それはちょっと汚いハックです。

PeriodicWorkRequest AP​​Iだけでこれを行う方法はありますか?

12
Sriram R

WorkManagerv1.0.0-alpha07)、PeriodicWorkReqeustの初期遅延を設定することは不可能だと思います。次のリリースでいくつかのAPIを取得する可能性があります。

当面は、先ほどお話ししたように、OneTimeWorkリクエストセットアップを初期遅延付きで使用できます。これにより、PeriodicWorkリクエストがWorkManagerにエンキューされます。

私はそれをハックと言いますが、それほど汚いものではありません。

4
Qasim

PeriodicWorkRequestには、作業を実行できる間隔を渡すことができるNice Builderコンストラクタがあります。ビルダーと各パラメーターの詳細を確認できます ここ

したがって、定期的な作業に初期遅延を設定するには、次のようにします。

int hourOfTheDay = 10; // When to run the job
int repeatInterval = 1; // In days

long flexTime = calculateFlex(hourOfTheDay, repeatInterval);

Constraints myConstraints = new Constraints.Builder()
        .setRequiresBatteryNotLow(true)
        .build();

PeriodicWorkRequest workRequest =
        new PeriodicWorkRequest.Builder(MyNiceWorker.class,
                repeatInterval, TimeUnit.DAYS,
                flexTime, TimeUnit.MILLISECONDS)
                .setConstraints(myConstraints)
                .build();

WorkManager.getInstance().enqueueUniquePeriodicWork(YOUR_Nice_WORK_TAG,
        ExistingPeriodicWorkPolicy.REPLACE,
        workRequest);

ここで魔法が起こります:

private long calculateFlex(int hourOfTheDay, int periodInDays) {

    // Initialize the calendar with today and the preferred time to run the job.
    Calendar cal1 = Calendar.getInstance();
    cal1.set(Calendar.HOUR_OF_DAY, hourOfTheDay);
    cal1.set(Calendar.MINUTE, 0);
    cal1.set(Calendar.SECOND, 0);

    // Initialize a calendar with now.
    Calendar cal2 = Calendar.getInstance();

    if (cal2.getTimeInMillis() < cal1.getTimeInMillis()) {
        // Add the worker periodicity.
        cal2.setTimeInMillis(cal2.getTimeInMillis() + TimeUnit.DAYS.toMillis(periodInDays));
    }

    long delta = (cal2.getTimeInMillis() - cal1.getTimeInMillis());

    return ((delta > PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS) ? delta
            : PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS);
}

今回は正確ではありませんのでご了承ください。 WorkManagerは、制約、システム負荷、その他のスケジュールされたジョブなどに応じて、そのフレックスウィンドウでいつでもジョブをトリガーできます。

正確なタイミングが必要な場合は、AlarmManagerに切り替えます。

それが役に立てば幸い!

3
Rafael Chagas

新しいバージョンのワークマネージャ( バージョン2.1.0-alpha02 2019年5月16日にリリース)では、PeriodicWorkRequestsが初期遅延をサポートするようになりました。 PeriodicWorkRequest.BuilderでsetInitialDelayメソッドを使用して、初期遅延を設定できます。

例:

    PeriodicWorkRequest workRequest = new PeriodicWorkRequest.Builder(
        WorkerReminderPeriodic.class,
        24,
        TimeUnit.HOURS,
        PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
        TimeUnit.MILLISECONDS)
      .setInitialDelay(1, TimeUnit.HOURS)
      .addTag("send_reminder_periodic")
      .build();


    WorkManager.getInstance()
        .enqueueUniquePeriodicWork("send_reminder_periodic", ExistingPeriodicWorkPolicy.REPLACE, workRequest);
2
Anjal Saneen