获取我们在 Firebase 峰会上发布的所有信息,了解 Firebase 可如何帮助您加快应用开发速度并满怀信心地运行应用。了解详情

构建应用服务器发送请求

使用 Firebase Admin SDK 或 FCM 应用服务器协议,您可以构建消息请求并将其发送到以下类型的目标:

  • 主题名称
  • 健康)状况
  • 设备注册令牌
  • 设备组名称(仅适用于 Node.js 的旧协议和 Firebase Admin SDK)

您可以发送包含由预定义字段组成的通知负载、您自己的用户定义字段的数据负载或包含这两种负载类型的消息的消息。有关详细信息,请参阅消息类型

本页中的示例展示了如何使用 Firebase Admin SDK(支持NodeJavaPythonC#Go )和v1 HTTP 协议发送通知消息。还有通过旧的 HTTP 和 XMPP 协议发送消息的指南。

向特定设备发送消息

要发送到单个特定设备,请传递设备的注册令牌,如图所示。请参阅您平台的客户端设置信息以了解有关注册令牌的更多信息。

节点.js

// This registration token comes from the client FCM SDKs.
const registrationToken = 'YOUR_REGISTRATION_TOKEN';

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

// Send a message to the device corresponding to the provided
// registration token.
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);
  });

爪哇

// This registration token comes from the client FCM SDKs.
String registrationToken = "YOUR_REGISTRATION_TOKEN";

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

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

Python

# This registration token comes from the client FCM SDKs.
registration_token = 'YOUR_REGISTRATION_TOKEN'

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

# Send a message to the device corresponding to the provided
# registration token.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

// Obtain a messaging.Client from the App.
ctx := context.Background()
client, err := app.Messaging(ctx)
if err != nil {
	log.Fatalf("error getting Messaging client: %v\n", err)
}

// This registration token comes from the client FCM SDKs.
registrationToken := "YOUR_REGISTRATION_TOKEN"

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

// Send a message to the device corresponding to the provided
// registration token.
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#

// This registration token comes from the client FCM SDKs.
var registrationToken = "YOUR_REGISTRATION_TOKEN";

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

// Send a message to the device corresponding to the provided
// registration token.
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":{
      "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
      "notification":{
        "body":"This is an FCM notification message!",
        "title":"FCM Message"
      }
   }
}

卷曲命令:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message":{
   "notification":{
     "title":"FCM Message",
     "body":"This is an FCM Message"
   },
   "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send

成功时,每个发送方法都会返回一个消息 ID。 Firebase Admin SDK 以projects/{project_id}/messages/{message_id}格式返回 ID 字符串。 HTTP 协议响应是单个 JSON 密钥:

    {
      "name":"projects/myproject-b5ae1/messages/0:1500415314455276%31bd1c9631bd1c96"
    }

向多个设备发送消息

REST API 和 Admin FCM API 允许您将消息多播到设备注册令牌列表。每次调用最多可以指定 500 个设备注册令牌。

节点.js

// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // …
  'YOUR_REGISTRATION_TOKEN_N',
];

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

getMessaging().sendMulticast(message)
  .then((response) => {
    console.log(response.successCount + ' messages were sent successfully');
  });

爪哇

// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

MulticastMessage message = MulticastMessage.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .addAllTokens(registrationTokens)
    .build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
// See the BatchResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " messages were sent successfully");

Python

# Create a list containing up to 500 registration tokens.
# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_N',
]

message = messaging.MulticastMessage(
    data={'score': '850', 'time': '2:45'},
    tokens=registration_tokens,
)
response = messaging.send_multicast(message)
# See the BatchResponse reference documentation
# for the contents of response.
print('{0} messages were sent successfully'.format(response.success_count))

// Create a list containing up to 500 registration tokens.
// This registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}
message := &messaging.MulticastMessage{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Tokens: registrationTokens,
}

br, err := client.SendMulticast(context.Background(), message)
if err != nil {
	log.Fatalln(err)
}

// See the BatchResponse reference documentation
// for the contents of response.
fmt.Printf("%d messages were sent successfully\n", br.SuccessCount)

C#

// Create a list containing up to 500 registration tokens.
// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};
var message = new MulticastMessage()
{
    Tokens = registrationTokens,
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
};

var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

休息

构造一个 HTTP 批处理请求:

--subrequest_boundary
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /v1/projects/myproject-b5ae1/messages:send
Content-Type: application/json
accept: application/json

{
  "message":{
     "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
     "notification":{
       "title":"FCM Message",
       "body":"This is an FCM notification message!"
     }
  }
}

...

--subrequest_boundary
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /v1/projects/myproject-b5ae1/messages:send
Content-Type: application/json
accept: application/json

