Search code examples
javaandroiddatealarmmanagerrepeatingalarm

Why set DAY_OF_WEEK for repeating alarm don't change date if today's Sunday?


I'm using alarmmanager in android for set a repeating alarm for days selected by the user, that's works fine but if actual day is Sunday that's don't work correct. Let's see. If today's Sunday(7) and I set the alarm for Monday (8) and Tuesday(9) when I see the calendar toString() the date configured is 7, don't change, but if today is other day it's works fine only happens when today's Sunday.

calendar.set(Calendar.HOUR_OF_DAY,h)
calendar.set(Calendar.MINUTE,m)
calendar.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY)//repeating for Monday if today is Sunday 8, and I set MONDAY, the new date most be Monday 9
Log.d("test",calendar.toString())

What's happening?


Solution

  • java.time through desugaring

    Consider using java.time, the modern Java date and time API, for your date and time work.

        LocalTime alarmTime = LocalTime.of(23, 45);
        ZonedDateTime alarmDateTime = ZonedDateTime.now(ZoneId.of("Africa/Porto-Novo"))
                .with(TemporalAdjusters.next(DayOfWeek.MONDAY))
                .with(alarmTime);
        
        System.out.println("Alarm date and time: " + alarmDateTime);
    

    Output when running just now (Monday, February 8):

    Alarm date and time: 2021-02-15T23:45+01:00[Africa/Porto-Novo]

    If you wanted the alarm to happen already today, use nextOrSame() instead of next().

    What went wrong in your code?

    While it’s quite common for programmers to run into one of the many confusing points about the Calendar class, you have run into two of them:

    1. calendar.set(Calendar.DAY_OF_WEEK,Calendar.MONDAY) may set the date of the Calendar object either to the previous or to the next Monday. Which one it picks does not only depend of the day of week but also of the settings of the Calendar object, which will typically be different on different devices.
    2. When next you call calendar.toString(), the string you get will not reflect the necessary changes to the Calendar object after changing the day of week. I would immediately expect that the day of week has changed, but the old value of day of month will still be printed. I am not going to study the documentation well enough to give you a precise answer. The Calendar does not compute its fields until you call get() or some other designated method that causes the recomputation to take place.

    There are plenty of reasons for not using Calendar.

    Question: Doesn’t java.time require Android API level 26?

    java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

    • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
    • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
    • On older Android either use desugaring or the Android edition of ThreeTen Backport. It’s called ThreeTenABP. In the latter case make sure you import the date and time classes from org.threeten.bp with subpackages.

    Links