GCM / FCM中通知有效负载的大小

时间:2015-07-07 09:03:32

标签: android google-cloud-messaging firebase-cloud-messaging

此问题最初是指Google Cloud Messaging(GCM),但现在它也适用于取代GCM的新Firebase云消息传递(FCM)。

我想知道如何在GCM有效负载包含“通知”字典时计算其大小。

我一直在尝试针对Android的Google Cloud Messaging服务。文档的某些部分说您可以发送最多4KB的数据,here它说“通知消息最多可以有2kb的负载”。

做一些测试我可以发送带有4KB数据的“数据”有效负载的消息,服务器按预期接受它们而没有错误。

但是,使用“通知”有效负载我发现我可以发送超过2KB数据的消息,并且服务器没有返回错误。我预计这样的消息会太大了。

我发现“通知”有效负载与“数据”有效负载共享允许的4KB,但不是以相同的方式。在“数据”有效负载中,您可以通过添加键和值的大小来计算大小。 “通知”有效负载占用的空间大于密钥的大小和它包含的值。

如果有效载荷包含“通知”字典,我如何预先计算有效载荷的大小?

6 个答案:

答案 0 :(得分:16)

我尝试了新的FCM服务的有效负载大小。

对于包含"数据"的消息字典,没有"通知"字典,我设法发送最多4096个字符(计算所有键和值的长度)。

对于包含"通知"的邮件字典和没有"数据"字典,以及包含"通知"的消息。字典和数据"字典我设法发送多达4062个字符。我无法弄清楚剩余的34个字符是如何计算的。

这意味着限制"通知"有效载荷到2K是不正确的。您可以发送接近4K。

现在,阅读FCM的最新文档,我发现the documentation of Message types说:

  

通知消息包含一组预定义的用户可见键。相反,数据消息仅包含用户定义的自定义键值对。通知消息可以包含可选的数据有效负载。 两种邮件类型的最大有效负载为4KB ,但从Firebase控制台发送邮件时除外,该控制台强制执行1024个字符的限制。

另一方面,the description of the "MessageTooBig" error说:

  

检查消息中包含的有效负载数据的总大小是否超过FCM限制:大多数消息为4096字节,对于主题消息为或2048字节。这包括键和值。

我测试的消息不是主题消息,因此根据两个引号,它们不应限于2K。

因此,根据当前文档的有效负载限制是4K(除了主题消息之外,我没有测试过。)

答案 1 :(得分:2)

对于下游消息传递,GCM提供两种类型的有效负载:通知和数据。通知是更轻量级的选项,具有2KB限制和一组预定义的用户可见键。数据有效负载允许开发人员发送最多4KB的自定义键/值对。通知消息可以包含可选的数据有效负载,当用户单击通知时会将其传递。

通知 - GCM会代表客户端应用自动向最终用户设备显示消息。通知具有一组预定义的用户可见键。设置通知负载。可能有可选的数据负载。总是可折叠的。

数据 - 客户端应用负责处理数据消息。数据消息只有自定义键/值对。仅设置数据有效负载。可以是可折叠的,也可以是不可折叠的。

答案 2 :(得分:1)

这可能不是您明确要求的内容,但最好不要在GCM消息中使用大量的有效负载数据。

将您的有效负载存储在数据库中,并通过Web-API使其可用。现在发送一个GCM-Message,它只包含该数据库条目的ID。现在,您的应用可以独立于GCM请求有效负载,并且您不限于此大小。

还有另一个优势:Google不会知道您通过GCM发送的内容。

如果您不需要长时间存储有效负载,您也可以使用Redis或类似的东西在有限的时间内存储该有效负载。

答案 3 :(得分:0)

我还体验到有效载荷大小仅接近4 kb。

当我试图发送一个7kb大小的有效载荷时,我向我展示了一个错误的响应,说消息太大了..

因此,您可以解析响应代码并验证Google服务器是否接受了有效负载。

答案 4 :(得分:0)

您可以使用将String数据转换为字节的传统方法。您以JSON形式获得的通知包含键/值对:

{
  "to" : "APA91bHun4MxP5egoKMwt2KZFBaFUH-1RYqx...",
  "notification" : {
    "body" : "great match!",
    "title" : "Portugal vs. Denmark"
  }
}

根据Google文档:

现在使用以下方法计算数据大小:

String mydata = "value from JSON";
byte[] mybyte = mydata.getBytes("UTF-8");
int bytes = mybyte.length;

确保指定String的编码,因为不同的编码可能占用相同String的不同字节数。在上面的示例中,UTF-8用作编码。

要将字节转换为kB,只需除以1024.有关详细信息,请参阅this

答案 5 :(得分:0)

FCM为通知有效负载中的每个键添加前缀 gcm.notification。

以下有效负载的样本计算:

  "to":"cgOtBDOGIEc:APA91bGrjdPtrnGr0sIl4c66Z3Xp-JTzUasIN5TzWy7DtNUf-BlGvF64iNOXFN68zFC6oTYHJbP6eQgzIZICcsmIUG-NP5cIXf8EyPNiIAvOFU27XDKFbI2vowMjsNmZQdmh",


  "notification":{
    "title":"Testing title from postman!",
    "body":"Testing body from postman!",
    "sound":"default",
    "tickerText":"This is ticker text"
  },
  "data" : {
     "Nick" : "Mario Test",
     "body" : "great match!",
     "Room" : "PortugalVSDenmark"
   }
}

对于上述有效载荷,

总长度=(通知有效负载+数据有效负载)的长度

数据有效负载的长度= [键的长度+值的长度] = [尼克+身体+房间]的字节长度+ [Mario测试+匹配+葡萄牙VSDenmark]的字节长度= 12 + 39 = 51 < / p>

要计算通知有效负载, 每个密钥必须带有gcm.notification前缀。

对于通知有效负载的每个键,firebase在内部添加gcm.notification。作为前缀,并同时考虑该前缀来计算长度。

Length of Notification Payload  =  [ no.of keys * length of (gcm.notification.)  +  length of keys + length of values ] 

                                 = 4*17 + length of bytes of [ title + body + sound + tickerText ] + length of bytes of [ Testing title from postman! + Testing body from postman! + default + This is ticker text ]

                                                   = 68 + 24 +79

                                                   =  171 bytes

Total length of the payload = 51 + 171 =  222 bytes.                        

希望这能回答您的问题。