How to cancel this repeating alarm?
Asked Answered
C

3

36

I'm writing something like a reminder for users. Users will set reminders for their events, when the time comes, a repeating alarm will be set to trigger a status bar notification. But the alarm seems non-stop after I selected the notification or cleared the notification. I am not sure where to cancel this repeating alarm. Below are some of the codes: Set up the repeating alarm in my main activity

alarmTime = Calendar.getInstance();
Intent intent = new Intent(this, AlarmReceive.class);
PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

alarmTime.add(Calendar.MINUTE,offset_time);

//Schedule the alarm
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, alarmTime.getTimeInMillis(), 30 * 1000, sender);

In my OnReceive method, I just display the notification in status bar and set the flag as FLAG_AUTO_CANCEL

manager = (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);

// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.medical, text, System.currentTimeMillis());

PendingIntent contentIntent = PendingIntent.getActivity(context, 0, i, 0);

notification.flags = Notification.FLAG_AUTO_CANCEL;

manager.notify(R.string.service_text, notification);

How can I stop the alarm when the user selects the notification or clears it?

Colicroot answered 25/7, 2010 at 18:44 Comment(0)
C
83

Call cancel() on AlarmManager with an equivalent PendingIntent to the one you used with setRepeating():

Intent intent = new Intent(this, AlarmReceive.class);
PendingIntent sender = PendingIntent.getBroadcast(this, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);

alarmManager.cancel(sender);
Culhert answered 25/7, 2010 at 19:56 Comment(16)
I want to cancel this alarm after user sees the notification, but the notification is defined in onReceive. So how can I determine whether user knows about the notification in my main activity before I cancel the alarm?ThanksColicroot
@Wen: use a different Intent (e.g., different action) to start your main activity from the Notification than you use for the launcher. Or, if you are bringing an existing instance of the main activity to the foreground, your Notification will trigger onNewIntent() in the activity, so you can cancel the alarm there.Culhert
The notification will trigger another activity. What do u mean by use a diff Intent to start activity from the Notification than use for launcher?Colicroot
@Wen: "The notification will trigger another activity.". OK, put your cancel-the-alarm code in onCreate() of that activity, then.Culhert
there is no such Flag which value would be 0. why do you use that flag in getBroadcast() then?Pipsqueak
@laplasz: 0 provides the default behavior.Culhert
What is the default behavior then, I haven't found any info about that.Pipsqueak
@laplasz: The default behavior is to not do any of the other flags. IOW, the original PendingIntent is not modified and is simply reused. If you have further inquiries on this topic, please open a fresh StackOverflow question.Culhert
I have 2 questions: 1) Does the intent have to be the same instance or just be the same instance. 2) Does I need to add the extras to the intent?Langer
@Langer the extras do not need to be the same. When comparing the intents with Intent.filterEquals the extras are ignored.Sorcerer
@Culhert I have CardViews with Due dates in a RecyclerView list. When a Due date is reached, an alarm is triggered which then triggers a notification. When the user long presses a CardView, its data (including the Duedate) is deleted from an SQLite database. But I also need to delete the alarm so no notification is triggered. So how can the cancel() for AlarmManager with an equivalent PendingIntent be safely called from my RecyclerView list Activity which is different from the original Activity that created the initial PendingIntent and alarm?Blunder
@AJW: Create a PendingIntent with the same ID (second parameter to methods like getBroadcast()) and an equivalent Intent. By "an equivalent Intent" I mean one with all the same routing data (component name, action string, MIME type, Uri, categories). Extras can be different between the two Intent objects. Then, pass that PendingIntent to cancel().Culhert
@Culhert Will try that. So to delete the specific alarm for the specific Duedate, I have to pass the ID of the original PendingIntent in a Bundle using Extra from the original Activity to the RecyclerView Activity?Blunder
@AJW: Uh, I guess so. That's deep in the implementation of your app, so I cannot really comment on that.Culhert
@Culhert In the second Activity, I set up the exact same Intent and Pending Intent and used the exact same ID. The alarm still triggers and therefore the Notification still fires. Any thoughts on how to fix?Blunder
can you please help me to fix this error #51405897 spending lot of time in this ,please help me bro @CulhertExecrable
G
5

I tried various methods and couldnt get it to work, so I decided to do a dirty trick. When I want to cancel my repeating alarm, I use the same method that created my alarm (and hence replacing the old one) and then cancel it right away. With this method if the boolean variable is set to true it creates an alarm ow it replaces and then cancels the replacement which has the same id:

static void CancelRepeatingAlarm(Context context, boolean creating){
    //if it already exists, then replace it with this one
    Intent alertIntent = new Intent(context, AlertReceiver.class);
    PendingIntent timerAlarmIntent = PendingIntent
            .getBroadcast(context, 100, alertIntent,PendingIntent.FLAG_CANCEL_CURRENT); 
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    if (creating){
        alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), INTERVAL, timerAlarmIntent);
    }else{
        alarmManager.cancel(timerAlarmIntent);
    }
Grahamgrahame answered 15/11, 2016 at 6:14 Comment(0)
D
3

In your MainActivity, set the alarm time. If you're going to use multiple alarms, use SharedPreferences to store their respective IDs. Here is the code:

PendingIntent pendingIntent = PendingIntent.getBroadcast(MainActivity.this, _id,intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager = (AlarmManager) getSystemService(Activity.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, targetCal.getTimeInMillis(),
            pendingIntent);

public static Context getContext() {
    return mContext;
}
mContext=mainactivity.this;

In your second Activity use same ID from SharedPreferences. In my code, I get the ID from the ArrayList, Alarm_id. Last, you can use the MainActivity context here with MainActivity.getContext(). Here is the code:

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intentAlarm = new Intent(AlarmListviewActivity.this,
        MainActivity.class);
PendingIntent morningIntent = PendingIntent.getBroadcast(MainActivity.getContext(), Alarm_id.get(positon),
        intentAlarm, PendingIntent.FLAG_CANCEL_CURRENT);

alarmManager.cancel(morningIntent);
morningIntent.cancel();
Decreasing answered 26/6, 2015 at 6:27 Comment(1)
I am trying to cancel a Notification in a second Activity using similar code you have listed above. But Android Studio says "Non-static field "mContext" cannot be referenced from a static context. Also the "mContext = MainActivity.this;" is also throwing an error. Any thoughts on how to correct?Blunder

© 2022 - 2024 — McMap. All rights reserved.