26

I want cancel AlarmManager which define a service,in this service might start a new AlarmManger or cancel alarm that defined before.And I know the params pendingintent in alarmManager.cancel(PendingIntent),must be the same.compare with filterEquals(Intent other) but It still not work.cancel failed. here is my code

public class GetRoundStroe {
    private Store[] stores;
    private Context mContext;

    public GetRoundStroe(Context mContext) {
        this.mContext = mContext;
    }

    public Store[] getStores() {
        if (ComCommand.haveInternet(mContext)) {
            start_am_normal();
        } else {
            start_am_silence();
        }
        return stores;
    }

    public Store[] start_am_silence() {


        long firstTime = SystemClock.elapsedRealtime();

        AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

        if (AlarmHolder.mAlarmNormal != null) {
            am.cancel(AlarmHolder.mAlarmNormal);

        }

        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                firstTime, TestSwitch.getInstance().getSilence_time(), AlarmHolder.mAlarmSilence);


        return null;


    }

    public Store[] start_am_normal() {


        long firstTime = SystemClock.elapsedRealtime();

        AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);

        if (AlarmHolder.mAlarmSilence != null) {
            MyLog.e(GetRoundStroe.class,"AlarmHolder.mAlarmSilence"+AlarmHolder.mAlarmSilence+"");
            am.cancel(AlarmHolder.mAlarmSilence);
        }
        am.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
                firstTime, TestSwitch.getInstance().getNormal_time(), AlarmHolder.mAlarmNormal);

        return null;
    }

    private static final class AlarmHolder {
        static final PendingIntent mAlarmSilence = PendingIntent.getService(ApplicationContext.getInstance(),
                0,
                new Intent(ApplicationContext.getInstance(), GetRoundSilenceService.class),
                0);

        static final PendingIntent mAlarmNormal = PendingIntent.getService(ApplicationContext.getInstance(),
                0, new
                Intent(ApplicationContext.getInstance(), GetRoundNormalService.class),
                0);

    }
}

GetRoundSilenceService and GerRoundNormalService invoke start_am_normal() or start_am_silence; Anyone could help me? thanks

Albert.Qing
  • 4,220
  • 4
  • 37
  • 49

2 Answers2

73
   myIntent = new Intent(SetActivity.this, AlarmActivity.class);
   pendingIntent = PendingIntent.getActivity(CellManageAddShowActivity.this,
       id, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
   pendingIntent.cancel();
   alarmManager.cancel(pendingIntent);

These lines of code surely can help you remove/cancel the pending intent and alarm.

The main thing that you will need is:

  1. Create pending intent with the same id and appropriate intent FLAG.
  2. Cancel that pending intent.
  3. Cancel the alarm using alarm manager.
Mario Kutlev
  • 4,897
  • 7
  • 44
  • 62
MKJParekh
  • 34,073
  • 11
  • 87
  • 98
  • 4
    perfect answer, both pendingIntent.cancel() and alarmanager.cancel(pendingIntent) need to be called to "completely" cancel the pendingIntent – Soham Feb 20 '14 at 23:43
  • @MKJParekh why not this? PendingIntent.FLAG_CANCEL_CURRENT – likejudo Apr 13 '14 at 11:02
  • 1
    @likejiujitsu Actually we are creating PendingIntent so we can cancel it we are not creating for any other use. So that's our only need. Now the flag you suggested :- `PendingIntent.FLAG_CANCEL_CURRENT` This flag suggests that The PendingIntent object you are creating currently will not be created if any other pending intent object available with the same id. In our case there will be always a object available to so new object will not be created and the previous one will be assigned to this object. So Yes we can use that flag also, I am sure it will work fine. – MKJParekh Apr 22 '14 at 07:23
  • You need not cancel the pending intent. And when using FLAG_CANCEL_CURRENT, AlarmManager.cancel not work, the alarm still show in the ouput of `dumpsys alarm`. I don't know why. – Shaw Mar 14 '16 at 07:11
  • 1
    @Shaw The FLAG_CANCEL_CURRENT documentation specifically says that it will cancel an existing PendingIntent and replace it with the new one you are passing to AlarmManager. I find the name to be confusing, even though it's technically not inaccurate. https://developer.android.com/reference/android/app/PendingIntent.html#FLAG_CANCEL_CURRENT – Ethan Hohensee Jun 14 '17 at 23:01
  • @MKJParekh I have a similar use case where I am trying to cancel a pendingIntent in Activity A from Activity B, here: https://stackoverflow.com/questions/61161676/android-cancel-alarm-and-pendingintent-in-different-activity Any ideas on how to fix? – AJW Apr 12 '20 at 01:17
1

@MKJParekh answer is correct, however I would like to add more information so that we all know what will work and what will not.

Lets say on activityA you create and set the AlarmManager to open activityC in 30 seconds, then on some other activity which can be any, we want to cancel that AlarmManager. Thus, we would do the following;

in activityA we create and set the AlarmManager;

//activityA
Intent myIntentA = new Intent(actvityA.this, activityB.class)
myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent myPendingIntent = PendingIntent.getActivity(activityA.this, 0, myIntentA, PendingIntent.FLAG_ONE_SHOT);

//Calendar with the time we want to fire the Alarm
Calendar calendar = Calendar.getInstance();   // Get Current Time
calendar.add(Calendar.SECOND,30);      //Fire Alarm in 30 seconds from Now.                  

((AlarmManager)getSystemService(ALARM_SERVICE)).setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), myPendingIntent);

in Another Activity some time later we want to cancel such AlarmManager created in activityA which we have no access to. Lets call this current activity activityZ;

//activityZ
Intent myIntentZ = new Intent(activityZ.this, activityB.class);
PendingIntent pendingIntentZ = PendingIntent.getActivity(activityZ.this, 0, myIntentZ, PendingIntent.FLAG_ONE_SHOT);

((AlarmManager)getSystemService(ALARM_SERVICE)).cancel(pendingIntentZ);

Some important points,

The context we provide in activityA in new Intent(context) and getActivity(context) are the same, however they do not have to match the activity from where we are canceling the AlarmManager, in this case activityZ has another context.

The class we want to open with the AlarmManager has to be the same in both activities new Intent (context, activityB.class), the requestCode which is an int must be the same, I used 0 for this example. Finally the flag has to be the same in both activities PendingIntent.FLAG_ONE_SHOT.

myIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); was used because PendingIntent.getActivity requires it if we are starting an activity outside of a context of an existing activity.

ArtiomLK
  • 2,120
  • 20
  • 24
  • suggested edit: given your first line defining the Intent as "myIntentA" then your second line "myIntent.setFlags(...);" should be: "myIntentA.setFlags(...);" – AJW Apr 11 '20 at 20:30
  • I am trying to send a message to a BroadcastReceiver and there is no equivalent "Intent.FLAG_ACTIVITY_NEW_TASK" for getBroadcast... for the pendingIntent. Any ideas on how to cancel an Alarm and pendingIntent in another Activity for getBroadcast? see https://stackoverflow.com/questions/61161676/android-cancel-alarm-and-pendingintent-in-different-activity – AJW Apr 11 '20 at 20:43