如何创建不同的PendingIntent,以使filterEquals()方法返回false?

23
我正在使用AlarmManager来设置重复意图,但是它引起了一些小问题,希望有人能帮忙。 概要 有2个待处理的意图。一个在每天的1000运行,另一个在每天的2000运行。每个都包含一个用于识别目的的数据库行ID。代码看起来像这样:
Intent i = new Intent(mContext, ScheduleReceiver.class);
i.putExtra(RuleDBAdapter.KEY_ROWID, (int)taskId);
PendingIntent pi =PendingIntent.getBroadcast(...);
mAlarmManager.set(AlarmManager.RTC_WAKEUP, when.getTimeInMillis(), pi); 

删除:

问题在于我们需要删除其中一个。正确的删除pending intent的方法是设置一个相同的pending intent,然后从AlarmManager调用cancel。

Android文档:

public void cancel(PendingIntent operation)
删除与匹配意图的任何警报。任何类型的警报,如果其意图与此匹配(由filterEquals(Intent)定义),都将被取消。

public boolean filterEquals(Intent other)
确定两个意图在意图解析(过滤)的目的上是否相同。也就是说,如果它们的操作、数据、类型、类和类别相同,则它们相同。这不比较包含在意图中的任何额外数据。

因此,在上面的示例中,如果我创建一个相同的意图,然后取消,上述两个意图都将被取消,因为它们来自相同的类/相同的操作等(除了“extra”数据是rowId,但filterEquals不关心额外数据)。

有没有任何解决办法?

5个回答

23

您可以尝试在创建待定意图时使用requestCode参数:

PendingIntent pi =PendingIntent.getBroadcast(mContext, yourUniqueDatabaseId,i,PendingIntent.FLAG_ONE_SHOT);

这应该创建一个Intent,用于匹配目的的唯一性。


谢谢!可能会起作用。没想到这么简单。 :) - markbse
我希望他们更新文档,因为当你试图让某些东西工作时,将requestCode标记为“未使用”真的很令人生畏。 - Travis Castillo
注意:requestCode 被定义为 int,而通常 (sqlite) 的行 ID 是 long。 - HaimS
你确定可以使用requestCode吗?从文档上看,它们谈论了各种能够区分它们的事情,但却没有提及requestCode:https://developer.android.com/reference/android/app/AlarmManager#setAlarmClock(android.app.AlarmManager.AlarmClockInfo,%20android.app.PendingIntent) -> ... -> https://developer.android.com/reference/android/app/AlarmManager#set(int,%20long,%20android.app.PendingIntent) -> https://developer.android.com/reference/android/content/Intent#filterEquals(android.content.Intent) - android developer

4

public boolean filterEquals(Intent other) 比较Intent的action, data, type, package, component和categories属性,但不比较extra属性。因此,extra属性的差别无法区分Intents。可以尝试为这些Intents设置不同的数据,数据可以是无关紧要的Uri。

尝试阅读源代码以获取更多信息。


1
尝试在意图中放置一个虚拟操作。 例如:

myIntent.setAction(""+System.currentTimeMillis());

这将导致filterEquals返回false。
我需要一个类似的解决方案来从多个号码发送短信通知,以便允许通知使用不同的号码启动短信线程查看器。

0
在我的情况下,我没有一个好的方法来生成一个唯一的键用于我的待处理意图,所以我做的是向生成的意图添加自定义数据。
一旦你开始填充数据属性,你必须记得在Android清单文件中的intent-filter中添加一个data参数。如果你不这样做,它将无法触发你的自定义接收器。
示例:
意图
    Intent intent = new Intent(reminderFire);
intent.addCategory(reminderCategory);
Uri.Builder builder = new Uri.Builder();
builder.scheme(context.getString(R.string.scheme));
builder.authority(context.getString(R.string.intent_filter_reminder_host));
builder.appendQueryParameter("oid", Reminder.getOid());
intent.setData(builder.build());

AndroidManifest条目

<receiver 
    android:name=".client.MyReminder"
    android:enabled="true"
>
    <intent-filter>
        <action android:name="com.example.client.reminder.fire"/>
        <action android:name="com.example.client.reminder.category"/>
        <data
            android:host="@string/intent_filter_reminder_host"
            android:scheme="@string/scheme" />
    </intent-filter>
</receiver>

通过这样做,您还可以在将其添加为挂起意图之前测试意图的唯一性,这在进行单元测试时非常有用。

0
将任务 ID 和时间戳放入意图的操作中。这样,您就可以将挂起的意图与任务 ID 关联起来,并且在过滤方面意图仍然是不同的。
intent.setAction("ACTION_" + taskId + "_" + currentTimestamp);

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