如何创建不同的pendingintent 使filterEquals() 返回false?

Posted

技术标签:

【中文标题】如何创建不同的pendingintent 使filterEquals() 返回false?【英文标题】:How to create different pendingintent so filterEquals() return false? 【发布时间】:2011-11-21 17:38:03 【问题描述】:

我正在使用 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); 

删除:

问题是当我们需要删除其中一个时。删除待处理意图的正确方法是设置一个相同的意图,然后从 AlarmManager 调用取消。

android 文档:

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

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

所以在上面的例子中,如果我做了一个相同的意图然后取消,上述两个意图将被取消,因为它们来自相同的类/相同的动作等(除了“额外" data 是 rowId 但filterEquals 不关心额外数据)。

有什么解决方法吗?

【问题讨论】:

【参考方案1】:

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

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

这应该创建一个用于匹配目的的唯一 Intent..

【讨论】:

谢谢!很有可能它会起作用。不知道这么简单。 :) 我希望他们能更新文档,因为当你试图让某些东西正常工作时,将它说为“未使用”的 requestCode 真的很吓人。 小心:requestCode 被定义为 int 而通常 (sqlite) 行 ID 很长。 你确定可以使用requestCode吗?查看文档,他们谈论了能够区分它们的各种事物,但不是 requestCode:developer.android.com/reference/android/app/… -> ... -> developer.android.com/reference/android/app/… ->developer.android.com/reference/android/content/…【参考方案2】:

public boolean filterEquals(Intent other) 比较action、data、type、package、component、category,但是不比较extra,所以extra之间的区别无法区分Intent。尝试为这些 Intent 设置不同的数据,这些数据可能是微不足道的 Uris。

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

【讨论】:

【参考方案3】:

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

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

这将导致 filterEquals 返回 false。

我需要一个类似的解决方案来从多个号码发送短信通知, 为了允许通知以不同的数字启动短信线程查看器。

【讨论】:

【参考方案4】:

将任务 ID 和时间戳放入意图的操作中。这样,您将待处理的 Intent 与任务 ID 相关联,并且 Intent 在过滤方面仍然会有所不同。

intent.setAction("ACTION_" + taskId + "_" + currentTimestamp);

【讨论】:

【参考方案5】:

在我的情况下,我没有一个好的方法来为我的待处理意图生成唯一键,所以我所做的就是将自定义数据添加到生成的意图中。

一旦你开始填充 data 属性,你必须记住在 android manifest 中的 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>

通过这样做,您还可以在将 Intent 添加为待处理 Intent 之前测试其唯一性,这在您进行单元测试时非常有用。

【讨论】:

以上是关于如何创建不同的pendingintent 使filterEquals() 返回false?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 PendingIntent 用于两个不同的活动?

如何告诉 PendingIntent 是创建新广播还是更新现有广播

如何从 PendingIntent 中获取 Intent

FileCoin 挖矿教程之三:发送与接收 FIL

如何获取和取消 PendingIntent?

PendingIntent requestCode flags 参数