I am creating a repeating alarm. This works fine using the following code:
Intent intent = new Intent(this.ctx, AlarmReceiver.class);
intent.setAction("" + notificationId);
intent.putExtra(AlarmReceiver.TITLE, alarmTitle);
intent.putExtra(AlarmReceiver.SUBTITLE, alarmSubTitle);
intent.putExtra(AlarmReceiver.TICKER_TEXT, alarmTicker);
intent.putExtra(AlarmReceiver.NOTIFICATION_ID, notificationId);
PendingIntent sender = PendingIntent.getBroadcast(this.ctx, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = getAlarmManager();
am.setRepeating(AlarmManager.RTC_WAKEUP, triggerTime, 60000, sender);
Now I want to cancel an existing notification message (which pops up every minute for testing purposes), I invoke the following code, passing it an identical notificationId:
Intent intent = new Intent(this.ctx, AlarmReceiver.class);
intent.setAction("" + notificationId);
PendingIntent pi = PendingIntent.getService(this.ctx, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = getAlarmManager();
try {
am.cancel(pi);
} catch (Exception e) {
Log.e(PLUGIN_NAME, "AlarmManager update was not canceled. " + e.toString());
}
I see that pi != null, however the notification keeps coming and is not being cancelled. Both code snippets reside in the same class.
Basically I have two questions:
- How can I cancel a single alarm using its unique ID?
- How can I cancel all alarms, regardless of the ID?
UPDATE: I found that posting my issue here helps to get my mind straight. Changing the cancel code from:
PendingIntent sender = PendingIntent.getService( ... )
To:
PendingIntent sender = PendingIntent.getBroadcast( ... )
Helps to solve question 1. However the code to cancel all events, still does not work:
Intent intent = new Intent(this.ctx, AlarmReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this.ctx, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = getAlarmManager();
am.cancel(pi);
I'm a noob here. But I think if you want to cancel the alarm, you have to use the exact same instance of PendingIntent. That means "their action, data, type, class, and categories are the same" as defined by filterEquals(Intent) . Therefore, you need to use the same requestCode here, not 0. Maybe you could use a list to store the Notification Ids, and iterate them to cancel all alarms.
I think , you should use same AlarmManager object to cancel the alram and also try to use same PendingIntent.
Related
I have set multiple repeating alarms each with different PendingIntent.
Is there a way to cancel all these alarms at once?
The only way i find to cancel alarms is to create individual PendingIntent and then call AlarmManager.cancel(pendingIntent) method.
As I have many different alarms with different PendingIntent i will have to recreate all those, is there a better way?
As far as I know there is no other way to cancel the alarms
The only way you can do is recreate your pending intent and cancel it.
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent updateServiceIntent = new Intent(context, MyPendingIntentService.class);
PendingIntent pendingUpdateIntent = PendingIntent.getService(context, 0, updateServiceIntent, 0);
// Cancel it
try{
alarmManager.cancel(pendingUpdateIntent);
} catch (Exception e) {
Log.e(TAG, "Update failed " + e.getMessage());
}
Courtsey
Let's see if someone found this problem and can help me to solve the mistery. I have the following situation. The app is a simple to-do list:
public class NewToDo extends Activity {
private PendingIntent pendingIntent;
private AlarmManager manager;
...
When the user creates a to-do with a notification, I create it in one of the methods of this class like this:
int interval = 30000;
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
/*Let's let the putExtras apart, as documentation says they're not considered when comparing intents, but I add some of them*/
manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
pendingIntent = PendingIntent.getBroadcast(getBaseContext(), _id, alarmIntent, alarmIntent.FILL_IN_DATA);
/*Printing _id we see 3, for instance, but is a unique identifier to associate the notification with this to-do item*/
/*I use the flag alarmIntent.FILL_IN_DATA because I want to send extras to create a custom notification*/
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + interval, interval,
pendingIntent);
I quit from the app (but no difference if I don't quit).Then the notification arrives correctly each 30 seconds, and selecting it the app launchs on the detailed view of the item. An actionbar button allows editting it, calling again the same class, NewToDo.
While editting I can cancel the notifications associated with the to-do, and my code makes that like this -in the NewToDo class-:
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent i = new Intent(this, AlarmReceiver.class); //creating a matching Intent
Log.v(getString(R.string.app_name), "_id: " + _id); //the 3 aforementioned
PendingIntent displayIntent = PendingIntent.getActivity(getBaseContext(), _id, i, alarmIntent.FILL_IN_DATA);
alarmManager.cancel(displayIntent);
But the notifications keeps appearing each 30 seconds, so they're not cancelled.
I saw the following suggestion in another post:
"Intent intentYouWantToCancel = new Intent(this, AlarmReceive.class);
intentYouWantToCancel.setAction("aRelevantString");
when you set the alarmmanager as well as when you want to delete it. "
So I put in both intents as 'aRelevantString' a cast to String of the unique identifier. But same problem.
Also changed the getBaseContext() for this, just in case, but no difference.
No errors, just the notifications keep repeating ignoring my cancel. Any idea?
PS: I restart the AVD each time I run it. I realised that the way I was using the print of the filterEquals had no sense at all (too many hours with this), but that doesn't affect the rest of the question.
I finally solved it like this. To create the alarm:
public class NewToDo extends Activity {
private PendingIntent pendingIntent;
private AlarmManager manager;
...
int interval = 30000;
manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent alarmIntent = new Intent(this, AlarmReceiver.class);
alarmIntent.putExtra("id", _id);
pendingIntent = PendingIntent.getBroadcast(this, _id, alarmIntent,0);
manager.setInexactRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis() + interval, interval,
pendingIntent);
To cancel that concrete alarm:
manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(getBaseContext(), AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
getApplicationContext(), _id, i, 0);
manager.cancel(pendingIntent);
pendingIntent.cancel();
I want to cancel all the alarms that are set..... I have searched a lot and tried a lot of things but nothing worked... When I set alarm for say after 2 minutes and then I cancel it, it will still fire after 2 minutes.....
Any help will be appreciated.
Method for creating alarms :
Intent intent = new Intent(c, AlarmReceiver.class);
intent.putExtra("task", task);
intent.putExtra("id", id);
PendingIntent pendingIntent = PendingIntent.getActivity(c, code, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
This is to cancel alarms :
Intent intent = new Intent(c, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getActivity(c, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
am.cancel(pendingIntent);
When you schedule your alarms, your second parameter to getActivity() is code.
When you try to cancel your alarms, your second parameter to getActivity() is 0. This will only successfully cancel an alarm whose code was 0.
If you want to consistently cancel the alarms, you need to create equivalent PendingIntents, and that means, among other things, that the second parameter to getActivity() needs to be the same.
You are setting the alarm with request code (second parameter for getActivity) equals to code, while when you are cancelling the alarm, the second parameter is 0. If the value of code is not 0 the alarm wouldn't be cancelled.
In order to fire and cancel multiple alarms, you need to use unique value for requestCode (second parameter) in PendingIntent.getActivity
see this code that will set 3 Alarms using three unique request Codes,
for (int requestCode = 1; requestCode <= 3; requestCode++) {
PendingIntent pendingIntent = PendingIntent.getActivity(c, requestCode, intent,PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
}
You can cancel the Alarm using the same requestCode (and other parameters) that were used to set it.
The other parameters which are needed to matched are,
The "action" in the Intent must be the same (or both null). Otherwise they do not match.
The "data" in the Intent must be the same (or both null). Otherwise they do not match.
The "type" (of the data) in the Intent must be the same (or both null). Otherwise they do not match.
The "package" and/or "component" in the Intent must be the same (or both null). Otherwise they do not match. "package" and "component" fields are set for "explicit" Intents.
The list of "categories" in the Intent must be the same. Otherwise they do not match.
Please see this answer for more details.
To cancel an alarm you need no re-create the same PendingIntent and pass the same request code.
You can see my solution here
When you cancel alarm its intent must be same with intent which used for set alarm .
so just add following 2 line
intent.putExtra("task", task);
intent.putExtra("id", id);
So your final code will be
Intent intent = new Intent(c, AlarmReceiver.class);
intent.putExtra("task", task);
intent.putExtra("id", id);
PendingIntent pendingIntent = PendingIntent.getActivity(c, code, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager)c.getSystemService(Context.ALARM_SERVICE);
am.cancel(pendingIntent);
I am setting multiple alarms which will have the exact same PendingIntent object, but their time of going off is different. If I cancel one alarm by providing the same Intent object to PendingIntent, and pass this to AlarmManager.cancel(), will it cancel all the alarms (i.e. with different starting times) or will it exhibit some other behavior?
Here is the code:
while(size != 0)
{
timeToSet = getNewTime(); //gets calendar object
Intent intent = new Intent(this, MyAlarmReceiver.class);
intent.putExtra("uniqueid", uuid);
intent.putExtra("vibrate", myalarm.getVibrate());
intent.putExtra("important", myalarm.getImportant());
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(),
0, intent, PendingIntent.FLAG_UPDATE_CURRENT | Intent.FILL_IN_DATA);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, timeToSet.getTimeInMillis(), 604800000, pendingIntent);
size--;
}
So the Intent object is same for all the alarms, but the time is different.
Now when I cancel these alarms:
Intent intent = new Intent(this, MyAlarmReceiver.class);
intent.putExtra("uniqueid", uuid);
intent.putExtra("vibrate", myalarm.getVibrate());
intent.putExtra("important", myalarm.getImportant());
PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT | Intent.FILL_IN_DATA);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
Will all the alarms get cancelled? That is what I want it to do. I could use a different requestCode in every PendingIntent, but it will be better if all of them get cancelled as I dont want to maintain and store these extra requestCodes.
Thanks!
If you have a predefined amount of alarms you can set a unique requestCode (second parameter of getBroadcast) for each alarm. But I'm not sure if that works for you. If you don't specify a requestCode all alarms will be seen as equal by filterEqualsand therefore all alarms will be canceled.
This is what sets the alarm
public void setSilent(Long taskId, Calendar when){
Intent i = new Intent(mContext, SilentReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(mContext, 1 , i, PendingIntent.FLAG_ONE_SHOT);
mAlarmManager.set(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), pi);
It takes in an id and date to use with the intent.
I am canceling it in another file when the user clicks delete. using
Intent i = new Intent(null, SilentReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(null, 1 , i, PendingIntent.FLAG_ONE_SHOT);
should this work because it has the same request code as the first one or am I doing something wrong?
You have to save a reference to your first PendingIntent. This way you can use:
mAlarmManager.cancel(pi);
And the alarm should be cancelled.
This answer has been repeated many times. Please search before asking.
Be careful to send a PendingIntent to stop the alarm with the same data than the Intent to create the alarm: problem with cancel the alarm manager pending intent