Google is committed to advancing racial equity for Black communities. See how.
Эта страница была переведа с помощью Cloud Translation API.
Switch to English

Отправлять сообщения в темы в Интернете / JavaScript

Основываясь на модели публикации / подписки, обмен сообщениями по темам FCM позволяет отправлять сообщения на несколько устройств, которые выбрали определенную тему. Вы составляете тематические сообщения по мере необходимости, а FCM выполняет маршрутизацию и надежную доставку сообщения на нужные устройства.

Например, пользователи местного приложения для прогнозирования приливов и отливов могут выбрать тему «Оповещения о приливных течениях» и получать уведомления об оптимальных условиях морской рыбалки в определенных областях. Пользователи спортивного приложения могут подписаться на автоматические обновления результатов матчей своих любимых команд.

О некоторых вещах, которые следует помнить о темах:

  • Тематические сообщения лучше всего подходят для такого контента, как погода или другой общедоступной информации.
  • Тематические сообщения оптимизированы для обеспечения пропускной способности, а не задержки . Для быстрой и безопасной доставки на отдельные устройства или небольшие группы устройств нацеливайте сообщения на токены регистрации , а не на темы.
  • Если вам нужно отправлять сообщения на несколько устройств для каждого пользователя , рассмотрите возможность обмена сообщениями группы устройств для этих случаев использования.
  • Обмен сообщениями по темам поддерживает неограниченное количество подписок для каждой темы. Однако FCM применяет ограничения в следующих областях:
    • На один экземпляр приложения можно подписаться не более чем на 2000 тем.
    • Если вы используете пакетный импорт для подписки на экземпляры приложения, каждый запрос ограничен 1000 экземплярами приложения.
    • Частота новых подписок ограничена для каждого проекта. Если вы отправите слишком много запросов на подписку за короткий период времени, серверы FCM ответят ответом 429 RESOURCE_EXHAUSTED («квота превышена»). Повторите попытку с экспоненциальным откатом.

Подпишите клиентское приложение на тему

Вы можете передать список токенов регистрации методу подписки Firebase Admin SDK, чтобы подписать соответствующие устройства на тему:

Node.js

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

