如何在Android 8中为FCM推送消息指定Android通知渠道

32
我们的应用现在使用的是targetSdkVersion 26(Android 8),并且应用程序使用FCM推送通知。
按照FCM文档的规定,我将FCM客户端库更新到了11.2.0版本。
dependencies {
     compile 'com.google.firebase:firebase-messaging:11.2.0'
}

通过此FCM客户端库更新,FCM通知开始出现在Android设备上。不过,当应用程序在后台时,它的系统处理FCM消息,因此它使用名为“Miscellaneous”的默认Android通知通道,这不是我们想要的(我们有其他通知通道,“Miscellaneous”在该列表中很令人困惑)。
正如FCM文档所说,有一种方法可以指定FCM消息的默认通知通道:

(可选)在应用程序组件内,元数据元素设置通知的默认图标、颜色和通知通道(在Android O中新增)。每当传入消息没有显式设置图标、颜色或通知通道时,Android就会使用这些值。

然而,没有显示代码示例(仅显示图标和颜色的示例)。所以我通过在Firebase Cloud Messaging Quickstart上github搜索找到了一个示例:
<meta-data
    android:name="com.google.firebase.messaging.default_notification_channel"
    android:value="@string/default_notification_channel_id"/>

但是它没有起作用 - FCM通知仍然出现在"杂项"频道中。我在日志中看到:
W/FirebaseMessaging:AndroidManifest中缺少默认通知频道元数据。将使用默认值。
当然,我尝试重新安装应用程序。仍然存在问题。
理想情况下,在发送消息时,后端应该有一些指定通知频道的方法。FCM开发控制台允许测试发送,现在在用户界面上有这样一个选项:

enter image description here

这个应用程序运行良好。然而,我们的后端使用Java Amazon SNS API,我不知道该API是否允许在发送消息时指定Android通知渠道(因为这是一个新的Android功能,Amazon需要时间来适应它)。因此,在AndroidManifest.xml中设置默认的通知渠道现在是一个有效的解决方法,但它并不起作用。


你创建了字符串值 default_notification_channel_id 吗? - Tash Pemhiwa
当然,我做了。 - Vit Khudenko
1
在你的帖子中,你写了“.default_notification_channel”,但应该是“..default_notification_channel_id”。 - rickul
请参考与该问题相关的答案:[https://dev59.com/jFYO5IYBdhLWcg3wTPvk#46047344]。 - ToolmakerSteve
3个回答

19

请参考文档:https://firebase.google.com/docs/cloud-messaging/http-server-ref

android_channel_id 通知的渠道 ID(Android O 中新增)。

在接收到此关键字对应的任何通知之前,应用必须使用此 ID 创建一个渠道。

如果您没有在请求中发送此关键字,或者提供的渠道 ID 尚未由您的应用创建,则 FCM 将使用在应用清单中指定的渠道 ID。

尝试在即将发布到 fcm 的 json 中包括 android_channel_id。我不知道为什么您的清单值无法工作。尝试只是添加渠道到您的请求,您应该得到与 Firebase 控制台相同的效果。

编辑:我刚意识到您正在要求 Amazon 客户端集成。也许您能够手动构建 json 请求(对于 Amazon 服务,我不是很了解,抱歉)。


非常感谢!我能够通过Amazon SNS控制台使用android_channel_id参数(只需将其添加到JSON有效负载中)。这甚至比AndroidManifest.xml中的默认通知通道更好,所以我不再为它无法工作而烦恼。 :) - Vit Khudenko
3
如何创建 android_channel_id - Mahesh Gawhane
2
引用的链接指向一个标记为Legacy HTTP Server Protocol的部分,但主协议部分没有提到android_channel_id。 - JulianSymes
1
@VitKhudenko,我可以问一下你在JSON文件中具体添加了什么吗?谢谢。 - rosu alin
1
@rosualin,android_channel_id参数是特定于我的应用程序的字符串ID值。 - Vit Khudenko
显示剩余4条评论

16

FCM已经迁移到HTTP v1 API

https://fcm.googleapis.com/v1/projects/{{projectId}}/messages:send

android_channel_id 会导致错误的请求:

"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
  {
    "field": "message.notification",
    "description": "Invalid JSON payload received. Unknown name \"android_channel_id\" at 'message.notification': Cannot find field."
  }

正确的有效载荷应该是:

{
    "message": {
        "token": "{{deviceToken}}",
        "notification": {
            "body": "This is an FCM notification message hello 23",
            "title": "FCM Message",
            "image": "https://lumiere-a.akamaihd.net/v1/images/au_moviesshowcase_mulan_poster_r_2_54011055.jpeg?region=0,0,960,1420"
        },
        "android": {
          "notification": {
            "channel_id": "channel_id_1"
          }
        },
        "data": {
            "key1": "42",
            "key2": "sent by 21"
        }
    }
}

请参阅https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#resource:-message


2
但问题在于,如果负载包含“通知”部分,则当应用程序在后台时,“onMessageReceived”将不会被调用,这意味着如果您需要调用“onMessageReceived”,则不能将通道ID放入负载中,无论应用程序是在前台还是后台。完全不知道如何使它们同时工作。笑 - Weiyi
嘿li2,我的情况也完全一样。你或其他人解决了吗? - gramos
1
@GuilhermeRamos 你可以在"data"部分添加一个额外的键"channel_id",然后在"onMessageReceived"回调函数中解析数据负载remoteMessage.data,这样你就可以自由操作了。 - Weiyi
终于在搜寻了数小时后成功了,谢谢,老兄 :) - Shalabyer
嘿,有人找到解决方案了吗? - Luca Jeevanjee
显示剩余2条评论

10
依赖此资源:https://firebase.google.com/docs/cloud-messaging/http-server-ref 这里的有效载荷(Payload)如下:
{
   "to":"$device_token"
   "notification":{
      "title":"Title",
      "body":"Here Body",
      "android_channel_id":"$channel_id", // For Android >= 8
      "channel_id":"$channel_id", // For Android Version < 8
      "image": "https://xxxxx.com/xxxxx.jpeg"
   },
   "data":{},
   "priority":"normal"
}

4
这是我正在寻找的,大家看一下这个答案代码注释,他指定了 android_channel_idchannel_id - abdalmonem

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接