当前位置: 首页 > 知识库问答 >
问题:

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

阎乐池
2023-03-14

我正在使用alarmmanager调度1到35个警报(取决于用户输入)。当用户请求调度新的警报时,我需要取消当前的警报,因此我使用相同的requestCode创建所有警报,该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(这是一个复选框),它将安排一个闹钟在每周日的hourminute运行。您可以看到,以这种方式创建的每个警报都有相同的requestCode,但工具有时会对每个警报进行额外更改。

但是,在我的测试中,当警报响起并且我的服务运行时,来自意图的额外内容现在是null。这个问题表明使用pendingintent.flag_cancel_current可以解决这个问题,但这不会取消其他的pendingintents吗?

有没有人可以解释一下,在创建多个具有相同请求代码和不同附加代码的PendingIntents时,它是如何工作的?我应该使用什么标志(如果有的话)?

共有1个答案

呼延烈
2023-03-14

实际上,您并不“创建”pendingintents。您可以从Android框架中请求它们。当您从Android框架中请求pendingintent时,它会检查是否已经存在与您作为参数传递的条件匹配的pendingintent。如果是,它不会创建新的PendingIntent,它只是返回一个指向现有PendingIntent的“令牌”。如果它没有找到匹配的pendingintent,它将创建一个,然后返回一个指向它刚刚创建的“令牌”。您可以设置一些标志来修改这种行为,但不是那么多。这里最需要理解的是Android框架做匹配的方式。

为此,它检查以下参数是否匹配(将现有的pendingintent与您传递的参数进行比较):

  • 请求代码必须相同。否则它们不匹配。
  • intent中的“action”必须相同(或两者均为空)。否则它们不匹配。
  • intent中的“数据”必须相同(或两者均为空)。否则它们不匹配。
  • intent中的(数据的)“类型”必须相同(或两者均为空)。否则它们不匹配。
  • intent中的“包”和/或“组件”必须相同(或两者均为空)。否则它们不匹配。“Package”和“Component”字段设置为“Explicit”intent
  • intent中的“类别”列表必须相同。否则它们不匹配。

您应该注意到“extras”不在上面的列表中。这意味着,如果您请求pendingintent,那么当Android框架试图找到匹配的pendingintent时,“额外”不会被考虑在内。这是开发人员经常犯的错误。

我们现在可以处理附加标志,您可以添加这些标志来修改pendingintent请求的行为:

flag_cancel_current-指定此标志时,如果找到匹配的pendingintent,则取消(删除、删除、无效)该pendingintent并创建一个新标志。这意味着任何持有指向旧pendingintent的“令牌”的应用程序都不能使用它,因为它不再有效。

flag_one_shot-指定此标志时,创建的pendingintent只能使用一次。这意味着,如果您将此PendingIntent的“令牌”提供给多个应用程序,则在首次使用PendingIntent之后,它将被取消(删除、删除、无效),以便以后使用它的任何尝试都将失败。

flag_update_current-指定此标志时,如果找到匹配的pendingintent,则pendingintent中的“extras”将被作为参数传递给getxxx()方法的intent中的“extras”替换。如果没有找到匹配的pendingintent,则创建一个新的(这是正常行为)。这可用于更改现有PendingIntent上的“附加”,您已经将“令牌”赋予其他应用程序,并且不想使现有PendingIntent无效。

让我试着解决你的具体问题:

如果请求代码、操作、数据、类型和包/组件参数相同,则系统中不能有多个活动的pendingintent。因此,您要求能够有多达35个活动的pendingintentS都具有相同的请求代码、操作、数据、类型和包/组件参数,但具有不同的“附加”,这是不可能的。

我建议您或者使用35个不同的请求代码,或者为intent创建35个不同的唯一“动作”参数。

 类似资料:
  • 但是我有两种回购方式 如何创建两个bean,其中一个是用注入的,另一个是用注入的?

  • 我在项目中使用drools 6.3.0。我有大约3000条规则,分为两类。比如,类别1有1500条规则,类别2有1500条规则。有2万份订单具有不同的数据。每个订单都有一组不同的属性。现在,为每个请求创建kiesession需要时间,而且速度非常慢。因此,计划使用相同的kiesession执行所有订单,订单将使用多线程处理。 以下是我目前的做法。 这就是我创建kiesession的方式,我想将此k

  • 我需要从客户端进程向多个snmp代理发送获取请求。 我已经基于以下URL实现了客户端/代理http://www.jitendrazaa.com/blog/java/snmp/create-snmp-client-in-java-using-snmp4j/http://www.jitendrazaa.com/blog/java/snmp/creating-snmp-agent-server-in-j

  • 问题内容: 和 第二个代码产生了一个空指针异常,该怎么做才能使下一个等效? 问题答案: 我可以看到,如果players某个自定义java.lang.Iterable的get()实现的实现被破坏,或者至少以一种异常的方式(与的行为不同),就会发生这种情况。 除此之外,我唯一能想到的就是您未在代码中向我们展示的某些内容导致了某些错误。 如果执行此操作会怎样?

  • 我已经创建了一个按钮数组(),我想为数组中的所有按钮添加相同的操作侦听器,而不是逐个添加它们。 想象一下,每次我点击屏幕上显示的一个按钮,它就会在数组中打印出该按钮的索引。