安卓如何比较待处理意图(Pending Intent)?

24

PendingIntent.FLAG_NO_CREATE 的文档说明如下:

如果所描述的 PendingIntent 不存在,则返回 null 而不是创建它。

我的问题是:用什么标准来比较 PendingIntent?

我猜这个标志在幕后使用PendingIntent.equals,但我不确定这个函数使用了哪些标准。它是否使用操作、请求代码、类别、额外信息(我猜不是)等?

上下文:

如果我的闹钟还没有设置,我想要使用待定意图启动闹钟。具体来说,我正在遵循这个答案

Intent i = new Intent(applicationContext, MyService.class);
i.setAction("myAction");
PendingIntent pi = PendingIntent.getService(applicationContext, /*requestCode*/0, i, PendingIntent.FLAG_NO_CREATE);
if (pi != null) {
  AlarmManager alarmMgr = (AlarmManager)applicationContext.getSystemService(Context.AlarmService);
  alarmMgr.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, AlarmManager.INTERVAL_HOUR, AlarmManager.INTERVAL_HOUR, pi);
}

4
好问题。 我知道这样做不正确。 但是,我曾经会在认为需要时取消之前的闹钟并重新启动它。 我期待着得到这个问题的答案。 - user3616287
我猜只有requestCode。你不能访问源代码来检查吗?Android Studio通常会显示它。 - Stan
2个回答

33

要确定 2 个 PendingIntent 是否匹配,需要确保以下内容相等:

  • PendingIntent 创建时使用的 requestCode 参数
  • Intent 的 ACTION
  • Intent 的 CATEGORIES
  • Intent 的 DATA
  • Intent 的 MIMETYPE
  • Intent 的 PACKAGE
  • Intent 的 COMPONENT

不考虑 Extras。

您可以在PendingIntent 概述文档Intent.filterEquals()中了解更多信息。


2

我猜测在底层,这个标志使用了PendingIntent.equals函数,但我不确定这个函数使用的是哪些标准。它是否使用了action、requestCode、categories、extras(我猜测没有),等等?

实际上,答案已经在类描述中了:

一个Intent的描述和目标操作。 使用getActivity(android.content.Context,int,android.content.Intent,int), getActivities(android.content.Context,int,android.content.Intent [],int), getBroadcast(android.content.Context,int,android.content.Intent,int), getService(android.content.Context,int,android.content.Intent,int)创建此类的实例; 返回的对象可以传递给其他应用程序,以便它们可以代表您在以后执行您描述的操作。 通过向另一个应用程序提供PendingIntent,您授予其执行您指定的操作的权利,就像另一个应用程序是您自己一样(具有相同的权限和身份)。因此,您应该注意如何构建PendingIntent: 例如,几乎始终,您提供的基本Intent应将组件名称明确设置为您自己的组件之一,以确保最终将其发送到那里而不是其他地方。 PendingIntent本身只是对系统维护的令牌的引用,描述用于检索它的原始数据。这意味着,即使拥有应用程序的进程被杀死,PendingIntent本身也将保持可用,从而可以从已经获得它的其他进程中使用它。如果创建应用程序稍后重新检索相同类型的PendingIntent(相同的操作,相同的Intent操作,数据,类别和组件以及相同的标志),则如果该令牌仍然有效,则将接收表示相同令牌的PendingIntent,因此可以调用cancel()将其删除。 由于这种行为,重要的是要知道何时认为两个意图是相同的,以便检索PendingIntent。人们经常犯的一个常见错误是使用在其“额外”内容方面只有所谓的Intents创建多个PendingIntent对象,期望每次都会得到不同的PendingIntent。这不会发生。用于匹配的Intent部分与Intent.filterEquals定义的相同。如果使用两个Intent对象,它们根据Intent.filterEquals是等效的,则对于它们两者都将获得相同的PendingIntent。 有两种典型的处理方法。 如果您真正需要同时激活多个不同的PendingIntent对象(例如用作同时显示的两个通知),则需要确保有某些与它们不同的内容来将它们与不同的PendingIntents关联起来。这可以是Intent.filterEquals考虑的任何Intent属性,或者提供给getActivity(android.content.Context,int,android.content.Intent,int), getActivities(android.content.Context,int,android.content.Intent [],int), getBroadcast(android.content.Context,int,android.content.Intent,int)或getService(android.content.Context,int,android.content.Intent,int)的不同请求代码整数之一。 如果您只需要任何Intents的一个PendingIntent处于活动状态,那么您还可以使用FLAG_CANCEL_CURRENT或FLAG_UPDATE_CURRENT标志来取消或修改与您提供的Intent关联的任何当前PendingIntent。

from: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.0.0_r1/android/app/PendingIntent.java#PendingIntent


我想知道这个函数是做什么的:“我猜测在底层,这个标志使用 PendingIntent.equals,但我不确定该函数使用了哪些标准。” - Steven Wexler
通常人们会查看源代码来理解这些东西,这就是为什么我向您展示它的原因。 - Stan
我通常很欣赏答案中的源代码!它通常很好地帮助解释/支持答案。但是我粘贴了一个链接到你粘贴的代码。我不理解那段代码,所以我正在寻找解释,而不仅仅是复制/粘贴我链接到的代码。 - Steven Wexler
抱歉,我没有注意到方法的链接。我希望在你的问题中看到它的主体。 - Stan
答案就藏在你引用的大约30行文本中。如果你格式化它,我会给你支票。 - Steven Wexler
显示剩余3条评论

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