在PendingIntent上使用的“ requestCode”是什么?


110

背景:

我通过AlarmManager使用PendingIntent发出警报。

问题:

起初,我认为为了取消以前的警报,必须提供在启动警报之前使用的确切requestCode。

但是后来我发现我错了,正如取消API所述

删除所有具有匹配意图的警报。任何警报,其意图与该警报相匹配(由filterEquals(Intent)定义)的任何类型的警报都将被取消。

查看“ filterEquals ”,文档说:

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

所以我不明白“ requestCode”是为了什么...

问题:

“ requestCode”是用来做什么的?

如果使用相同的“ requestCode”创建多个警报该怎么办?他们会互相覆盖吗?


如果您使用相同的requestCode,则将获得相同的PendingIntent
pskink 2014年

3
对于PendingIntent.getBroadcast(),Android显然会忽略requestCode。从API 22开始,它不会使您的待定意向变得唯一。为getActivity()(也许还有getService())做,但是我还没有测试。stackoverflow.com/a/33203752/2301224
贝克

@Baker这不是虫子吗?如果是错误,则应在此处进行说明:code.google.com/p/android/issues/list
android开发人员

1
好吧,实际上,文档确实指定了requestiCode的用法:If you truly need multiple distinct PendingIntent objects active at the same time (such as to use as two notifications that are both shown at the same time), then you will need to ensure there is something that is different about them to associate them with different PendingIntents. This may be any of the Intent attributes considered by Intent#filterEquals(Intent), or different request code integers supplied.
Eir

@Eir对,那么使用requestCode有什么意义呢?在哪里可以使用?
android开发人员

Answers:


77
  1. requestCode 用于稍后检索相同的挂起的Intent实例(用于取消等)。
  2. 是的,我的猜测是警报会相互覆盖。我将使请求代码保持唯一。

5
即使在警报的意图非常不同的情况下(例如,针对服务A的一个和针对服务B的一个),将requestCode设置为唯一需要的代码吗?此外,文档为什么没有对此作任何说明?是否可以删除某种类型的所有警报,无论requestCode是什么?
android开发人员

1
不,没有必要使用不同的意图。而且我不知道为什么文档中什么也没说,但是我在设置重复警报以及使用相同意图时学到了这一点。
2014年

2
我在谈论PendingIntent。startActivityForResult使用常规意图。
android开发人员

2
“使用代理活动在PendingIntent中使用startActivityForResult”的目的是什么?能给我举个例子吗?
android开发人员

3
我同意; PendingIntent和AlarmManager的文档太少了-由于无法以编程方式列出警报,因此情况变得更糟。
某处某人2015年

32

我只想添加到@Minhaj Arfin答案

1- requestCode用于稍后获得相同的待处理意图(用于取消等)

2-是的,只要您在PendingIntent上为Intent指定了相同的接收方,它们就会被覆盖

例:

Intent startIntent1 = new Intent(context, AlarmReceiverFirst.class);
PendingIntent pendingIntent1 = PendingIntent.getBroadcast(context, 0, startIntent1, 0);

Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, 0);

从上面的例子中,他们 由于接收方不同(AlarmReceiverFirst和AlarmReceiverSecond)将不会相互覆盖。

Intent startIntent2 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent2 = PendingIntent.getBroadcast(context, 0, startIntent2, 0);

Intent startIntent3 = new Intent(context, AlarmReceiverSecond.class);
PendingIntent pendingIntent3 = PendingIntent.getBroadcast(context, 0, startIntent3, 0);

在上面的示例中,它们相互覆盖,因为接收者是相同的(AlarmReceiverSecond)


Intent startIntent4 =新的Intent(上下文,AlarmReceiverSecond.class); PendingIntentendingIntent4 = PendingIntent.getService(context,0,startIntent4,0); 那会好吗?我的意思是,不会覆盖它,因为它调用的是getService()而不是getBroadcast()吗?
Jenix

很抱歉提出另一个问题,但是因为stackoverflow不允许我在没有任何代码行的情况下编写问题。.PendingIntent的方法(如getBroadcast())的最后一个参数是否与重写有关?我习惯把0那里就像你上面的例子代码,但我也看到很多人把一些具体的期权价值而不是0
Jenix

1
@Jenix uou AlarmReceiverSecond.class在意图上使用,然后使用PendingIntent.getService()。这是行不通的,因为AlarmReceiverSecond.class是一个BroadcastReceiver,不是Service
HendraWD