{
  "message":{
     "token":"cR1rjyj4_Kc:APA91bGusqbypSuMdsh7jSNrW4nzsM...",
     "notification":{
       "title":"FCM Message",
       "body":"This is an FCM notification message!"
     }
  }
}
--subrequest_boundary--

将请求保存到文件中(在此示例中为 batch_request.txt)。然后使用 cURL 命令:

curl --data-binary @batch_request.txt -H 'Content-Type: multipart/mixed; boundary="subrequest_boundary"' -H 'Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA' https://fcm.googleapis.com/batch

对于 Firebase Admin SDK,此操作在后台使用sendAll() API,如示例中所示。返回值是一个BatchResponse ,其响应列表对应于输入标记的顺序。当您要检查哪些令牌导致错误时,这很有用。

节点.js

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

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

getMessaging().sendMulticast(message)
  .then((response) => {
    if (response.failureCount > 0) {
      const failedTokens = [];
      response.responses.forEach((resp, idx) => {
        if (!resp.success) {
          failedTokens.push(registrationTokens[idx]);
        }
      });
      console.log('List of tokens that caused failures: ' + failedTokens);
    }
  });

爪哇

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

MulticastMessage message = MulticastMessage.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .addAllTokens(registrationTokens)
    .build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
if (response.getFailureCount() > 0) {
  List<SendResponse> responses = response.getResponses();
  List<String> failedTokens = new ArrayList<>();
  for (int i = 0; i < responses.size(); i++) {
    if (!responses.get(i).isSuccessful()) {
      // The order of responses corresponds to the order of the registration tokens.
      failedTokens.add(registrationTokens.get(i));
    }
  }

  System.out.println("List of tokens that caused failures: " + failedTokens);
}

Python

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

message = messaging.MulticastMessage(
    data={'score': '850', 'time': '2:45'},
    tokens=registration_tokens,
)
response = messaging.send_multicast(message)
if response.failure_count > 0:
    responses = response.responses
    failed_tokens = []
    for idx, resp in enumerate(responses):
        if not resp.success:
            # The order of responses corresponds to the order of the registration tokens.
            failed_tokens.append(registration_tokens[idx])
    print('List of tokens that caused failures: {0}'.format(failed_tokens))

// Create a list containing up to 500 registration tokens.
// This registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}
message := &messaging.MulticastMessage{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Tokens: registrationTokens,
}

br, err := client.SendMulticast(context.Background(), message)
if err != nil {
	log.Fatalln(err)
}

if br.FailureCount > 0 {
	var failedTokens []string
	for idx, resp := range br.Responses {
		if !resp.Success {
			// The order of responses corresponds to the order of the registration tokens.
			failedTokens = append(failedTokens, registrationTokens[idx])
		}
	}

	fmt.Printf("List of tokens that caused failures: %v\n", failedTokens)
}

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};
var message = new MulticastMessage()
{
    Tokens = registrationTokens,
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
};

var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message);
if (response.FailureCount > 0)
{
    var failedTokens = new List<string>();
    for (var i = 0; i < response.Responses.Count; i++)
    {
        if (!response.Responses[i].IsSuccess)
        {
            // The order of responses corresponds to the order of the registration tokens.
            failedTokens.Add(registrationTokens[i]);
        }
    }

    Console.WriteLine($"List of tokens that caused failures: {failedTokens}");
}

休息

每个发送子发送都返回一个响应。响应由以--batch_开头的响应边界字符串分隔。

--batch_nDhMX4IzFTDLsCJ3kHH7v_44ua-aJT6q
Content-Type: application/http
Content-ID: response-

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Vary: Origin
Vary: X-Origin
Vary: Referer

{
  "name": "projects/35006771263/messages/0:1570471792141125%43c11b7043c11b70"
}

...

--batch_nDhMX4IzFTDLsCJ3kHH7v_44ua-aJT6q
Content-Type: application/http
Content-ID: response-

HTTP/1.1 200 OK
Content-Type: application/json; charset=UTF-8
Vary: Origin
Vary: X-Origin
Vary: Referer

{
  "name": "projects/35006771263/messages/0:1570471792141696%43c11b7043c11b70"
}

--batch_nDhMX4IzFTDLsCJ3kHH7v_44ua-aJT6q--

向主题发送消息

创建主题后,通过在客户端订阅客户端应用程序实例或通过服务器 API订阅主题,您可以向该主题发送消息。如果这是您第一次为 FCM 构建发送请求,请参阅服务器环境和 FCM指南以获取重要的背景和设置信息。

在后端的发送逻辑中,指定所需的主题名称,如下所示:

节点.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);

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

要将消息发送到主题组合,请指定条件,它是指定目标主题的布尔表达式。例如,以下条件将向订阅了TopicATopicBTopicC的设备发送消息:

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

FCM 首先计算括号中的任何条件,然后从左到右计算表达式。在上面的表达式中,订阅任何单个主题的用户都不会收到消息。同样,未订阅TopicA的用户也不会收到该消息。这些组合确实收到了它:

  • TopicATopicB
  • TopicATopicC