// Subscribe the devices corresponding to the registration tokens to the
// topic.
admin.messaging().subscribeToTopic(registrationTokens, topic)
  .then(function(response) {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully subscribed to topic:', response);
  })
  .catch(function(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");

Python

# 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");

API Admin FCM также позволяет вам отписывать устройства от темы, передавая токены регистрации в соответствующий метод:

Node.js

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

// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
admin.messaging().unsubscribeFromTopic(registrationTokens, topic)
  .then(function(response) {
    // See the MessagingTopicManagementResponse reference documentation
    // for the contents of response.
    console.log('Successfully unsubscribed from topic:', response);
  })
  .catch(function(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");

Python

# 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. Тип возврата имеет тот же формат независимо от количества токенов регистрации, указанных в запросе.

В случае ошибки (ошибки аутентификации, неверный токен или тема и т. Д.) Эти методы приводят к ошибке. Полный список кодов ошибок, включая описания и шаги по устранению, см. В разделе Ошибки API администратора FCM .

Получать и обрабатывать тематические сообщения

FCM доставляет тематические сообщения так же, как и другие нисходящие сообщения. Как обрабатывать сообщения на клиенте, зависит от состояния переднего плана / фона веб-страницы и других факторов, описанных в этом разделе.

Поведение сообщений различается в зависимости от того, находится ли страница на переднем плане (в фокусе) или в фоновом режиме, скрыта за другими вкладками или полностью закрыта. Во всех случаях страница должна обрабатывать onMessage вызов onMessage , но в фоновых случаях вам также может потребоваться обработать onBackgroundMessage или настроить отображение уведомления, чтобы пользователь мог вывести ваше веб-приложение на передний план.

Состояние приложения Уведомление Данные И то и другое
Передний план onMessage onMessage onMessage
Фон (сервисный работник) onBackgroundMessage (отображение уведомления отображается автоматически) onBackgroundMessage onBackgroundMessage (отображение уведомления отображается автоматически)

Обработка сообщений, когда ваше веб-приложение находится на переднем плане

Чтобы получить событие onMessage , ваше приложение должно определить работника службы обмена сообщениями Firebase в firebase-messaging-sw.js . В качестве альтернативы вы можете предоставить SDK существующего сервис- getToken(): Promise<string> помощью getToken(): Promise<string> .

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.0.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.0.1/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
  apiKey: 'api-key',
  authDomain: 'project-id.firebaseapp.com',
  databaseURL: 'https://project-id.firebaseio.com',
  projectId: 'project-id',
  storageBucket: 'project-id.appspot.com',
  messagingSenderId: 'sender-id',
  appId: 'app-id',
  measurementId: 'G-measurement-id',
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

Когда ваше приложение находится на переднем плане (пользователь в данный момент просматривает вашу веб-страницу), вы можете получать данные и полезные данные уведомлений прямо на странице.

// Handle incoming messages. Called when:
// - a message is received while the app has focus
// - the user clicks on an app notification created by a service worker
//   `messaging.setBackgroundMessageHandler` handler.
messaging.onMessage((payload) => {
  console.log('Message received. ', payload);
  // ...
});

Обработка сообщений, когда ваше веб-приложение находится в фоновом режиме

Все сообщения, полученные, когда приложение работает в фоновом режиме, вызывают отображение уведомления в браузере. Вы можете указать параметры для этого уведомления, такие как заголовок или действие щелчка, либо в запросе отправки с сервера приложения, либо с помощью логики сервис-воркера на клиенте.

Настройка параметров уведомления в запросе на отправку

Для уведомлений, отправленных с сервера приложений, FCM JavaScript API поддерживает ключ fcm_options.link . Обычно это настраивается на страницу в вашем веб-приложении:

https://fcm.googleapis.com//v1/projects/<YOUR-PROJECT-ID>/messages:send
Content-Type: application/json
Authorization: bearer <YOUR-ACCESS-TOKEN>

{
  "message": {
    "topic": "matchday",
    "notification": {
      "title": "Background Message Title",
      "body": "Background message body"
    },
    "webpush": {
      "fcm_options": {
        "link": "https://dummypage.com"
      }
    }
  }
}

Если значение ссылки указывает на страницу, которая уже открыта на вкладке браузера, щелчок по уведомлению переводит эту вкладку на передний план. Если страница еще не открыта, щелчок с уведомлением открывает страницу в новой вкладке.

Поскольку сообщения с данными не поддерживают fcm_options.link , рекомендуется добавлять fcm_options.link данные уведомления ко всем сообщениям с данными. Кроме того, вы можете обрабатывать уведомления с помощью сервис-воркера.

Для объяснения разницы между уведомлениями и сообщениями с данными см. Типы сообщений .

Настройка параметров уведомлений в сервис-воркере

Для сообщений с данными вы можете установить параметры уведомления в сервис-воркере. Сначала инициализируйте свое приложение в сервис-воркере:

// Give the service worker access to Firebase Messaging.
// Note that you can only use Firebase Messaging here. Other Firebase libraries
// are not available in the service worker.
importScripts('https://www.gstatic.com/firebasejs/8.0.1/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.0.1/firebase-messaging.js');

// Initialize the Firebase app in the service worker by passing in
// your app's Firebase config object.
// https://firebase.google.com/docs/web/setup#config-object
firebase.initializeApp({
  apiKey: 'api-key',
  authDomain: 'project-id.firebaseapp.com',
  databaseURL: 'https://project-id.firebaseio.com',
  projectId: 'project-id',
  storageBucket: 'project-id.appspot.com',
  messagingSenderId: 'sender-id',
  appId: 'app-id',
  measurementId: 'G-measurement-id',
});

// Retrieve an instance of Firebase Messaging so that it can handle background
// messages.
const messaging = firebase.messaging();

Чтобы установить параметры, вызовите setBackgroundMessageHandler в setBackgroundMessageHandler firebase-messaging-sw.js . В этом примере мы создаем уведомление с полями заголовка, тела и значка.

messaging.onBackgroundMessage(function(payload) {
  console.log('[firebase-messaging-sw.js] Received background message ', payload);
  // Customize notification here
  const notificationTitle = 'Background Message Title';
  const notificationOptions = {
    body: 'Background Message body.',
    icon: '/firebase-logo.png'
  };

  self.registration.showNotification(notificationTitle,
    notificationOptions);
});

Создание запросов на отправку

После создания темы, подписав экземпляры клиентского приложения на тему на стороне клиента или через серверный API , вы можете отправлять сообщения в тему. Если вы впервые создаете запросы отправки для FCM, ознакомьтесь с важной справочной информацией и информацией по настройке в руководстве по серверной среде и FCM .

В логике отправки на серверной части укажите желаемое имя темы, как показано:

Node.js

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

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

// Send a message to devices subscribed to the provided topic.
admin.messaging().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);

Python

# 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

Чтобы отправить сообщение на комбинацию тем, укажите условие , которое является логическим выражением, определяющим целевые темы. Например, следующее условие отправит сообщения на устройства, которые подписаны на TopicA и на TopicB или TopicC :

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

FCM сначала оценивает любые условия в скобках, а затем вычисляет выражение слева направо. В приведенном выше выражении пользователь, подписанный на какую-либо отдельную тему, не получает сообщение. Аналогичным образом, пользователь, не подписанный на TopicA , не получит сообщение. Эти комбинации действительно получают:

  • TopicA и TopicB
  • TopicA и TopicC

В условное выражение можно включить до пяти тем.

Чтобы отправить в условие:

Node.js

// 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 = {
  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.
admin.messaging().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);

Python

# 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

Следующие шаги