我正在使用AlarmManager
来安排1到35个警报之间的任何位置(取决于用户输入)。当用户请求安排新警报时,我需要取消当前警报,因此我使用final
变量中定义的相同requestCode创建所有警报。
// 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
(这是一个CheckBox),它会安排在每个星期天hour
和minute
运行警报。您可以看到以这种方式创建的每个警报具有相同的requestCode,但有时每个警报都会TOOL
额外更改。
但是,在我的测试中,当闹钟响起且我的服务运行时,Intent的额外内容现在为null
。 This question建议使用PendingIntent.FLAG_CANCEL_CURRENT
来解决此问题,但不会取消其他PendingIntents吗?
有人可以解释PendingIntents是如何工作的,参考创建具有相同requestCode和不同额外内容的多个?我应该使用什么标志(如果有的话)?
答案 0 :(得分:63)
实际上,你并没有“创造”PendingIntent
。您从Android框架请求它们。当您从Android框架请求PendingIntent
时,它会检查是否已存在与您作为参数传递的条件匹配的PendingIntent
。如果是这样,它不会创建新的PendingIntent
,它只会返回一个指向现有PendingIntent
的“标记”。如果找不到匹配的PendingIntent
,它将创建一个,然后返回一个“标记”,指向它刚创建的标记。您可以设置一些标志来修改此行为,但不是那么多。这里要了解的最重要的事情是Android框架进行匹配的方式。
为此,它会检查以下参数是否匹配(将现有PendingIntent
与您传递的参数进行比较):
Intent
中的“操作”必须相同(或两者都为null)。否则他们不匹配。Intent
中的“数据”必须相同(或均为空)。否则他们不匹配。Intent
中的“type”(数据)必须相同(或两者都为null)。否则他们不匹配。Intent
中的“包”和/或“组件”必须相同(或均为空)。否则他们不匹配。 “package”和“component”字段设置为“explicit”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
中的“extras”将被{{1中的“extras”替换您作为参数传递给getxxx()
方法。如果未找到匹配的PendingIntent
,则会创建一个新的(这是正常行为)。这可用于更改现有PendingIntent
上的“额外内容”,其中您已将“令牌”提供给其他应用程序,并且不希望使现有PendingIntent
无效。
让我试着解决您的具体问题:
如果请求代码,操作,数据,类型和包/组件参数相同,则系统中不能有多个活动PendingIntent
。因此,您无法使用相同的请求代码,操作,数据,类型和包/组件参数,但具有不同的“额外”参数,最多可以拥有35个活动PendingIntent
的所有内容。
我建议您使用35个不同的请求代码,或为Intent
创建35个不同的唯一“操作”参数。
答案 1 :(得分:3)
是的,可以为每个警报添加唯一意图操作
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);