Firebase Summit で発表されたすべての情報をご覧ください。Firebase を使用してアプリ開発を加速し、自信を持ってアプリを実行する方法を紹介しています。詳細

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

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

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

たとえば、地元の潮汐予報アプリのユーザーは、「潮流アラート」トピックにオプトインして、指定された地域での最適な海水釣り条件の通知を受け取ることができます。スポーツ アプリのユーザーは、お気に入りのチームのライブ ゲーム スコアの自動更新を購読できます。

トピックについては、次の点に注意してください。

  • トピック メッセージングは​​、天気やその他の公開情報などのコンテンツに最適です。
  • トピック メッセージは、待ち時間ではなくスループットを重視して最適化されています。単一のデバイスまたはデバイスの小さなグループに高速かつ安全に配信するには、メッセージのターゲットをトピックではなく登録トークンにします。
  • ユーザーごとに複数のデバイスにメッセージを送信する必要がある場合は、それらのユースケースでデバイス グループ メッセージングを検討してください。
  • トピック メッセージングは​​、トピックごとに無制限のサブスクリプションをサポートします。ただし、FCM は次の領域で制限を適用します。
    • 1 つのアプリ インスタンスをサブスクライブできるトピックは 2000 までです。
    • バッチ インポートを使用してアプリ インスタンスをサブスクライブしている場合、各リクエストは 1000 個のアプリ インスタンスに制限されます。
    • 新しいサブスクリプションの頻度は、プロジェクトごとにレート制限されています。短期間にあまりにも多くのサブスクリプション リクエストを送信すると、FCM サーバーは429 RESOURCE_EXHAUSTED (「クォータを超えました」) レスポンスで応答します。指数バックオフで再試行します。

クライアント アプリをトピックにサブスクライブする

トピックをサブスクライブするには、アプリケーションから::firebase::messaging::Subscribeを呼び出します。これにより、FCM バックエンドへの非同期リクエストが作成され、クライアントが特定のトピックにサブスクライブされます。

::firebase::messaging::Subscribe("example");

サブスクリプション要求が最初に失敗した場合、FCM はトピックに正常にサブスクライブできるまで再試行します。アプリが起動するたびに、FCM は要求されたすべてのトピックがサブスクライブされていることを確認します。

サブスクライブを解除するには、 ::firebase::messaging::Unsubscribeを呼び出します。FCM はバックグラウンドでトピックからサブスクライブを解除します。

サーバーでトピック サブスクリプションを管理する

Firebase Admin SDKを使用すると、サーバー側から基本的なトピック管理タスクを実行できます。登録トークンがあれば、サーバー ロジックを使用してクライアント アプリ インスタンスを一括でサブスクライブおよびサブスクライブ解除できます。

クライアント アプリ インスタンスを既存のトピックにサブスクライブするか、新しいトピックを作成できます。 API を使用してクライアント アプリを新しいトピック (Firebase プロジェクトにまだ存在しないトピック) にサブスクライブすると、その名前の新しいトピックが FCM に作成され、その後、任意のクライアントがそれにサブスクライブできます。

登録トークンのリストを Firebase Admin SDK サブスクリプション メソッドに渡して、対応するデバイスをトピックにサブスクライブできます。

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Subscribe the devices corresponding to the registration tokens to the
// topic.
getMessaging().subscribeToTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully subscribed to topic:', response);
  })
  .catch((error) => {
    console.log('Error subscribing to topic:', error);
  });

ジャワ

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Subscribe the devices corresponding to the registration tokens to the
// topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were subscribed successfully");

パイソン

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Subscribe the devices corresponding to the registration tokens to the
# topic.
response = messaging.subscribe_to_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were subscribed successfully')

行け

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Subscribe the devices corresponding to the registration tokens to the
// topic.
response, err := client.SubscribeToTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were subscribed successfully")

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Subscribe the devices corresponding to the registration tokens to the
// topic
var response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were subscribed successfully");

Admin FCM API を使用すると、登録トークンを適切なメソッドに渡すことで、デバイスをトピックからサブスクライブ解除することもできます。

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // ...
  'YOUR_REGISTRATION_TOKEN_n'
];

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
getMessaging().unsubscribeFromTopic(registrationTokens, topic)
  .then((response) => {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully unsubscribed from topic:', response);
  })
  .catch((error) => {
    console.log('Error unsubscribing from topic:', error);
  });

ジャワ

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopic(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were unsubscribed successfully");

パイソン

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_n',
]

