简体   繁体   中英

date and time not working in Alarm Manager

I'm having trouble working with the AlarmManager . I want to run AlarmManager using Calendar at a specific time. But the calendar doesn't work and AlarmManager always runs regardless of the time taken from the calendar.

 AlarmManager mAlarmManger = (AlarmManager) Objects.requireNonNull(activity).getSystemService(view.getContext().ALARM_SERVICE);
 Intent intent = new Intent(activity, MyReceiver.class);
 PendingIntent pendingIntent = PendingIntent.getBroadcast(activity, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

 Calendar calendar = Calendar.getInstance();
 calendar.set(Calendar.WEEK_OF_YEAR, Calendar.MONTH , Calendar.DAY_OF_MONTH, 11, 55, 0);
 calendar.set(Calendar.AM_PM, Calendar.AM);

 if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){

        mAlarmManger.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
    }
    else{

        mAlarmManger.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
    }

AlarmManager should run at 11:55 AM everyDay, but will run as soon as the app opens.

  Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.HOUR_OF_DAY, 11);
        calendar.set(Calendar.MINUTE, 30);
        calendar.set(Calendar.SECOND, 0);     

if (calendar.getTimeInMillis() > System.currentTimeMillis()) {

            Intent intent = new Intent(MainActivity.this, AlarmReceiver.class);
            pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            AlarmManager am = (AlarmManager) MainActivity.this.getSystemService(MainActivity.this.ALARM_SERVICE);
            am.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), 24 * 60 * 60 * 1000, pendingIntent); //Repeat every 24 h
}

Try this..

java.time and ThreeTenABP

To obtain your time in millseconds since the epoch for the triggerAtMillis argument for your alarm manager:

    long triggerAtMillis = ZonedDateTime.now(ZoneId.systemDefault())
            .with(LocalTime.of(11, 55))
            .toInstant()
            .toEpochMilli();

To have this code work also on Android versions before Oreo (version code O, API level 26), add ThreeTenABP to your Android project, see the link at the bottom. And then make sure you import org.threeten.bp.ZonedDateTime , org.threeten.bp.ZoneId and org.threeten.bp.LocalTime .

What went wrong in your code?

The Calendar class was always poorly designed and has a confusing interface. No wonder that you made this error. You're far from the first and unfortunately not the last either. In the original question you tried:

    calendar.set(Calendar.WEEK_OF_YEAR, Calendar.MONTH , Calendar.DAY_OF_MONTH, 11, 55, 0);

In my time zone this sets the calendar date to Mon Mar 05 11:55:00 CET 3 . That's 2016 years and some months ago. So the alarm manager did the correct thing when running as soon as your app was opened. Could it be that you passed year 3, month 3 and day of month 5 to the method? Almost! The Calendar interface is working with fields that can be set independently: an era field, a year field, a month field, etc. Since this was designed before enums in Java, each field has a number, and of course a named constant for that number. The month field, for example, is field 2, so when you pass Calendar.MONTH for month, you are passing the value 2. So how come we get March? This is another confusing trait of Calendar , months are numbered from 0 for January through 11 for December, so 2 means March. The week of year field is field 3 and the day of month field is field 5. This explains the date you got.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM