0

the purpose I'm writing this code is to make sure that my apps will notify the user on a certain time and the apps will be repeating the same notify every day starting at 7 AM.

However, I tried to use this function (as shown below). But it seems like it won't work.

calender.add(DATE, 1)

Actually, I want to generate an automatic notification. The medication information and the number of daily repeated is user input.

So the things that I want to do is for the if statement, it would compare whether the current hour is between 7 AM - 8 PM.

For the else if, the statement is to compare either the current hour is after 8 PM or not, if yes then the calendar will add another 1 day. So that the apps will pop up the same notification the next day at 7 AM.

And for else statement is to check if the current hour is before 7 AM or not. If yes, apps will pop up the notification right after the current hour equals to 7 AM

But the else if statement didn't work as I expected. I mean if I set the notification right now, at 10 PM, the apps won't notify me on the next day (at 7 AM).

So, I would like to ask if any of you could help me to fix my code as shown below. The if and else segment just works fine. But the else if statement seems like won't work.

 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

Calendar calendar = Calendar.getInstance();
Calendar now = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());

//repeat on 7am
calendar.set(Calendar.HOUR_OF_DAY, 7);
calendar.set(Calendar.MINUTE, 00);
calendar.set(Calendar.SECOND, 0);

//check current hour
int timeOfDay = now.get(Calendar.HOUR_OF_DAY);

//to check if current hour is after 7pm
Calendar later = Calendar.getInstance();
later.set(Calendar.HOUR_OF_DAY, 20);
later.set(Calendar.MINUTE, 00);
later.set(Calendar.SECOND, 0);

if (timeOfDay >= 7 && timeOfDay <= 20) {
    //notification's process
}

else if (now.after(later)) {
        Log.d("Hey", "Added a day");
        calendar.add(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 7);
        calendar.set(Calendar.MINUTE, 00);
        calendar.set(Calendar.SECOND, 0);

        this.context = context;
        prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
        nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        notification = new NotificationCompat.Builder(context);
        name = prefs.getString("name" + count, "");
        hours = prefs.getInt("hora" + count, 8);
        minutes = prefs.getInt("minuto" + count, 0);


        Intent newIntentKill = new Intent(context, Broadcast.class);
        Bundle saco = new Bundle();
        saco.putInt("count", count);
        saco.putBoolean("shownBefore", true);
        newIntentKill.putExtras(saco);

        PendingIntent pendingIntentKill = PendingIntent.getBroadcast(context, count, newIntentKill, PendingIntent.FLAG_UPDATE_CURRENT);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
               alarmManager.setExact(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);

         } else {
               alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);
         }

            Log.d("Alarm", "Alarms set for everyday 7 am.");
    }

else {

    this.context = context;
    prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
    nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    notification = new NotificationCompat.Builder(context);
    name = prefs.getString("name" + count, "");
    hours = prefs.getInt("hora" + count, 8);
    minutes = prefs.getInt("minuto" + count, 0);


    Intent newIntentKill = new Intent(context, Broadcast.class);
    Bundle saco = new Bundle();
    saco.putInt("count", count);
    saco.putBoolean("shownBefore", true);
    newIntentKill.putExtras(saco);

    PendingIntent pendingIntentKill = PendingIntent.getBroadcast(context, count, newIntentKill, PendingIntent.FLAG_UPDATE_CURRENT);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
           alarmManager.setExact(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);

     } 
     else {
           alarmManager.set(AlarmManager.RTC, calendar.getTimeInMillis(), pendingIntentKill);
         }

     Log.d("Alarm", "Alarms set for everyday 7 am.");
}

So, thank you in advance for your help. I would really appreciate it.

Izzati
  • 35
  • 7
  • Since the poorly designed `Calendar` class seems to be teasing, you may want to look into a better alternative: [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). If for minSDK under 26, then through the backport, ThreeTenABP, see [How to use ThreeTenABP in Android Project](https://stackoverflow.com/questions/38922754/how-to-use-threetenabp-in-android-project). – Ole V.V. Apr 05 '20 at 15:52

1 Answers1

0

java.time and ThreeTenABP

I suggest using java.time, the modern Java date and time API, for your date and time work. It is so much nicer to work with than the old and poorly designed Calendar class and generally doesn’t give as many unpleasant surprises. Your if/else scheme could for instance go like this:

    ZoneId zone = ZoneId.systemDefault();
    ZonedDateTime nowZdt = ZonedDateTime.now(zone);
    LocalTime now = nowZdt.toLocalTime();
    if (now.isBefore(LocalTime.of(20, 0))) {
        if (now.isBefore(LocalTime.of(7, 0))) {
            // Set alarm for 7 today
            long alarmTimeMillis = nowZdt.with(LocalTime.of(7, 0))
                    .toInstant()
                    .toEpochMilli();
            // Set alarm
        } else { // between 7 AM and 8 PM
            // notification's process
        }
    } else { // after 8 PM
        // Set alarm for 7 AM tomorrow
        long alarmTimeMillis = nowZdt.plusDays(1)
                .with(LocalTime.of(7, 0))
                .toInstant()
                .toEpochMilli();
        // Set alarm
    }           

Edit: In the two places in the code alarmTimeMillis is the count of milliseconds since the epoch for your alarm. You can use it in place of calendar.getTimeInMillis() in the calls to alarmManager.set() and alarmManager.setExact().

What went wrong in your code?

I’m not sure what happened. The possible problem that I have been able to spot is in this line:

if (timeOfDay >= 7 && timeOfDay <= 20) {

You are only comparing the hour of day, and you are using <=. This means that when the time is 20:something, up to and including 20:59, the condition is true. So in this case you are not getting into the branch where you are adding 1 day. I don’t think this is what you had intended.

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 use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161