# Unubscribe the devices corresponding to the registration tokens from the
# topic.
response = messaging.unsubscribe_from_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were unsubscribed successfully')

行け

// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
response, err := client.UnsubscribeFromTopic(ctx, registrationTokens, topic)
if err != nil {
	log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were unsubscribed successfully")

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};

// Unsubscribe the devices corresponding to the registration tokens from the
// topic
var response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(
    registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were unsubscribed successfully");

subscribeToTopic()およびunsubscribeFromTopic()メソッドは、FCM からの応答を含むオブジェクトになります。要求で指定された登録トークンの数に関係なく、戻り値の型は同じ形式になります。

エラー (認証の失敗、無効なトークンまたはトピックなど) の場合、これらのメソッドはエラーになります。説明と解決手順を含むエラー コードの完全なリストについては、 Admin FCM API Errorsを参照してください。

トピック メッセージを受信して​​処理する

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

メソッド::firebase::messaging::Listener::OnMessageをオーバーライドすることで、受信したメッセージに基づいてアクションを実行し、メッセージ データを取得できます。

void OnMessage(const ::firebase::messaging::Message& message) {
  LogMessage(TAG, "From: %s", message.from.c_str());
  LogMessage(TAG, "Message ID: %s", message.message_id.c_str());
}

送信リクエストの作成

トピックを作成したら、クライアント アプリ インスタンスをクライアント側のトピックにサブスクライブするか、サーバー APIを介してトピックにメッセージを送信できます。 FCM の送信リクエストを初めて作成する場合は、重要な背景情報とセットアップ情報について、サーバー環境と FCM のガイドを参照してください

バックエンドの送信ロジックで、次のように目的のトピック名を指定します。

Node.js

// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';

const message = {
  data: {
    score: '850',
    time: '2:45'
  },
  topic: topic
};

// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

ジャワ

// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";

// See documentation on defining a message payload.
Message message = Message.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .setTopic(topic)
    .build();

// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

パイソン

# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'

# See documentation on defining a message payload.
message = messaging.Message(
    data={
        'score': '850',
        'time': '2:45',
    },
    topic=topic,
)

# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

行け

// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Topic: topic,
}

// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

C#

// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";

// See documentation on defining a message payload.
var message = new Message()
{
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
    Topic = topic,
};

// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

休み

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
  "message":{
    "topic" : "foo-bar",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message"
      }
   }
}

cURL コマンド:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "message": {
    "topic" : "foo-bar",
    "notification": {
      "body": "This is a Firebase Cloud Messaging Topic Message!",
      "title": "FCM Message"
    }
  }
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

トピックの組み合わせにメッセージを送信するには、条件を指定します。これは、ターゲット トピックを指定するブール式です。たとえば、次の条件は、 TopicATopicBまたはTopicCのいずれかにサブスクライブしているデバイスにメッセージを送信します。

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

FCM は、最初に括弧内の条件を評価し、次に式を左から右に評価します。上記の式では、単一のトピックにサブスクライブしているユーザーはメッセージを受信しません。同様に、 TopicAに登録していないユーザーはメッセージを受信しません。これらの組み合わせはそれを受け取ります:

  • TopicATopicB
  • TopicATopicC

条件式には最大 5 つのトピックを含めることができます。

条件に送信するには:

Node.js

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
const condition = '\'stock-GOOG\' in topics || \'industry-tech\' in topics';

// See documentation on defining a message payload.
const message = {
  notification: {
    title: '$FooCorp up 1.43% on the day',
    body: '$FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
  },
  condition: condition
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

ジャワ

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
Message message = Message.builder()
    .setNotification(Notification.builder()
        .setTitle("$GOOG up 1.43% on the day")
        .setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
        .build())
    .setCondition(condition)
    .build();

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

パイソン

# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"

# See documentation on defining a message payload.
message = messaging.Message(
    notification=messaging.Notification(
        title='$GOOG up 1.43% on the day',
        body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
    ),
    condition=condition,
)

# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

行け

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Condition: condition,
}

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

C#

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
var message = new Message()
{
    Notification = new Notification()
    {
        Title = "$GOOG up 1.43% on the day",
        Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
    },
    Condition = condition,
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

休み

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
   "message":{
    "condition": "'dogs' in topics || 'cats' in topics",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message",
    }
  }
}

cURL コマンド:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "notification": {
    "title": "FCM Message",
    "body": "This is a Firebase Cloud Messaging Topic Message!",
  },
  "condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

次のステップ