Skip to content

How to schedule a periodic background work to activate at fixed times?

I want to push a notification every 12 hours at fixed times (lets say for an example, 9am and 9pm, every day). This is my current doWork() code:

  @NonNull
    @Override
    public Result doWork() {

        database.child("business_users").child(currentUserID).addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                user = snapshot.getValue(BusinessUser.class);
                if(user.isNotifications()==true)
                {
                    if(user.getRatingsCount() > user.getLastKnownRC())
                    {
                        theDifference = user.getRatingsCount() - user.getLastKnownRC();
                        notification();
                    }
                }

            }

            @Override
            public void onCancelled(@NonNull DatabaseError error) {

            }
        });

        Log.i("BackgroundWork" , "notif sent");
        return Result.success();
    }

`

and this is the work creation code:

public void FirstTimeWork ()
     {
         PeriodicWorkRequest myWorkRequest =
                 new PeriodicWorkRequest.Builder(BackgroundWork.class, 12, TimeUnit.HOURS)
                         .setInitialDelay(1, TimeUnit.DAYS)
                         .addTag("notif")
                         .build();
     }

I saw some people doing it with calendar but I don’t understand how it works.

Answer

I have found a simple solution, using calendar:

calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 22);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
    calendar.set(Calendar.DAY_OF_MONTH, Calendar.DAY_OF_MONTH + 1);
}

and the initial delay is set like so:

.setInitialDelay(calendar.getTimeInMillis() - System.currentTimeMillis(), TimeUnit.MILLISECONDS)

and this seems to work well.