1
关于标志,可以设置的属性将根据您提供的标志来使PendingIntent起作用。0表示关闭所有标志
HendraWD

啊,我很愚蠢,哈哈我到底在想什么。.我对PendingIntent有点困惑,您的回答确实很有帮助。我只是想更清楚一点,但现在意识到我的问题起初没有任何意义。谢谢!
Jenix

2

在我的情况下,我想使用两个不同的意图打开同一活动,因此,如果托盘中有两个或多个FCMS,则其中任何一个只会打开另一个而不会,所以我更改了待定意图的请求代码,然后它起作用了。

 PendingIntent pendingIntent =
                            PendingIntent.getActivity(this, **Some unique id for all GCMS** /* Request code */, intent,
                                    PendingIntent.FLAG_ONE_SHOT);

无需针对我的情况进一步检查代码,您能告诉我在哪种情况下需要挂起的intent实例。关于问题更改请求代码帮助我转到了正确的屏幕,我不知道这是否是正确的方法,并且对我来说,仅当托盘中有多个FCM时才会发生错误
JSONParser

那么,如果不需要,为什么还要设置一个不同的请求代码呢?
Android开发人员

好的,我将详细解释,我有一些活动A,这是为了表明问题,我将通过意图将通知中的ID传递给意图,然后向该ID发出网络请求并获取特定的问题,那么在那里发生了什么事通知栏中有多个通知,然后单击其中任何一个,将待处理的意图请求代码更改为可以正常工作的唯一值后,我得到了第一个GCM中的问题ID。我希望我现在已经说清楚了,如果需要更多讨论,我也想了解更多,谢谢
JSONParser

哦,你的意思是否则它根本不会起作用,对吧?对不起,我很困惑。这个问题是很久以前问过的,我一点也不记得了……
android开发人员

1

一件重要的事情requestCode是使用小部件会严重困扰您的应用程序。如果小部件requestCode相同,则小部件在电话重启后将无法工作。这意味着pendingIndent您在remoteViews窗口小部件上设置的,必须设置唯一的requestCode,通常是带数字的widgetId。


0

实际上,文档清楚地说明了请求代码的用途:

如果确实需要同时激活多个不同的PendingIntent对象(例如,用作同时显示的两个通知),则需要确保它们之间存在一些不同之处,以便将它们与不同的对象关联待定意图。这可以是Intent#filterEquals(Intent)考虑的任何Intent属性,或提供给getActivity(Context,int,Intent,int),getActivities(Context,int,Intent [],int),getBroadcast(上下文,整数,意图,整数或getService(上下文,整数,意图,整数)。

由于似乎还不清楚,所以让我尝试解释一下:

当您要使用一个PendingIntent对象时,您不仅要实例化一个。相反,你获得一个使用该系统的PendingIntent静态方法(getActivitygetBroadcastgetService等)。系统保留了一堆PendingIntent实例并给您一个。它为您提供哪一个,取决于您传递给这些getter方法的输入参数。这些输入参数是:Context,即意图的目标接收者,Intent使用的对象requestCodeflags。当您传递相同Context,相同requestCode和相同的Intent(意味着一个意图filterEquals与另一个Intent)时,您将获得相同的PendingIntent对象。关键是系统要少PendingIntent对象,因此它倾向于尽可能多地重用现有对象。

例如,您有两个不同日期的日历通知。当您单击其中之一时,您希望您的应用打开到该通知的相应日期。在这种情况下,您具有相同的Context目标,并且Intent所传递的对象仅在EXTRA_DATA(用于指定应打开的日期)方面有所不同。如果requestCode在获取PendingIntent对象时提供相同的对象,那么最终将获得相同的PendingIntent对象。因此,在创建第二个通知时,您将用Intent新的EXTRA_DATA 替换旧对象,最后得到两个指向相同日期的通知。

如果要具有两个不同的PendingIntent对象(在这种情况下应如此),则requestCode在获取PendingIntent对象时应指定一个不同的对象。


但是如上所述,要取消警报,您不能仅使用requestCode。这并不意味着什么。您将必须放入额外的数据以区分它们。我不记得了,但我想您甚至可以将相同的requestCode用于多个警报。
android开发人员

@androiddeveloper您刚才说的不正确。试试吧。
Eir
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.