0

I've programmed an app with multiple alarms using the AlarmManager. I also have a method which cancels all current/pending alarms. It works well, however if the user closes the app from recents (alarms are still active, as intended), my cancel-alarms-method doesn't work anymore (the app crashes). Is there any solution to this? How can I cancel my alarms after the user has closed the app?

This is what my alarms look like:

ArrayList<PendingIntent> intentArray = new ArrayList<PendingIntent>();
AlarmManager am = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
...
Intent intent = new Intent(this, AlertReceiver.class);
Long cal = new GregorianCalendar().getTimeInMillis() + sms_in_x_minutes * 60 * 1000;
PendingIntent i1 = PendingIntent.getBroadcast(this, intent_id++, intent, 0);
am.set(AlarmManager.RTC_WAKEUP, cal, i1);
intentArray.add(i1);

This is what my cancel-method looks like:

private void cancelAlarms(){
    if(intentArray.size()>0){
        for(int i=0; i<intentArray.size(); i++){
            am.cancel(intentArray.get(i));
        }
        intentArray.clear();
    }
}

My guess is that intentArray and am are empty after I close the app, and the PendingIntents are not saved. But I don't know how to work around that.

Jason
  • 2,278
  • 2
  • 17
  • 25
haby123
  • 33
  • 7
  • Have you tried the Android [Life Cycle](http://developer.android.com/reference/android/app/Activity.html#ActivityLifecycle), You should be able to cancel the alarms `onDestroy` however I'm not sure how that would work in a low memory situation. – hoss Jul 28 '15 at 13:08
  • Yea as Pier suggested I will have to use onDestroy , which is fine. It will prevent all my crashed. Ideally I would have liked to cancel all active alarms after i close and start the app. Maybe thats just not possible. Thanks a lot anyway! – haby123 Jul 28 '15 at 13:28
  • An app never needs multiple alarms set up. Only the earliest is required. When that one fires, your app can then set up the next earliest as the first task it performs. This makes keeping track of your alarms much more simple. It also makes it easier to set them up again after a reboot as alarms do not survive rebooting. – Kuffs Jul 28 '15 at 13:35
  • Thanks Kuffs! I can definitely do that, one alarm is probably a lot smarter :) But even if I only use one (the earliest) alarm. Is there a way (assuming i don't use OnDestroy) to cancel that alarm after the app was closed and reopened ? – haby123 Jul 28 '15 at 13:44
  • See my answer. below. – Kuffs Jul 28 '15 at 13:45

2 Answers2

3

Do not keep an array of Pending intents. As you correctly diagnosed, your array is empty after the app is closed which causes a crash when you are trying to access them again.

Set up ONLY the earliest alarm. Save the ID of the alarm to temp storage (e.g SharedPreferences). (If it is easier, you can also use a constant value for the ID as you now only have one alarm to think about)

When your alarm fires, you can set up the next earliest alarm as the first task that is performed.

If you want to cancel your alarm and have an ID value saved in your SharedPreferences, use this to recreate the AlarmManager and cancel the alarm. If there is no ID value then no alarms are set and no cancellation is required.

Kuffs
  • 35,581
  • 10
  • 79
  • 92
  • 1
    Thank you so much!! Creating another alarm with the same ID and canceling it was the idea i was looking for. I will also follow your advice only have 1 active alarm at a time. It will make my code much simpler! – haby123 Jul 28 '15 at 13:53
  • It is a common scenario (to set up multiple alarms) but logically, the second earliest can NEVER fire before the earliest and so is not needed until the earliest one has already fired. – Kuffs Jul 28 '15 at 13:55
  • Where is the ID of Alarm? – Talha Sep 05 '17 at 06:40
  • In the code in the question above, it is named _intent_id_ – Kuffs Sep 05 '17 at 07:04
  • So i can remove (cancel ) specific alarm by `PendingIntent i1 = PendingIntent.getBroadcast(this, , intent, 0);`, using this intent object? – Talha Sep 05 '17 at 07:39
  • If the Intent and the ID are identical then yes. This is what my final paragraph is saying. – Kuffs Sep 05 '17 at 08:20
-1

I think you should add the closing alarm method to the ondestroy method of your app, because if an user closes your app without stopping them, your method will never be called causing the crash of the app.

hope it works :)

EDIT: try to have a look at service and similar. some months ago i did use them in an android app and i remember that even if i close the app from recents, this service still worked and for closing it i had to add a method in app or to stop the process. If i got it this should be the method you were looking for, sorry if i'm not precise but months passed and i forgot the name of the service i used, i'm just sure it was a service :)

Pier Giorgio Misley
  • 5,305
  • 4
  • 27
  • 66
  • Mh good idea, i will do that. It definitely prevent all the crashes. It's not quite the answer i was looking for, since i would like to cancel all my alarms after i start up the app again. But thanks! – haby123 Jul 28 '15 at 13:26