如何获取和取消PendingIntent?

26

我有一个AlarmManager,我正在使用它在特定时间向用户发送通知。由于存在多个闹钟,我正在创建多个待处理意图并分配唯一的ID。但是,在某些情况下,我需要获取所有待处理意图,然后取消它们,以便重置闹钟。我尝试过这样做,但好像仍然无法正确执行,所以我有几个问题:

这是正确获取和取消PendingIntent的方法吗?

Intent intent = new Intent(con, AppointmentNotificationReciever.class);
PendingIntent sender = PendingIntent.getBroadcast(con, id, intent,
        PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) con.getSystemService(Context.ALARM_SERVICE);
am.cancel(sender);

待定意图的意图是否需要完全匹配(包括附加项等)?

PendingIntent 标志位是否需要与原始待定意图匹配?


FLAG_CANCEL_CURRENT 不会有任何区别 - 想要进行真正优秀的分析,请参见此链接 - Mr_and_Mrs_D
2个回答

61

我发现实际上你并不能“获取”到待处理的intent...你需要完全按照当初创建它时的方式重新创建它(同时也要重新创建Intent),然后将其传递给AlarmManager的cancel函数。因此,我之前发布的代码只要在创建时是这样的就不会有问题。希望对某些人有所帮助。


我遇到了你提到的同样的问题。你能简要解释一下我该如何克服这个问题吗?如果可能的话,你能提供创建和取消挂起意图的代码片段吗? - Krishna Prasad
3
请尝试此答案:https://dev59.com/DWkw5IYBdhLWcg3wirGs - Whitecat
如果我无法重新创建待处理意图,因为我不知道唯一的ID并且闹钟已被删除,该怎么办?我该如何删除此待处理意图。我觉得在删除后仍然存在一个处于活动状态的闹钟。 - stanley santoso
1
我曾经遇到过类似的问题。除了通过闹钟管理器取消PI之外,我还执行了pi.cancel - JenniferG
1
@JenniferG,Pending Intent 的第二个参数是用于标识它的位置。通过在 INTENT 中传递 Pending Intent 的“id”以及一组额外的数据包,每次触发接收器时,您的接收器都将具有 Pending Intent 的唯一 id。或者,如果您不在接收器内部,则可以删除所有的接近警报并重新创建它们(基于更新后的数据,我想)。 - tony gil

1
这是我测试创建和取消闹钟的示例实现。
    public void setTHEalarm(Calendar aCalendarToAlarm) {
    int id;
    Intent intent;
    PendingIntent pendingIntent;
    AlarmManager alarmManager;

    //I create an unique ID for my Pending Intent based on fire time of my alarm:

    id = Integer.parseInt(String.format("%s%s%s%s",

            aCalendarToAlarm.get(Calendar.HOUR_OF_DAY),
            aCalendarToAlarm.get(Calendar.MINUTE),
            aCalendarToAlarm.get(Calendar.SECOND),
            aCalendarToAlarm.get(Calendar.MILLISECOND))); //HASH for ID

    intent = new Intent(this,AlarmReceiver.class);
    intent.putExtra("id",id); //Use the id on my intent, It would be usefull later.

    //Put the id on my Pending Intent:
    pendingIntent = PendingIntent.getBroadcast(this,id,intent,0);
    alarmManager = (AlarmManager)

            this.getSystemService(Context.ALARM_SERVICE);


    alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP,aCalendarToAlarm.getTimeInMillis(),CustomDate.INTERVAL_MINUTE,pendingIntent);


    Log.w(TAG+" Torrancio","Created alarm id: "
            +id+" -> "
            +CustomDate.dateToHumanString(aCalendarToAlarm.getTime()));

    //Keep a reference in a previously declared field of My Activity (...)
    this.idSaved = id;

}

//Now for canceling
public void setCancel() {
    int id;
    Intent intent;
    PendingIntent pendingIntent;
    AlarmManager alarmManager;

    id = this.idSaved;
    intent =  new Intent(this,AlarmReceiver.class);
    intent.putExtra("id",id);
    pendingIntent = PendingIntent.getBroadcast(this,id,intent,PendingIntent.FLAG_CANCEL_CURRENT);

    //Note I used FLAG_CANCEL_CURRENT 

    alarmManager = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(pendingIntent);

    Log.w(TAG+" Torrancio","Canceled->"+id);


}

需要三个东西:

  • 相同类型的意图(在这种情况下,我们谈论的是一个AlarmManager)。
  • 相同的PendingIntent ID(保留id的引用,以某种方式保存)。
  • 正确的标志(FLAG_CANCEL_CURRENT用于取消操作,不需要也不能完全与创建pendingintent时使用的标志相同[因为我们使用取消标志来取消,但不是创建。]

欲了解更多详细信息,请查看this

希望对您有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接