iOS でのトピック メッセージング

パブリッシュ / サブスクライブ モデルに基づく FCM トピック メッセージングでは、特定のトピックにオプトインした複数の端末にメッセージを送信できます。必要に応じて作成したトピック メッセージを FCM がルーティング処理し、確実に正しい端末にメッセージを配信します。

たとえば、地域の天気予報アプリのユーザーは、「荒天警報」のトピックにオプトインし、暴風雨警報指定地域の通知を受信できます。スポーツアプリのユーザーは、お気に入りのチームの実況ゲームスコアの自動更新に登録できます。

トピックに関する留意点を以下に示します。

  • トピック メッセージングは、アプリごとに無制限のトピックとサブスクリプションをサポートします。
  • 現在、トピック メッセージ ペイロードは 2 KB に制限されています。
  • トピック メッセージングは、ニュース、天気、その他の広く入手可能な情報コンテンツに最適です。
  • トピック メッセージは、レイテンシではなくスループットに対して最適化されます。単一の端末または端末の小グループに高速かつ安全に配信する場合は、トピックではなく登録トークンをメッセージの宛先としてください
  • 各ユーザーの複数の端末にメッセージを送信する必要がある場合は、そのようなユースケース向けの端末グループ メッセージングを検討してください。

クライアント アプリをトピックに登録する

クライアント アプリを既存のトピックに登録することも、新しいトピックを作成することもできます。クライアント アプリを新しいトピック名(Firebase プロジェクトにまだ存在していないトピック名)に登録すると、その名前の新しいトピックが FCM に作成され、その後すべてのクライアントはそのトピック名に登録できるようになります。

FIRMessaging クラスは、トピック メッセージング機能を処理します。トピックに登録するには、アプリケーションのメインスレッドから subscribeToTopic:topic を呼び出します(FCM はスレッドセーフではありません)。

[[FIRMessaging messaging] subscribeToTopic:@"news"];
NSLog(@"Subscribed to news topic");

これにより、FCM バックエンドへの非同期リクエストが作成され、所定のトピックにクライアントが登録されます。最初の登録リクエストが失敗した場合、FCM はトピックに正しく登録できるまで再試行します。アプリが開始するごとに、FCM は、リクエストされたすべてのトピックが登録されたことを確認します。

登録解除するには、unsubscribeFromTopic:topic を呼び出します。これにより、FCM がバックグラウンドでトピックからの登録解除を行います。

サーバーでトピック登録を管理する

Instance ID API を利用して、サーバー側から基本的なトピック管理タスクを行うことができます。クライアント アプリ インスタンスの登録トークンを取得すると、次の操作を行えます。

メッセージを受信して処理する

FCM は、他のダウンストリーム メッセージと同じようにトピック メッセージを配信します。

AppDelegate application:didReceiveRemoteNotification: を次のように実装します。

Swift

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // Messaging.messaging().appDidReceiveMessage(userInfo)

  // Print message ID.
  if let messageID = userInfo[gcmMessageIDKey] {
    print("Message ID: \(messageID)")
  }

  // Print full message.
  print(userInfo)
}

func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // Messaging.messaging().appDidReceiveMessage(userInfo)

  // Print message ID.
  if let messageID = userInfo[gcmMessageIDKey] {
    print("Message ID: \(messageID)")
  }

  // Print full message.
  print(userInfo)

  completionHandler(UIBackgroundFetchResult.newData)
}

Objective-C

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // [[FIRMessaging messaging] appDidReceiveMessage:userInfo];

  // Print message ID.
  if (userInfo[kGCMMessageIDKey]) {
    NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
  }

  // Print full message.
  NSLog(@"%@", userInfo);
}

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
    fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  // If you are receiving a notification message while your app is in the background,
  // this callback will not be fired till the user taps on the notification launching the application.
  // TODO: Handle data of notification

  // With swizzling disabled you must let Messaging know about the message, for Analytics
  // [[FIRMessaging messaging] appDidReceiveMessage:userInfo];

  // Print message ID.
  if (userInfo[kGCMMessageIDKey]) {
    NSLog(@"Message ID: %@", userInfo[kGCMMessageIDKey]);
  }

  // Print full message.
  NSLog(@"%@", userInfo);

  completionHandler(UIBackgroundFetchResultNewData);
}

ビルド送信リクエスト

サーバー側からの Firebase Cloud Messaging トピックへのメッセージの送信は、個々の端末やユーザー グループ宛てのメッセージの送信とよく似ています。アプリサーバーは to キーに /topics/yourTopic などの値を設定します。デベロッパーは、正規表現 "/topics/[a-zA-Z0-9-_.~%]+" に一致するすべてのトピック名を選択できます。

複数のトピックの組み合わせに送信する場合、アプリサーバーは condition キーに、対象のトピックを指定するブール条件を設定します。たとえば、TopicA と、TopicBTopicC のいずれかに登録された端末にメッセージを送信する場合は、次のようになります。

'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)

FCM はまず、かっこ内の条件を評価し、次に左から右に式を評価していきます。上記の式では、いずれか 1 つのトピックだけに登録したユーザーはメッセージを受信しません。同様に、TopicA に登録していないユーザーはメッセージを受信しません。メッセージを受信するのは、次の組み合わせの場合のみです。

  • TopicA と TopicB
  • TopicA と TopicC

トピックの条件では、かっこの使用と、式ごとに 2 つの演算子の使用がサポートされています。

アプリサーバーのキーの詳細については、選択した接続サーバー プロトコル(HTTP または XMPP)のリファレンス情報をご覧ください。このページの例では、メッセージをトピックに送信する方法として HTTP と XMPP の両方を示しています。

トピック HTTP POST リクエスト

単一のトピックに送信します。

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

{
  "to" : /topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}

「犬」や「猫」のトピックに登録された端末に送信します。

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

{
  "condition": "'dogs' in topics || 'cats' in topics",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}

トピック HTTP レスポンス

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

トピック XMPP メッセージ

単一のトピックに送信します。

<message id="">
  <gcm xmlns="google:mobile:data">

{
  "to" : /topics/foo-bar",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}
  </gcm>
</message>

「犬」や「猫」のトピックに登録された端末に送信します。

<message id="">
  <gcm xmlns="google:mobile:data">

{
  "condition": "'dogs' in topics || 'cats' in topics",
  "priority" : "high",
  "notification" : {
    "body" : "This is a Firebase Cloud Messaging Topic Message!",
    "title" : "FCM Message",
  }
}
  </gcm>
</message>

トピック XMPP レスポンス

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

FCM 接続サーバーが、トピック送信リクエストに成功または失敗のレスポンスを返すまでに、最大 30 秒の遅延が発生する可能性があります。それに応じて、リクエスト内でアプリサーバーのタイムアウト値を必ず設定してください。

メッセージ オプションの完全なリストについては、選択した接続サーバー プロトコル(HTTP または XMPP)のリファレンス情報をご覧ください。

次のステップ

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。