您最多可以在条件表达式中包含五个主题。

发送到条件:

节点.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);

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

发送一批消息

REST API 和 Admin SDK 支持批量发送消息。您最多可以将 500 条消息分组到一个批次中,并在一个 API 调用中将它们全部发送,与为每条消息发送单独的 HTTP 请求相比,性能得到了显着提高。

此功能可用于构建自定义消息集并将其发送给不同的收件人,包括主题或特定设备注册令牌。例如,当您需要同时向不同的受众发送消息时,使用此功能,消息正文中的详细信息略有不同。

节点.js

// Create a list containing up to 500 messages.
const messages = [];
messages.push({
  notification: { title: 'Price drop', body: '5% off all electronics' },
  token: registrationToken,
});
messages.push({
  notification: { title: 'Price drop', body: '2% off all books' },
  topic: 'readers-club',
});

getMessaging().sendAll(messages)
  .then((response) => {
    console.log(response.successCount + ' messages were sent successfully');
  });

爪哇

// Create a list containing up to 500 messages.
List<Message> messages = Arrays.asList(
    Message.builder()
        .setNotification(Notification.builder()
            .setTitle("Price drop")
            .setBody("5% off all electronics")
            .build())
        .setToken(registrationToken)
        .build(),
    // ...
    Message.builder()
        .setNotification(Notification.builder()
            .setTitle("Price drop")
            .setBody("2% off all books")
            .build())
        .setTopic("readers-club")
        .build()
);

BatchResponse response = FirebaseMessaging.getInstance().sendAll(messages);
// See the BatchResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " messages were sent successfully");

Python

# Create a list containing up to 500 messages.
messages = [
    messaging.Message(
        notification=messaging.Notification('Price drop', '5% off all electronics'),
        token=registration_token,
    ),
    # ...
    messaging.Message(
        notification=messaging.Notification('Price drop', '2% off all books'),
        topic='readers-club',
    ),
]

response = messaging.send_all(messages)
# See the BatchResponse reference documentation
# for the contents of response.
print('{0} messages were sent successfully'.format(response.success_count))

// Create a list containing up to 500 messages.
messages := []*messaging.Message{
	{
		Notification: &messaging.Notification{
			Title: "Price drop",
			Body:  "5% off all electronics",
		},
		Token: registrationToken,
	},
	{
		Notification: &messaging.Notification{
			Title: "Price drop",
			Body:  "2% off all books",
		},
		Topic: "readers-club",
	},
}

br, err := client.SendAll(context.Background(), messages)
if err != nil {
	log.Fatalln(err)
}

// See the BatchResponse reference documentation
// for the contents of response.
fmt.Printf("%d messages were sent successfully\n", br.SuccessCount)

C#

// Create a list containing up to 500 messages.
var messages = new List<Message>()
{
    new Message()
    {
        Notification = new Notification()
        {
            Title = "Price drop",
            Body = "5% off all electronics",
        },
        Token = registrationToken,
    },
    new Message()
    {
        Notification = new Notification()
        {
            Title = "Price drop",
            Body = "2% off all books",
        },
        Topic = "readers-club",
    },
};

var response = await FirebaseMessaging.DefaultInstance.SendAllAsync(messages);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

休息

通过组合子请求列表构造一个 HTTP 批处理请求:

--subrequest_boundary
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /v1/projects/myproject-b5ae1/messages:send
Content-Type: application/json
accept: application/json

{
  "message":{
     "token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
     "notification":{
       "title":"FCM Message",
       "body":"This is an FCM notification message to device 0!"
     }
  }
}

--subrequest_boundary
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /v1/projects/myproject-b5ae1/messages:send
Content-Type: application/json
accept: application/json

{
  "message":{
     "topic":"readers-club",
     "notification":{
       "title":"Price drop",
       "body":"2% off all books"
     }
  }
}

...

--subrequest_boundary
Content-Type: application/http
Content-Transfer-Encoding: binary
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

POST /v1/projects/myproject-b5ae1/messages:send
Content-Type: application/json
accept: application/json

{
  "message":{
     "token":"cR1rjyj4_Kc:APA91bGusqbypSuMdsh7jSNrW4nzsM...",
     "notification":{
       "title":"FCM Message",
       "body":"This is an FCM notification message to device N!"
     }
  }
}
--subrequest_boundary--

您可以查询返回的BatchResponse以检查有多少消息已成功移交给 FCM。它还公开了可用于检查单个消息状态的响应列表。响应的顺序对应于输入列表中消息的顺序。

发送启用直接启动的消息(仅限 Android)

您可以使用 HTTP v1 或旧版 HTTP API 在直接启动模式下向设备发送消息。在直接启动模式下发送到设备之前,请确保您已完成使客户端设备能够在直接启动模式下接收 FCM 消息的步骤。

