11

我有一个前台服务通知,单击该通知应启动一项活动。此活动在调用完成()之前非常短暂。

第一次点击通知它工作,第二次,此后我得到错误:

    Sending contentIntent failed: android.app.PendingIntent$CanceledException

在创建前台服务通知时的代码中,我已将 randomActivity.class 更改为另一个不调用完成的 Activity 类,并且每次点击都能完美运行。从:

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

至:

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

工作正常...

我使用了来自 Android Developers 网站的标准通知代码,并使用 Notification builder 对其进行了测试。无论如何,我都会得到相同的结果。除非 Activity 调用 finish(); 否则它工作得很好。

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

我提前感谢您的帮助,并希望有一个解决方案!

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

4

4 回答 4

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

希望这可以帮助某人。

于 2012-09-21T10:20:01.817 回答
7

我不需要检查通知 ID(就像你建议的那样),但我确实必须将标志更改为FLAG_UPDATE_CURRENT,而不是FLAG_ONE_SHOT.

使用FLAG_ONE_SHOT时,待处理的 Intent 会在交付后被取消,之后,无论点击多少通知都不会允许再次交付相同的待处理 Intent,因此出现异常。

这对我来说是个问题。

于 2015-01-23T04:15:54.920 回答
1

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

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

但是我使用当前时间来生成一个唯一的 requestCode,精度为 10ms,所以如果第二次调用在第一次调用后 10ms 内发布本地通知,它会得到相同的请求代码。

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

因此,然后我尝试将 requestCode 设为常量 - 尽管如此,有时意图仍然可以正常工作。

我认为罪魁祸首是这两个调用并行运行,有时,取消其pendingIntent 的通知实际上是稍后发布的,替换了具有工作pendingIntent 的通知。

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

于 2018-09-29T16:43:38.867 回答
0

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

根据 Android 文档

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

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

如果您确实需要同时激活多个不同的 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。

两个意图在 时相等

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

于 2019-12-10T22:26:04.747 回答