Reputation: 745
This code sets an alarm to fire at a specified day & time and repeats every 20 minutes. Can I stop the repeat (when the user stops it or when it successfully performs a job) but keep the alarm set without having to reinitialize ?
Example, the following sets an alarm to fire at 8:30 am & repeats every 20 min after, if the user stops the alarm, I would like the alarm to fire the next day at 8:30 again
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
...
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmListener.class);
alarmIntent = PendingIntent.getBroadcast(context, AlarmListener.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Set the alarm to start at 8:30 am
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
// 20 minutes repeating.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
60 * 1000 * 20, alarmIntent);
A use case of this would be a monthly reminder where you set an Alarm for the 25th of every month. On the 25th, your Alarm would fire and repeat every 20 min but when you stop it, it should keep the schedule of firing an alarm on the 25th !
Also, any optimizations, notices or warnings regarding using AlarmManager would be highly appreciated.
Upvotes: 1
Views: 407
Reputation: 95636
Of course this is possible. When you want to reschedule the alarm to start at 8:30 am the next day just do this:
// Set the alarm to start at 8:30 am next day
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, 8);
calendar.set(Calendar.MINUTE, 30);
calendar.add(Calendar.DAY, 1);
// 20 minutes repeating.
alarmMgr.setInexactRepeating(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), 60 * 1000 * 20, alarmIntent);
This will replace your repeating alarm with an alarm that goes off tomorrow at 8:30am and then repeats every 20 mins after that.
Upvotes: 1
Reputation: 2387
Yes you can achieve that. My suggestion is your alarm manager, you set it to setExact
and you also need to check if the calendar is today or not like below:
//check whether the time is earlier than current time. If so, set it to tomorrow. Otherwise, all alarms for earlier time will fire
if (calendar.before(now)) {
calendar.add(Calendar.DATE, 1)
}
val timeTrigger = calendar.timeInMillis
if (Build.VERSION.SDK_INT >= 23) {
alarmManagerActivity.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
timeTrigger, //timeTrigger is Systemtimeinmillis
pendingIntentActivity
)
} else if (Build.VERSION.SDK_INT >= 19) {
alarmManagerActivity.setExact(
AlarmManager.RTC_WAKEUP,
timeTrigger,
pendingIntentActivity
)
} else {
alarmManagerActivity[AlarmManager.RTC_WAKEUP, timeTrigger] = pendingIntentActivity
}
Separate the method AlarmManager
for 8:30PM with the AlarmManager
repeat for 20minutes. Make sure you use the same BroadcastReceiver
so it will just trigger here for both of them. See example at below:
fun alarmManager20Minutes(context: Context) {
val calendar = Calendar.getInstance()
calendar[Calendar.HOUR_OF_DAY] = 0
calendar[Calendar.MINUTE] = 0
calendar[Calendar.SECOND] = 0
val intent = Intent(context, BroadcastReceiverHealthDeclaration::class.java)
val timeTrigger = System.currentTimeMillis() + 20 * 60 * 1000 //20 mins
val pendingIntentActivity = PendingIntent.getBroadcast(
context,
ALARM_MANAGER_ID_20_MINUTES,
intent,
PendingIntent.FLAG_UPDATE_CURRENT
)
val alarmManagerActivity = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
if (Build.VERSION.SDK_INT >= 23) {
alarmManagerActivity.setExactAndAllowWhileIdle(
AlarmManager.RTC_WAKEUP,
timeTrigger,
pendingIntentActivity
)
} else if (Build.VERSION.SDK_INT >= 19) {
alarmManagerActivity.setExact(
AlarmManager.RTC_WAKEUP,
timeTrigger,
pendingIntentActivity
)
} else {
alarmManagerActivity[AlarmManager.RTC_WAKEUP, timeTrigger] = pendingIntentActivity
}
}
Next, at your BroadcastReceiver
, onReceive
, once it trigger 8.30AM for today, you need to call the your Alarm Manager
method again and also don't forget to call alarmManager20Minutes()
.
override fun onReceive(context: Context?, intent: Intent?) {
//Check if user want to receive the daily or not
val receiveNotification = QuickSave.instance.getBoolean(
Constant.RECEIVE_NOTIFICATION,
true
)
if (receiveNotification) {
AlarmManagerUtil.alarmManager20Minutes(context)
//And then call method for 8:30AM
AlarmManagerUtil.alarmManager830AM(context)
}
}
So, when onReceive
triggered, so you call method alarmManager20minutes
. It will call again onReceive
for next 20minutes and also it will set the alarmManager830AM
for next day.
Upvotes: 1