Join us in person and online for Firebase Summit on October 18, 2022. Learn how Firebase can help you accelerate app development, release your app with confidence, and scale with ease. Register now

構建應用服務器發送請求

透過集合功能整理內容 你可以依據偏好儲存及分類內容。

使用 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
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

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

將請求保存到文件中(在此示例中為 batch_request.txt)。然後使用 cURL 命令:

curl --data-binary @batch_request.txt -H 'Content-Type: multipart/mixed; boundary="subrequest_boundary"' 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
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

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
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

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的參考文檔。