Reputation: 1340
I'm using the following code to cancel all my alarms and reset them:
for (int i = 0; i < mArrayList.size(); i++) {
Intent receiverIntent = new Intent(mContext, AlarmReceiver.class);
int _id = (int) mArrayList.get(i).getDateMillis(); //(int) System.currentTimeMillis();
PendingIntent sender = PendingIntent.getBroadcast(mContext, _id, receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
alarmManager.cancel(sender);
setAlarm(mContext, receiverIntent, mArrayList.get(i).getType(), _id, sender, alarmManager);
}
public static void setAlarm(Context context, Intent receiverIntent, String typ, long timeMillis, PendingIntent pendingIntent, AlarmManager
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timeMillis);
long sdl = calendar.getTimeInMillis();
String notificationTitle = "My Title";
String notificationText = "My Text";
receiverIntent.putExtra("notificationTitle", notificationTitle);
receiverIntent.putExtra("notificationText", notificationText);
receiverIntent.putExtra("notificationDateTime", sdl);
alarmManager.set(AlarmManager.RTC_WAKEUP, sdl, pendingIntent);
}
Problem is that when I first call CancelAllAlarms()
and then set my alarms the new alarms are created very good but the old ones are not deleted.
And so if I do a adb shell dumpsys alarm > D:\test.txt
the first time I have about 200 entries, the next the the app is run I have about 400, then 600 etc...
EDIT
I changed my code a lot because I'm now storing my generated ID's inside a DB which works fine. So my code has changed quiet significant:
Intent receiverIntent = new Intent(mContext, AlarmReceiver.class); AlarmManager alarmManager = (AlarmManager) mContext.getSystemService(mContext.ALARM_SERVICE);
String[] alarms = getAllAlarmsFromDB(databaseHAlarms, databaseHAlarms.tableName_alarms);
for (int i = 0; i < alarms.length; i++) {
//alarms[i] now holds the ID set before (see codee below)
PendingIntent sender = PendingIntent.getBroadcast(mContext, Integer.parseInt(alarms[i]), receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.cancel(sender);
}
for (int i = 0; i < mArrayList.size(); i++) {
long timeMillis = mArrayList.get(i).getDateMillis();
int _id = Integer.parseInt(String.valueOf(mArrayList.get(i).getDateMillis()).substring(0, 8));
PendingIntent sender = PendingIntent.getBroadcast(mContext, _id, receiverIntent, PendingIntent.FLAG_CANCEL_CURRENT);
insertAlarmIntoMySQL(databaseHAlarms, getMD5(timeMillis + ""), String.valueOf(mArrayList.get(i).getDateMillis()).substring(0, 8));
alarmManager.set(AlarmManager.RTC_WAKEUP, sdl, sender);
}
Upvotes: 1
Views: 708
Reputation: 19417
You need to pass exactly the same PendingIntent
to alarmManager.cancel()
that you passed to alarmManager.set()
.
In your code _id
will differ, thus the PendingIntent
s won't be equal, so cancel will not work.
The IDs should be unique (except if you always want to cancel all of them), but when you want to cancel a particular alarm, you need to know the ID you used for the PendingIntent
when created it, and use that exact same ID to cancel it.
I recommend storing the IDs in SQLite database.
Upvotes: 3
Reputation: 9870
In addition to user13s answer, you have to use FLAG_UPDATE_CURRENT
on the PendingIntent
.
So in summary, be sure to use same Context
and id
and use FLAG_UPDATE_CURRENT
:
start the alarm:
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, sender);
stop the alarm:
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_CUPDATE_CURRENT);
alarmManager.cancel(sender);
Well, it´s not exactly clear/documented why FLAG_CANCEL_CURRENT
is not working, but I have read this often here in SO. The docs tell us, that this cancels an existing PendingIntent
and creates a new one and you can use this if you want to change some extra data
inside the intent
.
FLAG_UPDATE_CURRENT
is described like:
This can be used if you are creating intents where only the extras change, and don't care that any entities that received your previous PendingIntent will be able to launch it with your new extras even if they are not explicitly given to it.
From these two description I can´t see a reason why it shouldn´t work with alarmManager.cancel()
if you use FLAG_CANCEL_CURRENT
. Maybe it´s because that the PendingIntent
is canceled and recreated through the FLAG
before alarmManager.cancel()
is able to.
For marshmallow there are some new circumstances. Cancel should work like before, there is no change. But setting an alarm with alarmManager.set()
will not work if device falls into doze mode. The docs describing that you have to use setAndAllowWhileIdle()
, setExactAndAllowWhileIdle()
or setAlarmClock()
.
BUT ONLY DO THIS IF YOUR APP NEEDS TO FIRE ALARMS ON DOZE! So to prepare your app for Marshmallow, you should check the API versions and set the method it depends on.
if (Build.VERSION.SDK_INT >= 23) {
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, sender);
} else {
PendingIntent sender = PendingIntent.getBroadcast(mContext, id, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, time, sender);
}
Upvotes: 3