web-dev-qa-db-fra.com

Définissez le délai initial sur un gestionnaire de travaux périodiques dans Android

J'ai une instance Worker qui doit s'exécuter toutes les 24 heures, ce qui est assez simple compte tenu de l'API PeriodicWorkRequest. Mais voici le hic.

Si l'utilisateur lance le travail à 20 heures, par exemple, j'ai besoin que la première instance du gestionnaire de travaux s'exécute à 9 heures le lendemain matin et que je suive la contrainte périodique de 24 heures.

J'ai regardé ici et j'ai trouvé que l'API OneTimeWorkRequest a une fonction setInitialDelay() qui peut être utilisée mais je n'ai rien trouvé pour l'API PeriodicWork.

Il y a des hacks pour cela, comme je peux utiliser le OneTimeWork avec le retard initial et ensuite planifier un PeriodicWork à partir de là mais c'est un peu un hack sale.

Existe-t-il un moyen de le faire uniquement avec l'API PeriodicWorkRequest?

12
Sriram R

Avec la version alpha actuelle de WorkManager (v1.0.0-alpha07), je pense qu'il n'est pas possible de définir le délai initial pour le PeriodicWorkReqeust. Peut-être que nous aurons de l'API dans les prochaines versions.

Pour le moment, comme vous l'avez dit, vous pouvez utiliser une configuration de demande OneTimeWork avec un délai initial, qui mettra ensuite en file d'attente une demande PeriodicWork vers WorkManager.

Je dirais que c'est un hack mais pas trop sale.

4
Qasim

PeriodicWorkRequest a un constructeur Nice Builder où vous pouvez passer un intervalle pendant lequel le travail peut s'exécuter. Vous pouvez vérifier les détails du Builder et chaque paramètre ici

Donc, pour définir un délai initial pour votre travail périodique, vous pouvez faire comme ceci:

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);

Voici où la magie opère:

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);
}

Veuillez noter que cette heure n'est pas exacte. WorkManager peut déclencher votre travail à tout moment dans cette fenêtre flexible en fonction de vos contraintes, de la charge système, d'autres travaux planifiés, etc.

Si vous voulez un timing précis, passez à AlarmManager .

J'espère que ça aide!

3
Rafael Chagas

Sur la nouvelle version de Work Manager ( Version 2.1.0-alpha02 publiée le 16 mai 2019) PeriodicWorkRequests prend désormais en charge les délais initiaux. Vous pouvez utiliser la méthode setInitialDelay sur PeriodicWorkRequest.Builder pour définir un délai initial.

Exemple:

    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