Apfelsaft23
Apfelsaft23

Reputation: 326

Android Work Manager: How to enqueue Jobs once a month

following this question, I looked into Android Job Scheduling and it seems like Work Manager is the latest tool if I want to do something once every month. I built a Worker class and activated it with this snippet in my activity:

PeriodicWorkRequest myWorkRequest =
                new PeriodicWorkRequest.Builder(MonthlyWorker.class, 20, TimeUnit.MINUTES)
                        .build();
WorkManager.getInstance().enqueueUniquePeriodicWork("my fancy test",ExistingPeriodicWorkPolicy.KEEP, myWorkRequest);

While i tested the 20 minutes period successfully, there is a problem: There are no TimeUnits for months available, only days. Doing the job every 30 days wont work for obvious reasons, since I need the task to be executed on the first day of each month. So what should i do? Do I have to use a different API? Thank you.

I could do something like if (dayOfMonth==1) do Function, but I think that undermines the purpose of a scheduler.

Upvotes: 5

Views: 2560

Answers (3)

mtotschnig
mtotschnig

Reputation: 1551

What I would do is to enqueue a unique, not periodic work for the beginning of the next month and when the job is triggered in the doWork method, at the end, you schedule the next run for the beginning of the next month, ...

Upvotes: 0

MengYuan Cheng
MengYuan Cheng

Reputation: 21

Maybe you can create a WorkManager and check today is or not the first day in a month like this:

Calendar c = Calendar.getInstance();
c.add(Calendar.MONTH, 0);
c.set(Calendar.DAY_OF_MONTH, 1);
String monthfirst = format.format(c.getTime());
System.out.println("===============nowfirst:" + monthfirst);

If is true, you can do you a real job.

Upvotes: 1

Pratik Butani
Pratik Butani

Reputation: 62419

You can do by minutes itself:

Just convert days to minutes:

Here : 30 days = 43200 minutes = 1 month

PeriodicWorkRequest myWorkRequest =
            new PeriodicWorkRequest.Builder(MonthlyWorker.class, 43200, TimeUnit.MINUTES)
                    .build();
WorkManager.getInstance().enqueueUniquePeriodicWork("my fancy test",ExistingPeriodicWorkPolicy.KEEP, myWorkRequest);

UPDATE:

As per my requirement, I wanted to perform task every 30 minutes in between 8 am to 6 pm

With help of that worker I made for you as you required 1st of every month in between 12 am to 2 am below:

public class TestWorker extends Worker {

    private static final String DEFAULT_START_TIME = "00:01"; //12:01 am
    private static final String DEFAULT_END_TIME = "03:00"; // 03:00 am

    private static final String TAG = "TestWorker";

    public TestWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
    }

    @NonNull
    @Override
    public Result doWork() {

        /**
         * Its for time
         */
        DateFormat dateFormat = new SimpleDateFormat("HH:mm", Locale.getDefault());

        /**
         * Get Current Calendar Instance
         */
        Calendar c = Calendar.getInstance();

        // Get current day of month
        int day = c.get(Calendar.DAY_OF_MONTH);

        /**
         * Get current time and compare with our start and end date.
         */
        Date date = c.getTime();
        String formattedDate = dateFormat.format(date);

        try {
            Date currentDate = dateFormat.parse(formattedDate);
            Date startDate = dateFormat.parse(DEFAULT_START_TIME);
            Date endDate = dateFormat.parse(DEFAULT_END_TIME);

            /**
             * This condition will check that day is 1, and time interval in between give time.
             */         
            if (day == 1 && currentDate.after(startDate) && currentDate.before(endDate)) {
                // Do your work here
            }
        } catch (ParseException ignored) {

        }

        return Result.success();
    }
}

You can start this test work for X hour interval so it will check every X hour (for example, In your case you can give 2 hours so it will check every two hours)

I do not know whether it will be affected to performance or not, but I think there is no other solution.

You can start worker as below:

PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(MyWorker.class, 2, TimeUnit.HOURS)
                .addTag("MYWORK")
                .build();

WorkManager.getInstance().enqueueUniquePeriodicWork("MYWORK", ExistingPeriodicWorkPolicy.REPLACE, periodicWork);

Hope it will help.

Upvotes: 5

Related Questions