FCM(Firebase云消息传递)向多个设备发送消息

22

我使用 FCM 库执行此代码以将通知推送到移动设备

public string PushFCMNotification(string deviceId, string message) 
    {
        string SERVER_API_KEY = "xxxxxxxxxxxxxxxxxxxxxxx";
        var SENDER_ID = "xxxxxxxxx";
        var value = message;
        WebRequest tRequest;
        tRequest = WebRequest.Create("https://fcm.googleapis.com/fcm/send");
        tRequest.Method = "post";
        tRequest.ContentType = "application/json";
        tRequest.Headers.Add(string.Format("Authorization: key={0}", SERVER_API_KEY));

        tRequest.Headers.Add(string.Format("Sender: id={0}", SENDER_ID));

        var data = new
        {
            to = deviceId,
            notification = new
            {
                body = "This is the message",
                title = "This is the title",
                icon = "myicon"
            }
        };

        var serializer = new JavaScriptSerializer();
        var json = serializer.Serialize(data);

        Byte[] byteArray = Encoding.UTF8.GetBytes(json);

        tRequest.ContentLength = byteArray.Length;

        Stream dataStream = tRequest.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();

        WebResponse tResponse = tRequest.GetResponse();

        dataStream = tResponse.GetResponseStream();

        StreamReader tReader = new StreamReader(dataStream);

        String sResponseFromServer = tReader.ReadToEnd();


        tReader.Close();
        dataStream.Close();
        tResponse.Close();
        return sResponseFromServer;
    }

现在,如何向多设备发送消息, 假设将字符串deviceId参数替换为设备ID列表。

你能帮忙吗?


请查看这个小而简单的库 - https://github.com/karanatwal/FirePush - karanatwal.github.io
5个回答

37
更新:对于v1版本,似乎不再支持registration_ids。强烈建议使用主题代替。仅支持文档中显示的参数。
只需在有效载荷中使用registration_ids参数,而不是to。根据您的用例,您可以使用Topic MessagingDevice Group Messaging。Firebase云消息传递(FCM)主题消息允许您向选择特定主题的多个设备发送消息。基于发布/订阅模型,主题消息支持每个应用程序的无限订阅。您可以根据需要编写主题消息,Firebase会处理消息路由并可靠地将消息传递到正确的设备。例如,本地天气预报应用程序的用户可以选择加入“严重天气警报”主题,并接收威胁指定区域的暴风雨通知。体育应用程序的用户可以订阅其最喜欢团队的实时比分自动更新。开发人员可以选择与正则表达式匹配的任何主题名称:"/topics/[a-zA-Z0-9-_.~%]+"
设备组消息 通过设备组消息,应用程序服务器可以向属于同一用户的多个设备上运行的应用程序实例发送单个消息。 通常,“组”指的是属于单个用户的不同设备集合。组中的所有设备共享一个公共通知密钥,该密钥是FCM用于向组中所有设备扇出消息的令牌。
设备组消息使得组中的每个应用程序实例都能反映最新的消息状态。除了将消息下发到通知密钥,您还可以使设备向设备组发送上行消息。您可以使用XMPP或HTTP连接服务器与设备组消息配合使用。发送到iOS设备时,数据有效负载的限制为2KB,其他平台为4KB。 notification_key允许的最大成员数为20。

如需更多详细信息,请查看FCM中发送到多个设备文档。


4
考虑使用主题,特别是如果您发送的设备数量超过1000。 - Arthur Thompson
1
你能添加关于 对于v1,registration_ids不再被支持 的源代码吗? - Nimit Bhargava
2
@NimitBhargava https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages -- v1 版本中未指定 registration_ids - AL.

16

你应该创建一个主题,并让用户订阅该主题。这样,当你发送FCM消息时,所有订阅的用户都会收到该消息,除非你实际上想为特殊目的记录他们的Id。

FirebaseMessaging.getInstance().subscribeToTopic("news");

请查看此链接:https://firebase.google.com/docs/cloud-messaging/android/topic-messaging

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{
  "to": "/topics/news",
  "data": {
    "message": "This is a Firebase Cloud Messaging Topic Message!",
   }
}

这是我认为最好的答案。 但我的解决方案很容易从客户端实现。 你很棒。 - Tawfiq Dawod
1
这总是返回错误=InvalidRegistration。不需要注册令牌。对吗? - Wai Yan Hein
你是否忘记定义 API 密钥? - Tosin Onikute
如果用户注销,设备应该取消订阅所有主题,并根据新验证的用户重新订阅。 - JCarlosR
这适用于单个主题,对于多个主题,Firebase文档中提到:'TopicA' in topics || 'TopicB' in topics || 'TopicC' in topics。是否有其他方法可以一次发送多个主题到端点? - Champ
Firebase太棒了!我正在处理Flutter Firebase FCM,只是想要一种从Postman向所有设备发送通知的方法!这个方法非常好用... Flutter开发者:_firebaseMessaging.subscribeToTopic("news");在Firebase配置之后添加这行代码。 - krupesh Anadkat

5
请按照以下步骤操作。
public String addNotificationKey(
    String senderId, String userEmail, String registrationId, String idToken)
    throws IOException, JSONException {
URL url = new URL("https://android.googleapis.com/gcm/googlenotification");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setDoOutput(true);

// HTTP request header
con.setRequestProperty("project_id", senderId);
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Accept", "application/json");
con.setRequestMethod("POST");
con.connect();

// HTTP request
JSONObject data = new JSONObject();
data.put("operation", "add");
data.put("notification_key_name", userEmail);
data.put("registration_ids", new JSONArray(Arrays.asList(registrationId)));
data.put("id_token", idToken);

OutputStream os = con.getOutputStream();
os.write(data.toString().getBytes("UTF-8"));
os.close();

// Read the response into a string
InputStream is = con.getInputStream();
String responseString = new Scanner(is, "UTF-8").useDelimiter("\\A").next();
is.close();

// Parse the JSON string and return the notification key
JSONObject response = new JSONObject(responseString);
return response.getString("notification_key");

我希望上面的代码可以帮助您在多个设备上发送推送消息。 要了解更多详细信息,请参阅此链接:https://firebase.google.com/docs/cloud-messaging/android/device-group

***注意:请务必阅读上面链接中有关创建/删除设备组的说明。


1

FCM文档中提到了一些警告,如下所示:

注意:任何使用设备组消息的应用程序必须继续使用传统API来管理设备组(创建、更新等)。HTTP v1可以向设备组发送消息,但不支持管理。

https://firebase.google.com/docs/cloud-messaging/migrate-v1

此外,Admin SDK使用批处理HttpPost请求使其易于消费者使用,因此,如果您想要设备组消息传递,则仍可以使用新的V1 FCM API,但是需要使用FCM Admin SDK。

以下是Admin SDK中执行此操作的代码。

类名:FirebaseMessagingClientImpl

    for (Message message : messages) {
      // Using a separate request factory without authorization is faster for large batches.
      // A simple performance test showed a 400-500ms speed up for batches of 1000 messages.
      HttpRequest request = childRequestFactory.buildPostRequest(
          sendUrl,
          new JsonHttpContent(jsonFactory, message.wrapForTransport(dryRun)));
      request.setParser(jsonParser);
      setCommonFcmHeaders(request.getHeaders());
      batch.queue(
          request, MessagingServiceResponse.class, MessagingServiceErrorResponse.class, callback);
    }


0
我刚刚添加了下面两行代码,我的代码可以在多个设备上运行:
"to": "/topics/news", FirebaseMessaging.getInstance().subscribeToTopic("news");

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