是否可以使用相同的requestCode和不同的附加项创建多个PendingIntents?

时间:2013-11-25 22:00:59

标签: android alarmmanager android-pendingintent

我正在使用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),它会安排在每个星期天hourminute运行警报。您可以看到以这种方式创建的每个警报具有相同的requestCode,但有时每个警报都会TOOL额外更改。

但是,在我的测试中,当闹钟响起且我的服务运行时,Intent的额外内容现在为nullThis question建议使用PendingIntent.FLAG_CANCEL_CURRENT来解决此问题,但不会取消其他PendingIntents吗?

简而言之:

有人可以解释PendingIntents是如何工作的,参考创建具有相同requestCode和不同额外内容的多个?我应该使用什么标志(如果有的话)?

2 个答案:

答案 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);