当活动调用finish()时,通知pendingIntent contentIntent失败

时间:2012-09-20 08:50:27

标签: java android

我有一个前台服务通知,点击后应该开始一项活动。这个活动在调用finish()之前很短暂。

第一次点击通知时,第二次发生错误:

    Sending contentIntent failed: android.app.PendingIntent$CanceledException

在我的代码中创建前台服务通知时,我已将randomActivity.class更改为另一个不调用finish的Activity类,它在每次单击时都能正常工作。从:

    Intent notificationIntent = new Intent(this, RandomActivity.class);

为:

    Intent notificationIntent = new Intent(this, HomeActivity.class);

工作得很好......

我使用了Android开发者网站上的标准通知代码,并使用“通知”构建器对其进行了测试。无论如何我得到相同的结果。除非Activity调用finish();

,否则它完美地工作

这是预期的行为,是一个错误,还是我错过了什么?

我提前感谢您的帮助,希望能找到解决方案!

注意:我使用的通知代码是完全标准的,所以我没有发布它。 RandomActivity调用finish();在onCreate,所以也没有什么不寻常的。

4 个答案:

答案 0 :(得分:12)

在尽我所能尝试之后,我终于找到了解决方案。如果有人遇到这个问题,也会发布。

我必须将int requestCode与通知ID匹配。为什么?绝对不知道......我只能假设它会阻止意图数据变为空或重用它?

    private static int ONGOING_NOTIFICATION_ID = 76;

    PendingIntent contentIntent = PendingIntent.getActivity(this,
    ONGOING_NOTIFICATION_ID, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

与startForeground的通知ID相同:

    this.startForeground(ONGOING_NOTIFICATION_ID, not);

希望这有助于某人。

答案 1 :(得分:4)

我不需要检查通知ID(与您的建议一样),但我必须将标记更改为FLAG_UPDATE_CURRENT,而不是FLAG_ONE_SHOT

使用FLAG_ONE_SHOT,待处理的意图一旦传递就会被取消,之后,没有任何数量的通知将允许再次传递相同的待处理意图,因此例外。

这对我来说是个问题。

答案 2 :(得分:0)

我刚刚遇到了类似的问题,它不是前台通知,但是有时单击通知会导致Sending contentIntent failed: android.app.PendingIntent$CanceledException错误,但没有任何反应。所以我只想描述我的问题和解决方案,因为我在这里寻找它。

对我来说,问题是我在服务器上有一个剩余的安装对象,因此实际上我得到了两次FCM onMessageReceived事件,并两次发布了本地通知。因为它与同一事件相关,所以它被实现为替换自身,因此我没有注意到。

但是我正在使用当前时间生成具有10ms精度的唯一requestCode,因此,如果第二个调用在第一次调用后的10ms内发布了本地通知,则它将获得相同的请求代码。

我还使用了标志FLAG_CANCEL_CURRENT,但是它应该只取消先前的挂起意图并创建一个新的意图。

所以,然后我尝试将requestCode设为常量-仍然,有时意图很好。

我认为罪魁祸首是这两个调用并发运行,有时,取消了其未完成的通知的通知实际上是在以后发布,代替了具有正在执行的未完成的通知。

我的解决方案: 我确保onMessageReceived中的代码等待上一个调用完成。它停止发生,一切正常。我还在onMessageReceived方法内部添加了一些过滤功能,以忽略传入的推送,这些推送具有完全相同的数据,并且间隔不到5秒就被接收到。

答案 3 :(得分:0)

我的问题源于多个PendingIntent相等;在这种情况下,取消一个PendingIntent会取消所有“重复项”。

Per the Android documentation

  

重要的是要知道何时两个Intent被认为是相同的,以便检索PendingIntent。人们经常犯的一个错误是创建多个PendingIntent对象,它们的Intent仅在其“额外”内容中有所不同,期望每次都获得一个不同的PendingIntent。这不会发生。用于匹配的Intent部分与Intent#filterEquals(Intent)定义的部分相同。如果您使用与Intent#filterEquals(Intent)等效的两个Intent对象,则它们将获得相同的PendingIntent。

关于如何处理此问题的两个建议:

  

如果您确实确实需要同时激活多个不同的PendingIntent对象(例如,用作同时显示的两个通知),那么您将需要确保存在一些不同的内容< / strong>,将其与其他PendingIntent相关联。 这可能是Intent#filterEquals(Intent)考虑的任何Intent属性,或提供给getActivity(Context,int,Intent,int),getActivities(Context,int,Intent [ ],int),getBroadcast(Context,int,Intent,int)或getService(Context,int,Intent,int)。

     

如果一次只需要一个PendingIntent来激活要使用的任何Intent,则可以选择使用标志FLAG_CANCEL_CURRENT或FLAG_UPDATE_CURRENT来取消或修改与您提供的Intent相关的任何当前PendingIntent。 / p>

Two intents are equal when

  

它们的动作,数据,类型,标识,类和类别相同。这不会比较意图中包含的任何其他数据。请注意,从技术上讲,当实际与IntentFilter进行匹配时,标识符将被忽略,而在这里它会像其他字段一样直接进行相等性比较。