The problem is calendar.getTimeInMillis() in
mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pi);
The second argument to setInexactRepeating , citing the document
triggerAtMillis times in milliseconds so that the alarm is first turned off using the appropriate clock (depending on the type of alarm). This is inaccurate: the alarm does not work until this time, but it may delay almost the entire alarm interval before the first alarm call.
The value will be executed for the first time aproximally one minute after you set it due
calendar.setTimeInMillis(System.currentTimeMillis()); calendar.set(Calendar.HOUR_OF_DAY, 0 ); calendar.set(Calendar.MINUTE, 1);
If you are not the first to start an alarm the next day, do calendar.add (Calendar, DATE, 1); `
As for the shutdown, did the device reboot? AlarmCalendar alarms are not saved when the device is rebooted, can you register the BroadcastReceiver to receive the BOOT_COMPLETED event and register the alarm re-check ? BOOT_COMPLETED Alarm manager persist even after the reboot?
Update: as suggested here, it will help you after looking at the code
In class BOOT_COMPLETED Receiver :
public void onReceive(Context context, Intent i) { if (i.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) { ReminderAlarm.scheduleAlarms(this); } }
In class ReminderAlarm
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.recurring); if(!alarmInitialized(this) { scheduleAlarms(this); }
}
public static void scheduleAlarms(Context context) { Calendar calendar = Calendar.getInstance(); if(hasRunnedToday(context)) { //if the alarm has run this day calendar.add(Calendar.DATE, 1); //schedule it to run again starting tomorrow } long firstRunTime = calendar.getTimeInMillis(); AlarmManager mgr = (AlarmManager) context .getSystemService(Context.ALARM_SERVICE); Intent notificationIntent = new Intent(context, ReminderAlarm.class); PendingIntent pi = PendingIntent.getActivity(context, 0, notificationIntent, 0); mgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstRunTime, AlarmManager.INTERVAL_DAY, pi); } public static boolean alarmInitialized(Context context) { SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE); long alarmLastRun = preferences.getLong("AlarmLastRun", -1); return alarmLastRun != -1; } public static void updateAlarmLastRun(Context context) { SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE); preferences.edit() .putLong("AlarmLastRun", new Date().getTime()) .apply(); } public static boolean hasRunnedToday(Context context) { SharedPreferences preferences = context.getSharedPreferences("alarm_prefs", MODE_PRIVATE); long alarmLastRun = preferences.getLong("AlarmLastRun", -1); if(alarmLastRun == -1) { return false; } //check by comparing day, month and year Date now = new Date(); Date lastRun = new Date(alarmLastRun); return now.getTime() - lastRun.getTime() < TimeUnit.DAYS.toMillis(1); }
Each time a call to the Reminder class starts, you must call updateAlarmLastRun to update the last time the alarm was started, this is necessary because the alarm can be a schedule that must be executed during the day, and the user restarts the device before the alarm starts, in in this case we do not want to use calendar.add(Calendar.DATE, 1); since it will skip the day.
On your Manifest.xml
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="false" android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
Notes:
- You should not do
context = this if the context is a class field, since the object contains a link to the field of its context field and context contains a reference to the object that will flow - Your
Receiver 'onReceive` has no additional settings that you think you have as a “notificationCount” onReceive when your device finishes booting. - Once your alarm starts, call
updateAlarmLastRun
Hope this helps