web-dev-qa-db-ja.com

GCM / FCMの通知ペイロードのサイズ

この質問は、元はGoogleクラウドメッセージング(GCM)に関するものでしたが、現在はGCMに代わる新しいFirebase Cloud Messaging(FCM)にも当てはまります。

「通知」辞書を含むGCMペイロードのサイズを計算する方法を教えてください。

Android向けのGoogleクラウドメッセージングサービスを試しています。ドキュメントの一部には、最大4KBのデータを送信できると記載されています ここ は、「通知メッセージは最大2kbのペイロードを持つことができる」と述べています。

いくつかのテストを行うと、4KBのデータで満たされた「データ」ペイロードを含むメッセージを送信でき、サーバーは期待どおりにエラーなしでそれらを受け入れました。

しかし、「通知」ペイロードを使用すると、2KBを超えるデータを含むメッセージを送信でき、サーバーはエラーを返しませんでした。そのようなメッセージは大きすぎると思いました。

「通知」ペイロードは許可された4KBを「データ」ペイロードと共有しますが、同じ方法ではないことがわかりました。 「データ」ペイロードでは、キーと値のサイズを追加してサイズを計算できます。 「通知」ペイロードは、含まれるキーと値のサイズよりも多くのスペースを使用します。

「通知」ディクショナリが含まれているペイロードのサイズを事前に計算するにはどうすればよいですか?

13
jorcasso

新しいFCMサービスのペイロードサイズを実験しました。

「データ」ディクショナリを含み、「通知」ディクショナリを含まないメッセージの場合、最大4096文字(すべてのキーと値の長さをカウント)まで正確に送信できました。

「通知」辞書を含み、「データ」辞書を含まないメッセージ、および「通知」辞書と「データ」辞書の両方を含むメッセージの場合、最大4062文字まで送信できました。残りの34文字がどのようにカウントされるのかわかりませんでした。

これは、「通知」ペイロードを2Kに制限するドキュメントが正しくないことを意味します。 4K近くまで送れます。

現在、FCMの最新のドキュメントを読んでいると、 メッセージタイプのドキュメント が次のように言うことがわかりました。

通知メッセージには、ユーザーに表示される事前定義されたキーのセットが含まれています。対照的に、データメッセージには、ユーザー定義のカスタムKey-Valueペアのみが含まれます。通知メッセージには、オプションのデータペイロードを含めることができます。 両方のメッセージタイプの最大ペイロードは4KBですが、Firebaseコンソールからメッセージを送信する場合は、1024文字の制限が適用されます。

一方、 「MessageTooBig」エラーの説明 は次のように述べています。

メッセージに含まれるペイロードデータの合計サイズがFCMの制限を超えていないことを確認します。ほとんどのメッセージでは4096バイト、またはトピックへのメッセージの場合は2048バイト。これには、キーと値の両方が含まれます。

私がテストしたメッセージはトピックへのメッセージではなかったので、両方の引用によれば、それらは2Kに限定されるべきではありません。

したがって、現在のドキュメントによると、ペイロードの制限は4Kです(トピックへのメッセージの例外を除いて、私はテストしていません)。

18
Eran

ダウンストリームメッセージングの場合、GCMは2種類のペイロード(通知とデータ)を提供します。通知はより軽量なオプションであり、2KBの制限とユーザーに表示されるキーの事前定義されたセットがあります。データペイロードにより、開発者は最大4KBのカスタムキー/値ペアを送信できます。通知メッセージには、ユーザーが通知をクリックしたときに配信されるオプションのデータペイロードを含めることができます。

通知-GCMは、クライアントアプリに代わってエンドユーザーのデバイスにメッセージを自動的に表示します。通知には、ユーザーに表示される事前定義されたキーのセットがあります。通知ペイロードを設定します。オプションのデータペイロードを含めることができます。常に折りたたみ可能。

Data-クライアントアプリはデータメッセージの処理を担当します。データメッセージには、カスタムのキーと値のペアしかありません。データペイロードのみを設定します。折りたたみ可能または折りたたみ不可のいずれかです。

2
Nikhil Jain

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"
   }
}

上記のペイロードの場合、

全長=(通知ペイロード+データペイロード)の長さ

データペイロードの長さ= [キーの長さ+値の長さ] = [ニックネーム+本体+部屋]のバイト長+ [マリオテスト+優れた一致+ポルトガルVSDenmark]のバイト長= 12 + 39 = 51

通知ペイロードを計算するには、すべてのキーの前に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.                        

これがあなたの質問に答えることを願っています。

1
Aanjaneyulu

これは、明示的に要求したものではない可能性がありますが、GCMメッセージ内でその大量のペイロードデータを使用しない方がよいでしょう。

ペイロードをデータベース内に保存し、Web-APIを介して利用できるようにします。次に、そのデータベースエントリのIDのみを保持するGCMメッセージを送信します。これで、アプリはGCMとは無関係にペイロードをリクエストでき、サイズに制限されません。

別の利点もあります。GoogleはGCM経由で何を送信するかを認識しません。

ペイロードを長期間保存する必要がない場合は、Redisなどを使用して、そのペイロードを一定期間保存することもできます。

1
Stefan Wanitzek

また、ペイロードサイズを約4 kbに近づけました。

サイズが7 kbのペイロードを送信しようとしたときに、メッセージが大きすぎるというエラーメッセージが表示されました。

したがって、応答コードを解析して、ペイロードがGoogleサーバーに受け入れられたかどうかを確認できます。

0

文字列データをバイトに変換する従来の方法を使用できます。次のようなキーと値のペアを含む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;

文字列のエンコードは、同じ文字列でもバイト数が異なる場合があるため、必ず指定してください。上記の例では、エンコーディングとしてUTF-8が使用されています。

バイトをkBに変換するには、1024で除算します。詳細については、 this を参照してください。

0
AniV