使用 FCM v1 HTTP API 发送

消息请求必须在请求正文的AndroidConfig选项中包含键"direct_boot_ok" : true 。例如:

https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send
Content-Type:application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

{
  "message":{
    "token" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
    "data": {
      "score": "5x1",
      "time": "15:10"
    },
    "android": {
      "direct_boot_ok": true,
    },
}

使用 FCM 旧版 HTTP API 发送

消息请求必须在请求正文的顶层包含键"direct_boot_ok" : true 。例如:

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

{ "data": {
    "score": "5x1",
    "time": "15:10"
  },
  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  "direct_boot_ok" : true
}

在请求正文中使用此键发送的消息可以由当前处于直接启动模式(以及不在该模式下)的设备上的应用程序处理。

跨平台自定义消息

Firebase Admin SDK 和 FCM v1 HTTP 协议都允许您的消息请求设置message对象中的所有可用字段。这包括:

  • 所有接收消息的应用程序实例解释的一组通用字段。
  • 特定于平台的字段集,例如AndroidConfigWebpushConfig ,仅由在指定平台上运行的应用实例解释。

特定于平台的块使您可以灵活地为不同平台自定义消息,以确保在收到它们时正确处理它们。 FCM 后端将考虑所有指定的参数并为每个平台定制消息。

何时使用公共字段

在以下情况下使用常用字段:

  • 针对所有平台(Apple、Android 和 Web)上的应用程序实例
  • 向主题发送消息

所有应用程序实例,无论平台如何,都可以解释以下公共字段:

何时使用特定于平台的字段

当您需要时使用特定于平台的字段:

  • 仅将字段发送到特定平台
  • 除了公共字段之外,还发送特定于平台的字段

每当您只想将值发送到特定平台时,请不要使用公共字段;使用特定于平台的字段。例如,要仅向 Apple 平台和 Web 发送通知而不向 Android 发送通知,您必须使用两组单独的字段,一组用于 Apple,一组用于 Web。

当您发送具有特定传递选项的消息时,请使用特定于平台的字段来设置它们。如果需要,您可以为每个平台指定不同的值。但是,即使您想跨平台设置基本相同的值,您也必须使用特定于平台的字段。这是因为每个平台对该值的解释可能略有不同——例如,在 Android 上将生存时间设置为以秒为单位的过期时间,而在 Apple 上将其设置为过期日期

示例:带有颜色和图标选项的通知消息

此示例发送请求向所有平台发送一个通用的通知标题和内容,但它也向 Android 设备发送一些特定于平台的覆盖。

对于 Android,该请求会设置一个特殊的图标和颜色以在 Android 设备上显示。如AndroidNotification参考中所述,颜色以 #rrggbb 格式指定,并且图像必须是 Android 应用本地的可绘制图标资源。

这是用户设备上视觉效果的近似值:

两个设备的简单绘图,其中一个显示自定义图标和颜色

节点.js

const topicName = 'industry-tech';

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.'
  },
  android: {
    notification: {
      icon: 'stock_ticker_update',
      color: '#7e55c3'
    }
  },
  topic: topicName,
};

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);
  });

爪哇

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())
    .setAndroidConfig(AndroidConfig.builder()
        .setTtl(3600 * 1000)
        .setNotification(AndroidNotification.builder()
            .setIcon("stock_ticker_update")
            .setColor("#f45342")
            .build())
        .build())
    .setApnsConfig(ApnsConfig.builder()
        .setAps(Aps.builder()
            .setBadge(42)
            .build())
        .build())
    .setTopic("industry-tech")
    .build();

Python

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.',
    ),
    android=messaging.AndroidConfig(
        ttl=datetime.timedelta(seconds=3600),
        priority='normal',
        notification=messaging.AndroidNotification(
            icon='stock_ticker_update',
            color='#f45342'
        ),
    ),
    apns=messaging.APNSConfig(
        payload=messaging.APNSPayload(
            aps=messaging.Aps(badge=42),
        ),
    ),
    topic='industry-tech',
)

oneHour := time.Duration(1) * time.Hour
badge := 42
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.",
	},
	Android: &messaging.AndroidConfig{
		TTL: &oneHour,
		Notification: &messaging.AndroidNotification{
			Icon:  "stock_ticker_update",
			Color: "#f45342",
		},
	},
	APNS: &messaging.APNSConfig{
		Payload: &messaging.APNSPayload{
			Aps: &messaging.Aps{
				Badge: &badge,
			},
		},
	},
	Topic: "industry-tech",
}

C#

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.",
    },
    Android = new AndroidConfig()
    {
        TimeToLive = TimeSpan.FromHours(1),
        Notification = new AndroidNotification()
        {
            Icon = "stock_ticker_update",
            Color = "#f45342",
        },
    },
    Apns = new ApnsConfig()
    {
        Aps = new Aps()
        {
            Badge = 42,
        },
    },
    Topic = "industry-tech",
};

