1

I am trying to stop the alarmManager in the MainActivity from the onBackPressed() method in the Map activity. I have tried the code below but the alarmManager is not being stoped and still firing. How can I fix it?

Code in the MainActivity:

Intent intent = new Intent(MainActivity.this, GetLLRD.class);
intent.putExtra("json_data", json);
PendingIntent pendingIntent = PendingIntent.getService(
        getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Calendar cal = Calendar.getInstance();
alarm.setRepeating(AlarmManager.RTC_WAKEUP,
System.currentTimeMillis(), 20 * 1000, pendingIntent);
startService(intent);

Code in the Map Activity:

@Override
public void onBackPressed() {       
    Intent intent = new Intent(Map.this, MainActivity.class);
    PendingIntent pendingIntent = PendingIntent.getService(
            getApplicationContext(), 123, intent, PendingIntent.FLAG_UPDATE_CURRENT);

    AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    alarm.cancel(pendingIntent);
}
Ibrahim Khan
  • 20,616
  • 7
  • 42
  • 55
MrPencil
  • 934
  • 8
  • 17
  • 36
  • The PendingIntent you're trying to cancel is not the same you're setting the alarm on initially. – ci_ Aug 01 '15 at 21:09
  • @ci_: And how can I make them the same? where is my error? – MrPencil Aug 01 '15 at 21:18
  • Well, the Intents are for different classes for starters. You're setting the alarm on GetLLRD.class and then try to cancel it on MainActivity.class. – ci_ Aug 01 '15 at 21:23
  • I tried it with this intent ` Intent intent = new Intent(Map.this,GetLLRD.class);` and it works now. Thanks. – MrPencil Aug 01 '15 at 21:55

2 Answers2

2

u problem is u use two different classes for intent to create and stop alarm:

Intent intent = new Intent(context,
                    GetLLRD.class);

Intent intent = new Intent(context,
                    MainActivity.class);

/** as in source code  - new intent constructor */
public Intent(Context packageContext, Class<?> cls) {
    mComponent = new ComponentName(packageContext, cls);
}

if u want to check if u got the same pending intent as before you can try to use:

 Intent.filterEquals(oherIntent);

to cancel alarm you have two options use flag or use the same intent on alarm:

PendingIntent.FLAG_CANCEL_CURRENT

& i advice to make pending intent as final - example:

 /**
 * create pending intent
 */
final PendingIntent pIntent(Intent alarmIntent) {
    // Create a PendingIntent to be triggered when the alarm goes off
    return PendingIntent.getBroadcast(getApplicationContext(), AlarmReceiver.REQUEST_CODE,
            alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
}


 /**
 * cancel alarm
 */
public void cancelAlarm(Intent alarmIntent, Context context) {
    try {

        AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        /** use flag cancel here */
        PendingIntent pIntent = PendingIntent.getService(context, AlarmReceiver.REQUEST_CODE, alarmIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        /** cancel alarm */
        alarm.cancel(pIntent);

    } catch (Exception e) {
        // handle exception here 
    }
}

why to make pending intent final ?

because to cancel alarm u need:

  • Create pending intent with the same id and appropriate intent FLAG.

    (to get reference to current pending intent)

PendingIntent.getBroadcast(context, REQUEST_CODE, intent, 
                       PendingIntent.FLAG_UPDATE_CURRENT);
  • Cancel that pending intent.
PendingIntent.cancel();
  • Cancel the alarm using alarm manager.
AlarmManager.cancel(PendingIntent);

A PendingIntent itself is simply a reference to a token maintained by the system describing the original data used to retrieve it. This means that, even if its owning application's process is killed, the PendingIntent itself will remain usable from other processes that have been given it. If the creating application later re-retrieves the same kind of PendingIntent (same operation, same Intent action, data, categories, and components, and same flags), it will receive a PendingIntent representing the same token if that is still valid, and can thus call cancel() to remove it.

Community
  • 1
  • 1
ceph3us
  • 7,326
  • 3
  • 36
  • 43
  • I dont understand your Point how can I make it final? And where have I to put this line `PendingIntent.FLAG_CANCEL_CURRENT`? – MrPencil Aug 01 '15 at 21:04
  • Why are you using `getBroadcast` in `pIntent` and `getSystemService` in `cancelAlarm`? I am not using Broadcastreceiver. – MrPencil Aug 01 '15 at 21:21
  • @MrPencil i gave u idea how create pending intent - as final to reuse it on cancel - u pending intent could be as activity / or broadcast etc – ceph3us Aug 01 '15 at 21:24
  • The PendingIntent does not have to be exactly the same object, that's not correct. – ci_ Aug 01 '15 at 21:29
  • @ci_ - see i gave two choices – ceph3us Aug 01 '15 at 21:30
  • @TomaszBest: I have tried it with the flag `PendingIntent.FLAG_CANCEL_CURRENT` but it does not work. I implemented my cancle code based on this answer http://stackoverflow.com/questions/6389143/stop-the-setrepeat-of-android-alarmmanager – MrPencil Aug 01 '15 at 21:32
  • The main Problem is the context as `ci_` emphasized before. With this context it works `Intent intent = new Intent(Map.this, GetLLRD.class);` You can edit it in you answer then I will mark your answer as answered. – MrPencil Aug 01 '15 at 21:55
  • @MrPencil - not context but second constructor argument (intent class) - try it out - but yr point is right – ceph3us Aug 01 '15 at 22:16
-1

if you are using activity, use

PendingIntent pendingIntent = PendingIntent.getActivity(getApplicationContext(),
                            12345, intent,0);
codetiger
  • 2,650
  • 20
  • 37
skn
  • 1