How to cancel AlarmManager using PendingIntents in different classes? - android

I am trying to use AlarmManager for doing some tasks upon an alarm time I set.
I know that I have to use same PendingIntent to make and cancel alarm.
But, the problem is that I am making the alarm in class "ClassA" and cancelling the alarm in class "ClassB" later on.
That's why I wonder if the intents to be broadcast in each class are same or not since they use "different contexts" as they are in different classes, I guess.
Can they be considered as same PendingIntent and Can I cancel the alarm?
If not, how can I make them same?
For making an alarm in class "ClassA" (that extends BroadcastReceiver):
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, myReceiver.class);
PendingIntent pender = PendingIntent.getBroadcast(context, codeNum, intent, 0);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, pender);
For cancelling the alarm in class "ClassB" (that extends BaseAdapter):
alarmMgr = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, myReceiver.class);
PendingIntent pilocal = PendingIntent.getBroadcast(context, codeNum, intent, 0);
pilocal.cancel();
alarm.cancel(pilocal);

You can retrieve the same kind of PendingIntent by providing same operation, same Intent action, data, categories, and components, and same flags.
Yes, you can cancel your alarm from another class if its still valid. Just make sure you pass the same parameters used, request code used to create the pending intent.

Related

Start of activity through AlarmManager PendingIntent after clearing app process

My app will allow user to set desired time on which activity will trigger. I used AlarmManager to open activity. Below is the code for same.`
/* Intent intent = new Intent(this, AlarmNotificationActivity.class);
PendingIntent pendingIntent=PendingIntent.getActivity(getBaseContext(), RQS_1, intent,
0);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(),interaval, pendingIntent);*/
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent=PendingIntent.getBroadcast(getBaseContext(), RQS_1, intent,
0);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(),interaval, pendingIntent);
If I use the PendingIntent with getActivity even the app killed AlarmNotification is came up.
If I use the PendingIntent with getBroadcast if the app killed AlarmNotification is not coming up.
Question is After clearing the app process from task list
Is it possible to trigger Notification Activity of my app through broadcast.
If Yes - Please share any link or sample code (TIA)
If No - How Clock App in Mobile triggers Alarm on specific time. Do I
need to define service to achieve this.

AlarmManager can't cancel an alarm

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();

Android AlarmManager Constantly goes off

I am using AlarmManager for my Timer. I have 2 classes.
In the first class (MainActivity) I am starting my alarm with the next code:
public void startAlarm(long Seconds) {
Intent myIntent = new Intent(MainActivity.this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(MainActivity.this, 13141337,
myIntent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, (int) Seconds);
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
pendingIntent);
}
In another class (AlarmSound), where the alarm goes off and the phone vibrates, I'm calling my cancel Alarm method.
public void stopAlarm(){
Intent intentstop = new Intent(AlarmSound.this, MyAlarmService.class);
PendingIntent senderstop = PendingIntent.getBroadcast(AlarmSound.this,
13141337, intentstop, 0);
AlarmManager myalarm = (AlarmManager) getSystemService(ALARM_SERVICE);
myalarm.cancel(senderstop);
Log.w("Karl","stopAlarm?");
}
Is this the correct way to do this? Because my alarm constantly goes off on android 4.1.
Thanks in advance!
Your Cancel wont work. The pending Intents have to match - since they have a different context (MainActivity and AlarmSound) this cancel wont work. You have to also use getService on both.
You can
a) try to recreate a matching pending Intent
b) get the pendingIntent that started the Service in the Service and use that to cancel
But usually every Alarm just goes off once if you dont use setRepeating().
Are you sure you are terminating your Service correctly with stopself() and are giving it the right flag in the onStartCommand() Method?

How to cancel multiple alarms with duplicate PendingIntent at once?

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.

Alarmmanager with pending Intent

The code snippet below....
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
///////////Do something////////////////////////
showtext.startScan();
//SEt Alarm
Intent intent = new Intent(this, TextReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+9000, pi);}
And my Receiver :
TextReceiver extends BroadcastReceiver{
public void onReceive(Context context, Intent intent) {
///Show text/////
}
}
The thing is that when I run the program after 9sn, I am getting an error that "The app stopped unexpectedly". Why I get this error?
My goal is to show the text every 9sn. What is the correct usage of AlarmManager in the main activity
OR Should I set alarm in the BroadcastReceiver ?
Which one does makes sense: am.setRepeating or am.set in terms of my goal?
**Edit: How can I change my alarm code to run in the Broadcast Receiver ? **
//try this
AlarmManager am=(AlarmManager)getApplicationContext getSystemService(Context.ALARM_SERVICE);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(),(9 * 1000), pendingIntent);
Never, ever use FLAG_CANCEL_CURRENT with PendingIntents that are set as alarms.
What happens is that you wind up canceling the validity of the PendingIntent currently held by the alarm manager, and this means that the alarm manager can no longer tell that any newly-set alarm matches that old PendingIntent. You wind up with the old (invalid) alarm still registered along with your new one. If you keep doing this you can wind up with hundreds (or more!) stale alarms registered in the system, none of which will actually do anything but which are taking up memory and CPU.

Categories

Resources