アプリが閉じている場合でも、バックグラウンドで毎日1つのAPIを呼び出す必要があります。 WorkManager APIについて見てきました。私のシナリオでは、PeriodicWorkRequestを試しましたが、残念ながら、期待どおりの結果が得られません。私がしたことは、このコードをApplicationクラスで使用したことです
PeriodicWorkRequest.Builder myWorkBuilder =
new PeriodicWorkRequest.Builder(MyWorker.class, 24,
TimeUnit.HOURS);
PeriodicWorkRequest myWork = myWorkBuilder.build();
WorkManager.getInstance().enqueue(myWork);
ただし、その後アプリを初めて開いたときに11回繰り返し実行され、24時間後には実行されません。誰か、解決してください。
PeriodicWorkRequest
が複数回作成されないようにする場合は、 WorkManager.enqueueUniquePeriodicWork
ワーカーをスケジュールする方法:
このメソッドを使用すると、一意の名前のPeriodicWorkRequestをキューに登録できます。特定の名前のPeriodicWorkRequestを一度に1つだけアクティブにできます。たとえば、1つの同期操作のみをアクティブにしたい場合があります。保留中のものがあれば、それを実行させるか、新しい作業に置き換えるかを選択できます。
例えば:
PeriodicWorkRequest.Builder myWorkBuilder =
new PeriodicWorkRequest.Builder(MyWorker.class, 24, TimeUnit.HOURS);
PeriodicWorkRequest myWork = myWorkBuilder.build();
WorkManager.getInstance()
.enqueueUniquePeriodicWork("jobTag", ExistingPeriodicWorkPolicy.KEEP, myWork);
3つの問題があると思います。
1)enqueue
myWork
にWorkManager
インスタンスを作成するたびに、新しい定期作業を作成しています。
試してみてください、MyWorker.class
_のdoWork()
メソッドのロジックは、最初に1回実行され、2回目に実行されます。ワークマネージャーに11個の作品を追加した可能性が高く、最後にチェックしたときに11回実行したのはこのためです。新しい作品を作成して作品マネージャーに追加すると、myWork
の実行回数が増えます。
ジョブスケジューラと同様に、ワークマネージャに追加する前に、ワークが存在するかどうかを確認する必要があります。
サンプルコード:
_final WorkManager workManager = WorkManager.getInstance();
final LiveData<List<WorkStatus>> statusesByTag = workManager
.getStatusesByTag(TAG_PERIODIC_WORK_REQUEST);
statusesByTag.observe(this, workStatuses -> {
if (workStatuses == null || workStatuses.size() == 0) {
Log.d(TAG, "Queuing the Periodic Work");
// Create a periodic request
final PeriodicWorkRequest periodicWorkRequest =
new PeriodicWorkRequest.Builder(SyncWorker.class, 30, TimeUnit.MINUTES)
.addTag(TAG_PERIODIC_WORK_REQUEST)
.build();
// Queue the work
workManager.enqueue(periodicWorkRequest);
} else {
Log.d(TAG, "Work Status Size: " + workStatuses.size());
for (int i = 0; i < workStatuses.size(); i++) {
Log.d(TAG, "Work Status Id: " + workStatuses.get(i).getId());
Log.d(TAG, "Work Status State: " + workStatuses.get(i).getState());
}
Log.d(TAG, "Periodic Work already exists");
}
});
_
上記のサンプルでは、一意のタグ_TAG_PERIODIC_WORK_REQUEST
_を使用して定期的な作業を識別し、作成前に存在するかどうかを確認しています。
2)アプリが強制終了されたときに作業が実行されていない可能性があります。
テストしているブランドは何ですか? Xiaomiですか?他の複数のブランドでテストした結果、同じ結果になりましたか?
Dozeモードでしたか?また、24時間の時間を設定したときに作業が実行されていないことをどのように検証しますか?
Work Managerは下位互換性を提供しますが、それでもデバイス固有のロジックを処理する必要があります。ジョブスケジューラ(またはFirebase Job DispatcherまたはAlarm)と同様のXiaomiデバイスでは、アプリが強制終了されると定期的な作業が停止します。
3)PeriodicWorkRequest
が提供するWorkManager
はバグだと思います。
前週の初めから複数のデバイスでテストしてきました。アプリを最初に起動したときに作品を作成し、3日間開いていませんでした。最初に1回実行され、2回目の同期がトリガーされたときに2回実行され、その間に13回に増加し、1回、4回に減少しました。
別のテストでは、最初のインストール時に以下のコードを使用して作品を作成し、2回目のインストールからコードを削除しました。このテスト中、作業が正常に完了した場合でも、作業は毎回実行され、アプリは強制終了後に開かれます。
_final PeriodicWorkRequest periodicWorkRequest =
new PeriodicWorkRequest.Builder(SyncWorker.class, 30, TimeUnit.MINUTES)
.addTag("periodic-work-request")
.build();
// Queue the work
WorkManager.getInstance().enqueue(periodicWorkRequest);
_
それはまだアルファ版なので、私は理解しています。実稼働環境で使用すべきではないと思います。
PeriodicWorkRequestBuilder
にタグを追加し、定期的な要求をキューに入れる前にWorkManager.getInstance().cancelAllWorkByTag(REQUEST_TAG)
を呼び出すと、重複が発生しなくなります。
から始まる alpha03
独自の定期的な作業をスケジュールできます。 https://developer.Android.com/jetpack/docs/release-notes
WorkManager.enqueueUniquePeriodicWork(String uniqueWorkName、ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy、PeriodicWorkRequest periodicWork)を使用すると、一意のPeriodicWorkRequestをキューに登録できます。
だから、今あなたが望むものを達成することは非常に簡単です。
Alpha 01には次の問題がありました。
Application.onCreate()でワーカーが再スケジュールされる問題を修正しました。
WorkManagerの最新バージョン、つまり1.0.0-alpha02を使用します。 リリースノート で詳細を確認してください。
WorkManagerバージョン1.0.0-alpha04を使用します。リリースノートを確認できます here
また、これを参照してください PeriodicWorkRequest GitHub demo は、メンテナンスウィンドウ中に1日1回(24時間ごと)に1日カウンターを更新します。アプリケーションが開いているか閉じているかに関係なく、doWork()メソッドを実行します。
WorkManagerはまだアルファモードであるため、最終バージョンをリリースすると、すべてのデバイスで完全に機能します。