Android Проблема выполнения WorkManager PeriodicWorkRequest - PullRequest
1 голос
/ 02 февраля 2020

У меня есть приложение, которое загружает данные из онлайн-базы данных. Он использует 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();
    }
}

1 Ответ

0 голосов
/ 02 февраля 2020

Прежде всего убедитесь, что ваш PeriodicWorkRequest не создается несколько раз, и вы можете проверить с помощью метода WorkManager.enqueueUniquePeriodicWork.

 PeriodicWorkRequest.Builder myWorkBuilder =
        new PeriodicWorkRequest.Builder(ArticleWorker.class, 120, MINUTES, 10, 
    MINUTES);

 PeriodicWorkRequest myWork = myWorkBuilder.build();
 WorkManager.getInstance()
.enqueueUniquePeriodicWork("jobTag", ExistingPeriodicWorkPolicy.KEEP, myWork);

Этот метод позволяет ставить в очередь уникальное имя PeriodicWorkRequest, где только один PeriodicWorkRequest из конкретное имя может быть активным одновременно. Например, вы можете захотеть, чтобы была активна только одна операция syn c. Если имеется одно ожидание, вы можете разрешить его запуск или заменить его новой работой.

...