是否可以使用相同的 requestCode 和不同的 extra 创建多个 PendingIntent?
Posted
技术标签:
【中文标题】是否可以使用相同的 requestCode 和不同的 extra 创建多个 PendingIntent?【英文标题】:Is it possible to create multiple PendingIntents with the same requestCode and different extras? 【发布时间】:2013-12-10 20:10:56 【问题描述】:我正在使用 AlarmManager
来安排 1 到 35 个警报之间的任意位置(取决于用户输入)。当用户请求安排新警报时,我需要取消当前警报,因此我使用相同的 requestCode 创建所有警报,在 final
变量中定义。
// clear remaining alarms
Intent intentstop = new Intent(this, NDService.class);
PendingIntent senderstop = PendingIntent.getService(this,
NODIR_REQUESTCODE, intentstop, 0);
am.cancel(senderstop);
// loop through days
if (sched_slider.getBooleanValue())
for (int day = 1; day < 8; day++)
if (day == 1 && sun.isChecked())
scheduleDay(day);
if (day == 2 && mon.isChecked())
scheduleDay(day);
if (day == 3 && tue.isChecked())
scheduleDay(day);
if (day == 4 && wed.isChecked())
scheduleDay(day);
if (day == 5 && thu.isChecked())
scheduleDay(day);
if (day == 6 && fri.isChecked())
scheduleDay(day);
if (day == 7 && sat.isChecked())
scheduleDay(day);
...
public void scheduleDay(int dayofweek)
Intent toolintent = new Intent(this, NDService.class);
toolintent.putExtra("TOOL", "this value changes occasionally");
PendingIntent pi = PendingIntent.getService(this,
NODIR_REQUESTCODE, toolintent, 0);
calendar.set(Calendar.DAY_OF_WEEK, dayofweek);
calendar.set(Calendar.HOUR_OF_DAY, hour);
calendar.set(Calendar.MINUTE, minute);
calendar.set(Calendar.SECOND, 0);
am.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY * 7, pi);
在这里,如果用户选中了sun
(这是一个复选框),它将安排在每个星期日在hour
和minute
运行警报。您可以看到以这种方式创建的每个警报都有相同的 requestCode,但 TOOL
的额外更改有时会针对每个警报。
但是,在我的测试中,当警报响起并且我的服务运行时,Intent 中的额外内容现在是 null
。 This question 建议使用 PendingIntent.FLAG_CANCEL_CURRENT
可以解决这个问题,但那不会取消其他 PendingIntents 吗?
简而言之:
有人能解释一下 PendingIntents 是如何工作的吗?关于创建多个具有相同 requestCode 和不同附加项的内容?我应该使用哪些标志(如果有)?
【问题讨论】:
【参考方案1】:实际上,您并没有“创建”PendingIntent
s。您从 android 框架中请求它们。当您从 Android 框架请求 PendingIntent
时,它会检查是否已经存在与您作为参数传递的条件匹配的 PendingIntent
。如果是这样,它不会创建一个新的PendingIntent
,它只是给你一个指向现有PendingIntent
的“令牌”。如果它没有找到匹配的PendingIntent
,它将创建一个,然后返回一个指向它刚刚创建的那个的“令牌”。您可以设置一些标志来修改此行为,但不是那么多。这里最重要的是要了解 Android 框架进行匹配的方式。
为此,它会检查以下参数是否匹配(将现有的PendingIntent
与您传递的参数进行比较):
Intent
中的“动作”必须相同(或均为空)。否则它们不匹配。
Intent
中的“数据”必须相同(或均为空)。否则它们不匹配。
Intent
中的(数据的)“类型”必须相同(或两者均为空)。否则它们不匹配。
Intent
中的“包”和/或“组件”必须相同(或均为空)。否则它们不匹配。 “包”和“组件”字段设置为“显式”Intent
s。
Intent
中的“类别”列表必须相同。否则它们不匹配。
您应该注意到“附加”不在上面的列表中。这意味着,如果您请求 PendingIntent
,则当 Android 框架尝试查找匹配的 PendingIntent
时,不会考虑“附加”。这是开发人员常犯的错误。
我们现在可以解决您可以添加以修改 PendingIntent
请求的行为的其他标志:
FLAG_CANCEL_CURRENT
- 指定此标志时,如果找到匹配的PendingIntent
,则取消(删除、删除、无效)PendingIntent
并创建一个新标志。这意味着任何持有指向旧 PendingIntent
的“令牌”的应用程序都将无法使用它,因为它不再有效。
FLAG_NO_CREATE
- 指定此标志时,如果找到匹配的PendingIntent
,则返回指向现有PendingIntent
的“令牌”(这是通常的行为)。但是,如果没有找到匹配的PendingIntent
,则不会创建一个新的,并且调用只会返回null
。这可用于确定是否有针对特定参数集的活动PendingIntent
。
FLAG_ONE_SHOT
- 当您指定此标志时,创建的PendingIntent
只能使用一次。这意味着,如果您将此 PendingIntent
的“令牌”提供给多个应用程序,则在首次使用 PendingIntent
后,它将被取消(删除、删除、无效),因此以后任何尝试使用它都会失败。
FLAG_UPDATE_CURRENT
- 指定此标志时,如果找到匹配的 PendingIntent
,则 PendingIntent
中的“附加”将替换为您作为参数传递的 Intent
中的“附加”到getxxx()
方法。如果找不到匹配的PendingIntent
,则会创建一个新的(这是正常行为)。这可用于更改现有PendingIntent
上的“额外”,您已经将“令牌”提供给其他应用程序并且不想使现有PendingIntent
无效。
让我尝试解决您的具体问题:
如果请求代码、操作、数据、类型和包/组件参数相同,则系统中不能有多个活动PendingIntent
。因此,您无法要求能够拥有多达 35 个活动的PendingIntent
s,它们都具有相同的请求代码、操作、数据、类型和包/组件参数,但具有不同的“附加”。
我建议您使用 35 个不同的请求代码,或者为您的 Intent
创建 35 个不同的唯一“操作”参数。
【讨论】:
感谢您的帮助!我的意图没有数据或操作,所以你是说我可能会随机化其中一个字段?如果我这样做,我真的不需要担心标志吗? 哦,我刚刚也想到了一些东西。如果我随机化,比如说,Action,那么我的代码的“清除警报”部分将不起作用。我必须记录随机操作并将 Intents 操作设置为循环以清除所有警报,对吗? 是的,你会的。这正是您需要做的。 谢谢。 Android 文档在这方面不是很好……这是唯一对我有意义的解释。 非常感谢您提供如此详细的回答【参考方案2】:是的,可以为每个警报设置独特的意图操作
intent.setAction("uniqueCode");
Intent intent = new Intent(context, MyAlarmReciver.class);
intent.setAction("uniqueCode");
PendingIntent pendingIntent = PendingIntent.getBroadcast(activity, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(activity.ALARM_SERVICE);
Calendar c = Calendar.getInstance();
c.add(Calendar.MINUTE, 1);
alarmManager.set(AlarmManager.RTC_WAKEUP, c.getTimeInMillis(), pendingIntent);
【讨论】:
以上是关于是否可以使用相同的 requestCode 和不同的 extra 创建多个 PendingIntent?的主要内容,如果未能解决你的问题,请参考以下文章
java 获取全局唯一的整形常量,可以用于requestCode的定义,防止其在不同文件中定义时值的碰撞。
Android:requestCode 和 resultCode
如何在android报警时从待处理的意图中获取requestCode
使用registerForActivityResult替代onActivityResult
android,,onActivityResult的作用是啥啊,requestCode, resultCode是啥意思啊?