У меня есть приложение, которое загружает данные из онлайн-базы данных. Он использует PeriodicWorkRequest и работает не так, как ожидалось. Я использую WorkManager 2.3.0.
Есть мои настройки WorkManager
public class ReminderUtil {
public static final String ARTICLE_WORK_TAG = "article_work";
public static void scheduleReminder(Context context) {
PeriodicWorkRequest request = new PeriodicWorkRequest
.Builder(ArticleWorker.class, 120, MINUTES, 10, MINUTES)
.setInitialDelay(1, MINUTES)
.build();
WorkManager.getInstance(context).enqueueUniquePeriodicWork(ARTICLE_WORK_TAG,
ExistingPeriodicWorkPolicy.KEEP, request);
}
Рабочий класс
public class ArticleWorker extends Worker {
private Context mContext;
public ArticleWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
mContext = context;
}
@NonNull
@Override
public Result doWork() {
//downloading new article date list
List<ArticleLight> recentArticleLightList = QueryUtils.getArticlesLight(ArticleUtils.articleUrl);
//sorting by Date
Collections.sort(recentArticleLightList, (o1, o2) -> o2.getDate().compareTo(o1.getDate()));
Date newestDate = recentArticleLightList.get(0).getDate();
String articleText = recentArticleLightList.get(0).getTitle();
//compare newestDate with last saved sate
SharedPreferences prefs = mContext.getSharedPreferences("MyPref", Context.MODE_PRIVATE);
long savedDateLong = prefs.getLong("date", 0);
savedDateLong = savedDateLong - 604800000;//todo this is a notification test
Date savedDate = new Date(savedDateLong);
Log.i("myTAG", "WORKER");
if (newestDate.compareTo(savedDate) > 0) {
//we have new article!
NotificationUtil.createNotification(mContext, articleText);
Log.i("myTAG", "NOTIFICATION");
}
return Result.success();
}
}
И есть мой журнал
2020-02-02 15:34:39.506 29571-7035/com.g84.spacenewstheguardian I/myTAG: WORKER
2020-02-02 15:34:39.521 29571-7035/com.g84.spacenewstheguardian I/myTAG: NOTIFICATION
2020-02-02 15:50:00.983 29571-31372/com.g84.spacenewstheguardian I/myTAG: WORKER
2020-02-02 15:50:00.998 29571-31372/com.g84.spacenewstheguardian I/myTAG: NOTIFICATION
2020-02-02 16:05:01.981 29571-337/com.g84.spacenewstheguardian I/myTAG: WORKER
2020-02-02 16:05:01.995 29571-337/com.g84.spacenewstheguardian I/myTAG: NOTIFICATION
2020-02-02 16:20:32.641 29571-3899/com.g84.spacenewstheguardian I/myTAG: WORKER
2020-02-02 16:20:32.710 29571-3899/com.g84.spacenewstheguardian I/myTAG: NOTIFICATION
Как видите, рабочий должен бегать каждые 120 минут с 10-минутным гибким временем, но он работает примерно каждые 16 минут.
РЕДАКТИРОВАТЬ:
Моя цель - создать ежедневный запрос в указанное время c. Поэтому я попытался изменить PeriodicWorkRequest на OneTimeWorkRequest. Когда приложение установлено, оно запускает запрос OneTimeWorkRequest с рассчитанным initialDelay до необходимого часа. Когда Worker запускается, он устанавливает новый OneTimeWorkRequest (снова с вычисленным initialDelay). Пока он работает так, как мне нужно, но все еще тестирует.
public class ReminderUtil {
public static final String ARTICLE_WORK_TAG = "article_work";
private static final int dayInMill = 86400000;
private static final int minDelay = 960000;//16 min - Min interval for WorkManager
public static void scheduleReminder2(Context context) {
if(!isWorkScheduled2(context)) { // check if my work is not already scheduled
scheduleWork2(context); // schedule my work
}
}
public static void scheduleWork2(Context context) {
OneTimeWorkRequest.Builder myBuilder =
new OneTimeWorkRequest.Builder(ArticleWorker.class)
.setInitialDelay(calculateDelay(), TimeUnit.MILLISECONDS)
.addTag(ARTICLE_WORK_TAG)
.setConstraints(new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build());
OneTimeWorkRequest myRequest = myBuilder.build();
WorkManager.getInstance(context)
.enqueue(myRequest);
}
private static boolean isWorkScheduled2(Context context) {
WorkManager instance = WorkManager.getInstance(context);
ListenableFuture<List<WorkInfo>> statuses = instance.getWorkInfosByTag(ReminderUtil.ARTICLE_WORK_TAG);
try {
boolean running = false;
List<WorkInfo> workInfoList = statuses.get();
for (WorkInfo workInfo : workInfoList) {
WorkInfo.State state = workInfo.getState();
running = state == WorkInfo.State.RUNNING | state == WorkInfo.State.ENQUEUED;
}
return running;
} catch (ExecutionException | InterruptedException e) {
e.printStackTrace();
return false;
}
}
private static long calculateDelay() {
Calendar now = Calendar.getInstance();
Calendar future = Calendar.getInstance();
// When to run the job
int hourOfTheDay = 8;
future.set(Calendar.HOUR_OF_DAY, hourOfTheDay);
future.set(Calendar.MINUTE, 0);
future.set(Calendar.SECOND, 0);
long diff = future.getTimeInMillis() - now.getTimeInMillis();
if (diff > minDelay) {
return diff;
}
else
return diff + dayInMill;
}
}
И рабочий класс
public class ArticleWorker extends Worker {
private Context mContext;
public ArticleWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
super(context, workerParams);
mContext = context;
}
@NonNull
@Override
public Result doWork() {
//downloading new article date list
List<ArticleLight> recentArticleLightList = QueryUtils.getArticlesLight(ArticleUtils.articleUrl);
//sorting by Date
Collections.sort(recentArticleLightList, (o1, o2) -> o2.getDate().compareTo(o1.getDate()));
Date newestDate = recentArticleLightList.get(0).getDate();
String articleText = recentArticleLightList.get(0).getTitle();
//compare newestDate with last saved sate
SharedPreferences prefs = mContext.getSharedPreferences("MyPref", Context.MODE_PRIVATE);
long savedDateLong = prefs.getLong("date", 0);
savedDateLong = savedDateLong - 604800000;//todo this is a notification test
Date savedDate = new Date(savedDateLong);
Log.i("myTAG", "WORKER");
if (newestDate.compareTo(savedDate) > 0) {
//we have new article!
NotificationUtil.createNotification(mContext, articleText);
Log.i("myTAG", "NOTIFICATION");
}
ReminderUtil.scheduleWork2(mContext);//todo test of oneTime Work
return Result.success();
}
}