休息

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":"industry-tech",
     "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."
     },
     "android":{
       "notification":{
         "icon":"stock_ticker_update",
         "color":"#7e55c3"
       }
     }
   }
 }

有关消息正文中特定于平台的块中可用键的完整详细信息,请参阅HTTP v1 参考文档

示例:带有自定义图像的通知消息

以下示例发送请求向所有平台发送一个通用的通知标题,但它也发送一个图像。这是用户设备上视觉效果的近似值:

在显示通知中简单绘制图像

节点.js

const topicName = 'industry-tech';

const message = {
  notification: {
    title: 'Sparky says hello!'
  },
  android: {
    notification: {
      imageUrl: 'https://foo.bar.pizza-monster.png'
    }
  },
  apns: {
    payload: {
      aps: {
        'mutable-content': 1
      }
    },
    fcm_options: {
      image: 'https://foo.bar.pizza-monster.png'
    }
  },
  webpush: {
    headers: {
      image: 'https://foo.bar.pizza-monster.png'
    }
  },
  topic: topicName,
};

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);
  });

休息

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":"industry-tech",
     "notification":{
       "title":"Sparky says hello!",
     },
     "android":{
       "notification":{
         "image":"https://foo.bar/pizza-monster.png"
       }
     },
     "apns":{
       "payload":{
         "aps":{
           "mutable-content":1
         }
       },
       "fcm_options": {
           "image":"https://foo.bar/pizza-monster.png"
       }
     },
     "webpush":{
       "headers":{
         "image":"https://foo.bar/pizza-monster.png"
       }
     }
   }
 }

有关消息正文中特定于平台的块中可用键的完整详细信息,请参阅HTTP v1 参考文档

示例:带有关联点击操作的通知消息

以下示例发送请求向所有平台发送一个通用通知标题,但它还发送一个操作以供应用程序执行以响应用户与通知交互。这是用户设备上视觉效果的近似值:

用户点击打开网页的简单绘图

节点.js

const topicName = 'industry-tech';

const message = {
  notification: {
    title: 'Breaking News....'
  },
  android: {
    notification: {
      clickAction: 'news_intent'
    }
  },
  apns: {
    payload: {
      aps: {
        'category': 'INVITE_CATEGORY'
      }
    }
  },
  webpush: {
    fcmOptions: {
      link: 'breakingnews.html'
    }
  },
  topic: topicName,
};

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);
  });

休息

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":"industry-tech",
     "notification":{
       "title":"Breaking News...",
     },
     "android":{
       "notification":{
         "click_action":"news_intent"
       }
     },
     "apns":{
       "payload":{
         "aps":{
           "category" : "INVITE_CATEGORY"
         }
       },
     },
     "webpush":{
       "fcm_options":{
         "link":"breakingnews.html"
       }
     }
   }
 }

有关消息正文中特定于平台的块中可用键的完整详细信息,请参阅HTTP v1 参考文档

示例:带有本地化选项的通知消息

以下示例发送请求为客户端发送本地化选项以显示本地化消息。这是用户设备上视觉效果的近似值:

用英语和西班牙语显示文本的两个设备的简单绘图

节点.js

var topicName = 'industry-tech';

var message = {
  android: {
    ttl: 3600000,
    notification: {
      bodyLocKey: 'STOCK_NOTIFICATION_BODY',
      bodyLocArgs: ['FooCorp', '11.80', '835.67', '1.43']
    }
  },
  apns: {
    payload: {
      aps: {
        alert: {
          locKey: 'STOCK_NOTIFICATION_BODY',
          locArgs: ['FooCorp', '11.80', '835.67', '1.43']
        }
      }
    }
  },
  topic: topicName,
};

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);
  });

休息

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":"Tech",
             "android":{
               "ttl":"3600s",
               "notification":{
                 "body_loc_key": "STOCK_NOTIFICATION_BODY",
                 "body_loc_args":  ["FooCorp", "11.80", "835.67", "1.43"],
               },
             },
             "apns":{
               "payload":{
                 "aps":{
                   "alert" : {
                     "loc-key": "STOCK_NOTIFICATION_BODY",
                     "loc-args":  ["FooCorp", "11.80", "835.67", "1.43"],
                    },
                 },
               },
             },
  },
}'

有关消息正文中特定于平台的块中可用键的完整详细信息,请参阅HTTP v1 参考文档

管理员错误代码

下表列出了 Firebase Admin FCM API 错误代码及其说明,包括推荐的解决步骤。

