Reputation: 121
I've built one small reminder app demo, where user fill some details and get notified. When I set the notification time, after current time to 5 minutes later like if current time is 14:55, then I'm setting 15:00 with current date. Now, notification is coming perfectly on time, when I do nothing and simply wait for 5 minutes to over.
But, when I manually go to my Android phone, and set time to 4 minutes later (14:59) and after wait for 1 minutes, notification is not coming. Why?
Code: Manifest:
<application
...
<receiver android:name=".Receiver.AlarmReceiver">
<intent-filter>
<action android:name="android.intent.action.TIME_SET" />
</intent-filter>
</receiver>
<receiver android:name=".Receiver.BootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.TIME_SET" />
</intent-filter>
</receiver>
</application>
AlarmReceiver
public void setAlarm(Context context, Calendar calendar, int ID) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Put Reminder ID in Intent Extra
Intent intent = new Intent(context, AlarmReceiver.class);
intent.putExtra(REMINDER_ID, Integer.toString(ID));
mPendingIntent = PendingIntent.getBroadcast(context, ID, intent, PendingIntent.FLAG_CANCEL_CURRENT);
/*mPendingIntent = PendingIntent.getBroadcast(context, requestCode, new Intent(context, AlarmReceiver.class),
PendingIntent.FLAG_NO_CREATE);
isAlarmSet = (mPendingIntent != null);
if (isAlarmSet) {
showLog("isAlarmSet: " + isAlarmSet);
} else {
showLog("isAlarmSet: " + isAlarmSet);
}*/
// Calculate notification time
Calendar c = Calendar.getInstance();
long currentTime = c.getTimeInMillis();
long diffTime = calendar.getTimeInMillis() - currentTime;
// Start alarm using notification time
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + diffTime,
mPendingIntent);
// Restart alarm if device is rebooted
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_ENABLED,
PackageManager.DONT_KILL_APP);
}
public void cancelAlarm(Context context, int ID) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
// Cancel Alarm using Reminder ID
mPendingIntent = PendingIntent.getBroadcast(context, ID, new Intent(context, AlarmReceiver.class), 0);
mAlarmManager.cancel(mPendingIntent);
// Disable alarm
ComponentName receiver = new ComponentName(context, BootReceiver.class);
PackageManager pm = context.getPackageManager();
pm.setComponentEnabledSetting(receiver,
PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
PackageManager.DONT_KILL_APP);
}
private void showLog(String msg) {
Log.d(TAG, msg);
}
}
AddReminderActivity:
private void setReminderAlarm(int id) {
String mDate = tvDueDate.getText().toString();
if (mDate.equals("")) {
mDate = CommonUtils.getDate();
}
String mTime = tvAlarmTime.getText().toString();
String[] mDateSplit = mDate.split("-");
String[] mTimeSplit = mTime.split(":");
mDay = Integer.parseInt(mDateSplit[2]);
mMonth = Integer.parseInt(mDateSplit[1]) - 1;
mYear = Integer.parseInt(mDateSplit[0]);
mHour = Integer.parseInt(mTimeSplit[0]);
mMinute = Integer.parseInt(mTimeSplit[1]);
// Check repeat type
long mRepeatTime = 0;
// Create a new notification
int day = mDay - notificationDay;
mCalendar.set(Calendar.DAY_OF_MONTH, mDay - notificationDay);
mCalendar.set(Calendar.MONTH, mMonth);
mCalendar.set(Calendar.YEAR, mYear);
mCalendar.set(Calendar.HOUR_OF_DAY, mHour);
mCalendar.set(Calendar.MINUTE, mMinute);
mCalendar.set(Calendar.SECOND, 0);
new AlarmReceiver().setAlarm(getApplicationContext(), mCalendar, id);
}
Upvotes: 0
Views: 224
Reputation: 143
You should use AlarmManager.RTC_WAKEUP while setting your alarm. AlarmManager.RTC_WAKEUP will trigger the alarm according to the time of the clock.
Example code:
mAlarmManager.set(AlarmManager.RTC_WAKEUP,
currentTime + diffTime,
mPendingIntent);
Upvotes: 1
Reputation: 733
mAlarmManager.set()
does not force to deliver the pending intent at the exact given time
Note: Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to "batch" alarms together across the entire system, minimizing the number of times the device needs to "wake up" and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.
mAlarmManager.setExact()
may fit what you are trying to do
if you have the exact time and date, (year, month, day, hour and minute) (you can check that with android studio debugger or with logcat to print the values) you can set the alarm with
mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, /*your exact time in millis*/, mPendingIntent
);
Upvotes: 0
Reputation: 10214
By using TIME_SET
receiver you can get to notify about the system time has been changed.
Whenever you're creating an Alarm just save the time in a local db also. When the broadcast receiver is triggered invoke a service, inside that fetch all existing alarm time with the new system time. You should be aware that all the alarms will get cancelled once you change the system time. So you should recreate all your alarms.
Upvotes: 0