错误代码说明和解决步骤
messaging/invalid-argument向 FCM 方法提供了无效参数。错误消息应包含其他信息。
messaging/invalid-recipient预期的邮件收件人无效。错误消息应包含其他信息。
messaging/invalid-payload提供了无效的消息负载对象。错误消息应包含其他信息。
messaging/invalid-data-payload-key数据消息有效负载包含无效密钥。有关受限密钥,请参阅DataMessagePayload的参考文档。
messaging/payload-size-limit-exceeded提供的消息负载超出 FCM 大小限制。大多数消息的限制为 4096 字节。对于发送到主题的消息,限制为 2048 字节。总有效负载大小包括键和值。
messaging/invalid-options提供了无效的消息选项对象。错误消息应包含其他信息。
messaging/invalid-registration-token提供的注册令牌无效。确保它与客户端应用从 FCM 注册时收到的注册令牌匹配。不要截断或添加其他字符。
messaging/registration-token-not-registered提供的注册令牌未注册。以前有效的注册令牌可能因多种原因而取消注册,包括:
  • 客户端应用程序从 FCM 注销了自身。
  • 客户端应用程序已自动取消注册。如果用户卸载应用程序,或者在 Apple 平台上,如果 APNs 反馈服务报告 APNs 令牌无效,则可能会发生这种情况。
  • 注册令牌已过期。例如,Google 可能决定刷新注册令牌,或者 Apple 设备的 APNs 令牌可能已过期。
  • 客户端应用程序已更新,但新版本未配置为接收消息。
对于所有这些情况,请删除此注册令牌并停止使用它来发送消息。
messaging/invalid-package-name该消息被发送到一个注册令牌,其包名称与提供的restrictedPackageName包名称选项不匹配。
messaging/message-rate-exceeded发送给特定目标的消息率太高。减少发送到此设备或主题的消息数量,不要立即重试发送到此目标。
messaging/device-message-rate-exceeded发送到特定设备的消息率太高。减少发送到此设备的消息数量,不要立即重试发送到此设备。
messaging/topics-message-rate-exceeded发送给特定主题订阅者的消息率太高。减少为此主题发送的消息数量,不要立即重试发送到此主题。
messaging/too-many-topics一个注册令牌已经订阅了最大数量的主题,不能再订阅了。
messaging/invalid-apns-credentials无法发送针对 Apple 设备的消息,因为所需的 APNs SSL 证书未上传或已过期。检查您的开发和生产证书的有效性。
messaging/mismatched-credential用于认证此 SDK 的凭证无权向提供的注册令牌对应的设备发送消息。确保凭据和注册令牌都属于同一个 Firebase 项目。有关如何验证 Firebase Admin SDK 的文档,请参阅将 Firebase 添加到您的应用
messaging/authentication-error SDK 无法向 FCM 服务器进行身份验证。确保使用具有发送 FCM 消息的适当权限的凭据对 Firebase Admin SDK 进行身份验证。有关如何验证 Firebase Admin SDK 的文档,请参阅将 Firebase 添加到您的应用
messaging/server-unavailable FCM 服务器无法及时处理请求。您应该重试相同的请求,但您必须:
  • 如果Retry-After标头包含在来自 FCM 连接服务器的响应中,则遵守该标头。
  • 在重试机制中实施指数退避。例如,如果您在第一次重试之前等待了一秒钟,那么在下一次重试之前至少等待两秒钟,然后再等待四秒钟,依此类推。如果您要发送多条消息,请将每条消息单独延迟一个额外的随机量,以避免同时对所有消息发出新请求。
引起问题的发件人有被列入黑名单的风险。
messaging/internal-error FCM 服务器在尝试处理请求时遇到错误。您可以按照上面的messaging/server-unavailable行中列出的要求重试相同的请求。如果错误仍然存​​在,请将问题报告给我们的错误报告支持渠道。
messaging/unknown-error返回了未知的服务器错误。有关更多详细信息,请参阅错误消息中的原始服务器响应。如果您收到此错误,请向我们的错误报告支持频道报告完整的错误消息。

使用旧版应用服务器协议发送消息

如果您更喜欢使用旧协议,请按照本节所示构建消息请求。请记住,如果您通过 HTTP 发送到多个平台,v1 协议可以简化您的消息请求。

向特定设备发送消息

要将消息发送到特定设备,请将to键设置为特定应用实例的注册令牌。请参阅您平台的客户端设置信息以了解有关注册令牌的更多信息。

HTTP POST 请求

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

{ "data": {
    "score": "5x1",
    "time": "15:10"
  },
  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}

HTTP 响应

{ "multicast_id": 108,
  "success": 1,
  "failure": 0,
  "results": [
    { "message_id": "1:08" }
  ]
}

XMPP 消息

<message id="">
  <gcm xmlns="google:mobile:data">
    { "data": {
      "score": "5x1",
      "time": "15:10"
    },
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  }
  </gcm>
</message>

XMPP 响应

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "from":"REGID",
      "message_id":"m-1366082849205"
      "message_type":"ack"
  }
  </gcm>
</message>

XMPP 连接服务器为响应提供了一些其他选项。请参阅服务器响应格式

有关向客户端应用程序发送下游消息时可用的消息选项的完整列表,请参阅您选择的连接服务器协议HTTPXMPP的参考信息。

向主题发送消息

向 Firebase 云消息传递主题发送消息与向单个设备或用户组发送消息非常相似。应用服务器将to键设置为/topics/yourTopic类的值。开发者可以选择任何匹配正则表达式的主题名称: "/topics/[a-zA-Z0-9-_.~%]+"

要发送到多个主题的组合,应用服务器必须将condition键(而不是to键)设置为指定目标主题的布尔条件。例如,要向订阅了TopicATopicBTopicC的设备发送消息:

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

FCM 首先计算括号中的任何条件,然后从左到右计算表达式。在上面的表达式中,订阅任何单个主题的用户都不会收到消息。同样,未订阅 TopicA 的用户也不会收到该消息。这些组合确实收到了它:

  • 主题 A 和主题 B
  • 主题A和主题C

您最多可以在条件表达式中包含五个主题,并且支持括号。支持的运算符: && , || .

主题 HTTP POST 请求

发送到单个主题:

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


发送到订阅主题“狗”或“猫”的设备:

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


主题 HTTP 响应

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

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

主题 XMPP 消息

发送到单个主题:

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


  </gcm>
</message>

发送到订阅主题“狗”或“猫”的设备:

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


  </gcm>
</message>

主题 XMPP 响应

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

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

在 FCM 服务器向主题发送请求返回成功或失败响应之前,预计最多延迟 30 秒。确保在请求中相应地设置应用服务器的超时值。

向设备组发送消息

向设备组发送消息与向单个设备发送消息非常相似。将to参数设置为设备组的唯一通知键。有关有效负载支持的详细信息,请参阅消息类型。本页中的示例展示了如何将数据消息发送到旧 HTTP 和 XMPP 协议中的设备组。

设备组 HTTP POST 请求

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

{
  "to": "aUniqueKey",
  "data": {
    "hello": "This is a Firebase Cloud Messaging Device Group Message!",
   }
}

设备组 HTTP 响应

这是一个“成功”的例子notification_key有 2 个注册令牌与之关联,并且消息已成功发送给它们:

{
  "success": 2,
  "failure": 0
}

这是一个“部分成功”的例子notification_key有 3 个与之关联的注册令牌。消息仅成功发送到 1 个注册令牌。响应消息列出了未能接收到消息的注册令牌 ( registration_ids ):

{
  "success":1,
  "failure":2,
  "failed_registration_ids":[
     "regId1",
     "regId2"
  ]
}

当消息未能传递到与notification_key关联的一个或多个注册令牌时,应用服务器应在重试之间使用退避重试。

如果服务器尝试向没有成员的设备组发送消息,则响应如下所示,0 成功,0 失败:

{
  "success": 0,
  "failure": 0
}

设备组 XMPP 消息

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to": "aUniqueKey",
      "message_id": "m-1366082849205" ,
      "data": {
          "hello":"This is a Firebase Cloud Messaging Device Group Message!"
      }
  }
  </gcm>
</message>

设备组 XMPP 响应

当消息成功发送到组中的任何一个设备时,XMPP 连接服务器会以 ACK 响应。如果发送到组中所有设备的所有消息都失败,XMPP 连接服务器会以 NACK 响应。

下面是一个“成功”的例子notification_key有 3 个与之关联的注册令牌,并且消息已成功发送给所有这些令牌:

{
  "from": "aUniqueKey",
  "message_type": "ack",
  "success": 3,
  "failure": 0,
  "message_id": "m-1366082849205"
}

这是一个“部分成功”的例子notification_key有 3 个与之关联的注册令牌。消息仅成功发送到 1 个注册令牌。响应消息列出了未能收到消息的注册令牌:

{
  "from": "aUniqueKey",
  "message_type": "ack",
  "success":1,
  "failure":2,
  "failed_registration_ids":[
     "regId1",
     "regId2"
  ]
}

当 FCM 连接服务器无法传送到组中的所有设备时。应用服务器将收到一个 nack 响应。

有关消息选项的完整列表,请参阅您选择的连接服务器协议HTTPXMPP的参考信息。

Firebase Admin SDK 旧版发送方法

Firebase Admin Node.js SDK 支持基于Legacy FCM 服务器 API发送 (FCM) 消息的方法。与send()方法相比,这些方法接受不同的参数。您应该尽可能使用send()方法,并且仅在向单个设备或设备组发送消息时使用本页中描述的方法。

发送到单个设备

您可以将注册令牌传递给sendToDevice()方法以向该设备发送消息:

节点.js

// This registration token comes from the client FCM SDKs.
const registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';

// See the "Defining the message payload" section below for details
// on how to define a message payload.
const payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

// Send a message to the device corresponding to the provided
// registration token.
getMessaging().sendToDevice(registrationToken, payload)
  .then((response) => {
    // See the MessagingDevicesResponse reference documentation for
    // the contents of response.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

sendToDevice()方法还可以通过传递注册令牌数组而不是单个注册令牌来发送多播消息(即,向多个设备发送消息):

节点.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...',
  // ...
  'ecupwIfBy1w:APA91bFtuMY7MktgxA3Au_Qx7cKqnf...'
];

// See the "Defining the message payload" section below for details
// on how to define a message payload.
const payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

// Send a message to the devices corresponding to the provided
// registration tokens.
getMessaging().sendToDevice(registrationTokens, payload)
  .then((response) => {
    // See the MessagingDevicesResponse reference documentation for
    // the contents of response.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

sendToDevice()方法返回一个由包含来自 FCM 的响应的MessagingDevicesResponse对象解析的承诺。传递单个注册令牌或注册令牌数组时,返回类型具有相同的格式。

某些情况(例如身份验证错误或速率限制)会导致整个消息无法处理。在这些情况下, sendToDevice()返回的承诺被拒绝并出现错误。有关错误代码的完整列表,包括说明和解决步骤,请参阅Admin FCM API Errors

发送到设备组

设备组消息允许您将多个设备添加到单个组。这类似于主题消息传递,但包括身份验证以确保组成员身份仅由您的服务器管理。例如,如果您想向不同的手机型号发送不同的消息,您的服务器可以将注册添加/删除到适当的组,并将适当的消息发送到每个组。设备组消息与主题消息的不同之处在于它涉及从您的服务器而不是直接在您的应用程序中管理设备组。

您可以通过应用服务器上的旧XMPPHTTP协议使用设备组消息传递。适用于 Node.js 的旧版 Firebase Admin SDK基于旧协议,还提供设备群组消息传递功能。通知键允许的最大成员数为 20。

您可以通过应用服务器或 Android 客户端创建设备组并生成通知密钥。有关详细信息,请参阅管理设备组

sendToDeviceGroup()方法允许您通过指定设备组的通知键向设备组发送消息:

节点.js

// See the "Managing device groups" link above on how to generate a
// notification key.
const notificationKey = 'some-notification-key';

// See the "Defining the message payload" section below for details
// on how to define a message payload.
const payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

// Send a message to the device group corresponding to the provided
// notification key.
getMessaging().sendToDeviceGroup(notificationKey, payload)
  .then((response) => {
    // See the MessagingDeviceGroupResponse reference documentation for
    // the contents of response.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

sendToDeviceGroup()方法返回一个由包含来自 FCM 的响应的MessagingDevicesResponse对象解析的承诺。

某些情况(例如身份验证错误或速率限制)会导致整个消息无法处理。在这些情况下, sendToDeviceGroup()返回的承诺被拒绝并出现错误。有关错误代码的完整列表,包括说明和解决步骤,请参阅Admin FCM API Errors

定义消息负载

上述基于 FCM 遗留协议的方法接受消息负载作为其第二个参数,并支持通知和数据消息。您可以通过使用data和/或notification键创建对象来指定一种或两种消息类型。例如,这里是如何定义不同类型的消息负载:

通知消息

const payload = {
  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.'
  }
};

数据信息

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

组合消息

const payload = {
  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.'
  },
  data: {
    stock: 'GOOG',
    open: '829.62',
    close: '635.67'
  }
};

通知消息有效负载具有预定义的有效属性子集,并且根据您所针对的移动操作系统而略有不同。有关完整列表,请参阅NotificationMessagePayload的参考文档。

数据消息有效负载由具有一些限制的自定义键值对组成,包括所有值都必须是字符串这一事实。有关限制的完整列表,请参阅DataMessagePayload的参考文档。

定义消息选项

上述基于 FCM 遗留协议的方法接受可选的第三个参数,指定消息的一些选项。例如,以下示例将高优先级消息发送到 24 小时后过期的设备:

节点.js

// This registration token comes from the client FCM SDKs.
const registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';

// See the "Defining the message payload" section above for details
// on how to define a message payload.
const payload = {
  notification: {
    title: 'Urgent action needed!',
    body: 'Urgent action is needed to prevent your account from being disabled!'
  }
};

// Set the message as high priority and have it expire after 24 hours.
const options = {
  priority: 'high',
  timeToLive: 60 * 60 * 24
};

// Send a message to the device corresponding to the provided
// registration token with the provided options.
getMessaging().sendToDevice(registrationToken, payload, options)
  .then((response) => {
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

有关可用选项的完整列表,请参阅MessagingOptions的参考文档。