建立應用程式伺服器發送請求

使用 Firebase Admin SDK 或 FCM 應用程式伺服器協議,您可以建立訊息請求並將其發送到以下類型的目標:

  • 主題名稱
  • 狀態
  • 設備註冊令牌
  • 設備群組名稱(僅限協定)

您可以傳送帶有由預先定義欄位組成的通知負載、您自己的使用者定義欄位的資料負載或包含兩種類型負載的訊息的訊息。有關詳細信息,請參閱訊息類型

本頁中的範例展示如何使用 Firebase Admin SDK(支援NodeJavaPythonC#Go )和v1 HTTP 協定發送通知訊息。還有透過已棄用的舊版 HTTP 和 XMPP協定發送訊息的指南。

向特定裝置發送訊息

若要傳送到單一特定設備,請傳遞設備的註冊令牌,如圖所示。請參閱您的平台的客戶端設定信息,以了解有關註冊令牌的更多資訊。

Node.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"
    }

向多個裝置發送訊息

管理 FCM API 允許您將訊息多播到裝置註冊令牌清單。每次呼叫最多可以指定 500 個設備註冊令牌。

Node.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.SendEachForMulticastAsync(message);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

傳回值是與輸入標記的順序相對應的標記清單。當您想要檢查哪些令牌導致錯誤時,這非常有用。

Node.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.SendEachForMulticastAsync(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}");
}

向主題發送訊息

建立主題後,您可以透過在客戶端訂閱該主題的客戶端應用程式實例或透過伺服器 API向該主題發送訊息。如果這是您第一次建置 FCM 的傳送請求,請參閱伺服器環境和 FCM指南以取得重要的背景和設定資訊。

在後端的發送邏輯中,指定所需的主題名稱,如下所示:

Node.js

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

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

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

爪哇

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

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

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

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

若要將訊息傳送到主題組合,請指定條件,它是指定目標主題的布林表達式。例如,以下條件將向訂閱TopicA以及TopicBTopicC的裝置發送訊息:

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

FCM 首先計算括號中的任何條件,然後從左到右計算表達式。在上面的表達式中,訂閱任何單一主題的用戶都不會收到訊息。同樣,未訂閱TopicA用戶也不會收到該訊息。這些組合確實收到了它:

  • TopicATopicB
  • TopicATopicC

您最多可以在條件表達式中包含五個主題。

發送到條件:

Node.js

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

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

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

爪哇

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

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

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

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

向設備群組發送訊息

若要將訊息傳送到裝置群組,請使用 HTTP v1 API。如果您目前使用已棄用的 HTTP 或 XMPP 舊版發送 API 或任何基於舊版協定的適用於Node.js 的 Firebase 管理 SDK向設備群組發送數據,我們強烈建議您遷移到 HTTP v1儘早提供 API 。舊版發送 API 將於 2024 年 6 月停用並刪除。

向裝置群組發送訊息與向單一裝置發送訊息非常相似,使用相同的方法來授權發送請求。將token欄位設定為群組通知鍵:

休息

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":"APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ",
      "data":{
        "hello": "This is a Firebase Cloud Messaging device group message!"
      }
   }
}

捲曲命令

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message":{
   "data":{
     "hello": "This is a Firebase Cloud Messaging device group message!"
   },
   "token":"APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ"
}}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send

發送一批訊息

Admin SDK 支援批次發送訊息。您可以將最多 500 個訊息分組為一個批次,並在一次 API 呼叫中將它們全部發送,與為每個訊息發送單獨的 HTTP 請求相比,效能顯著提高。

此功能可用於建立自訂訊息集並將其傳送給不同的收件人,包括主題或特定裝置註冊令牌。例如,當您需要同時向不同受眾發送郵件且郵件正文中的詳細資訊略有不同時,請使用此功能。

Node.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.SendEachAsync(messages);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

發送直接啟動訊息(僅限 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 應用程式本地的可繪製圖示資源。

以下是使用者裝置上視覺效果的近似值:

兩個設備的簡單繪圖,其中一個顯示自訂圖示和顏色

Node.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 參考文件

範例:帶有自訂圖像的通知訊息

以下範例發送請求向所有平台發送通用通知標題,但它還發送圖像。以下是使用者裝置上視覺效果的近似值:

在顯示通知中簡單繪製圖像

Node.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 參考文件

範例:帶有關聯點擊操作的通知訊息

以下範例發送請求向所有平台發送通用通知標題,但它還發送一個操作供應用程式執行,以回應使用者與通知的互動。以下是使用者裝置上視覺效果的近似值:

使用者點擊開啟網頁的簡單繪圖

Node.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 參考文件

範例:帶有本地化選項的通知訊息

以下範例發送請求傳送本地化選項供用戶端顯示本地化訊息。以下是使用者裝置上視覺效果的近似值:

顯示英語和西班牙語文字的兩個裝置的簡單繪圖

Node.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 參考文件

HTTP v1 API 的 REST 錯誤代碼

HTTP v1 API 的 HTTP 錯誤回應包含錯誤代碼、錯誤訊息和錯誤狀態。它們還可能包含一個details數組,其中包含有關錯誤的更多詳細資訊。

以下是兩個錯誤回應範例:

範例 1:來自 HTTP v1 API 請求的錯誤回應,資料訊息中的值無效

{
  "error": {
    "code": 400,
    "message": "Invalid value at 'message.data[0].value' (TYPE_STRING), 12",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "message.data[0].value",
            "description": "Invalid value at 'message.data[0].value' (TYPE_STRING), 12"
          }
        ]
      }
    ]
  }
}

範例 2:來自帶有無效註冊令牌的 HTTP v1 API 請求的錯誤回應

{
  "error": {
    "code": 400,
    "message": "The registration token is not a valid FCM registration token",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "INVALID_ARGUMENT"
      }
    ]
   }
}

請注意,兩個訊息具有相同的代碼和狀態,但詳細資料陣列包含不同類型的值。第一個範例的類型為type.googleapis.com/google.rpc.BadRequest ,指示請求值中存在錯誤。類型為type.googleapis.com/google.firebase.fcm.v1.FcmError的第二個範例具有 FCM 特定錯誤。對於許多錯誤,詳細資訊數組包含偵錯和查找解決方案所需的資訊。

下表列出了 FCM v1 REST API 錯誤代碼及其描述。

錯誤代碼描述和解決步驟
UNSPECIFIED_ERROR沒有關於此錯誤的更多資訊。沒有任何。
INVALID_ARGUMENT (HTTP 錯誤代碼 = 400)請求參數無效。傳回google.rpc.BadRequest類型的擴充以指定哪個欄位無效。可能的原因包括無效註冊、無效包名稱、訊息太大、無效資料金鑰、無效 TTL 或其他無效參數。
無效註冊:檢查您傳遞給伺服器的註冊令牌的格式。確保它與客戶端應用程式透過 FCM 註冊收到的註冊令牌相符。不要截斷標記或添加其他字元。
包名稱無效:確保訊息傳送至註冊令牌,其包名稱與請求中傳遞的值相符。
訊息太大:檢查訊息中包含的有效負載資料的總大小是否超過 FCM 限制:大多數訊息為 4096 字節,對於主題訊息為 2048 位元組。這包括鍵和值。
資料金鑰無效:檢查負載資料是否不包含 FCM 內部使用的金鑰(例如 from、gcm 或任何以 google 為前綴的值)。請注意,FCM 也使用某些單字(例如collapse_key),但在有效負載中允許使用,在這種情況下,有效負載值將被 FCM 值覆蓋。
無效 TTL :檢查 ttl 中使用的值是否為表示 0 到 2,419,200(4 週)之間的秒數持續時間的整數。
無效參數:檢查提供的參數是否具有正確的名稱和類型。
UNREGISTERED (HTTP 錯誤代碼 = 404) 應用程式實例已從 FCM 取消註冊。這通常意味著所使用的令牌不再有效,必須使用新的令牌。此錯誤可能是由於缺少註冊令牌或未註冊令牌引起的。
缺少註冊:如果訊息的目標是token值,請檢查請求是否包含註冊令牌。
未註冊:現有註冊令牌可能在多種情況下不再有效,包括:
- 如果用戶端應用程式向 FCM 取消註冊。
- 如果客戶端應用程式自動註銷,如果用戶卸載應用程序,就會發生這種情況。例如,在 iOS 上,如果 APNs 回饋服務將 APNs 令牌報告為無效。
- 如果註冊令牌過期(例如,Google 可能決定刷新註冊令牌,或 iOS 裝置的 APNs 令牌已過期)。
- 如果客戶端應用程式已更新,但新版本未配置為接收訊息。
對於所有這些情況,請從應用程式伺服器中刪除此註冊令牌並停止使用它發送訊息。
SENDER_ID_MISMATCH (HTTP 錯誤代碼 = 403) 經過驗證的寄件者 ID 與註冊令牌的寄件者 ID 不同。註冊令牌與特定的發送者群組相關聯。當客戶端應用程式註冊 FCM 時,它必須指定允許哪些寄件者傳送訊息。向客戶端應用程式發送訊息時,您應該使用這些寄件者 ID 之一。如果您切換到其他寄件人,現有的註冊令牌將無法運作。
QUOTA_EXCEEDED (HTTP 錯誤代碼 = 429)超出訊息目標的傳送限制。傳回google.rpc.QuotaFailure類型的擴充功能以指定超出了哪個配額。此錯誤可能是由於超出訊息速率配額、超出裝置訊息速率配額或超出主題訊息速率配額而導致。
訊息速率超出:訊息發送速率過高。您必須降低發送訊息的整體速率。使用指數退避和最小初始延遲 1 分鐘來重試被拒絕的訊息。
超出裝置訊息速率:傳送至特定裝置的訊息速率過高。請參閱單一裝置的訊息速率限制。減少發送到該裝置的訊息數量並使用指數退避來重試發送。
超出主題訊息速率:向特定主題的訂閱者發送訊息的速率過高。減少為此主題發送的訊息數量,並使用指數退避和最小初始延遲 1 分鐘來重試發送。
UNAVAILABLE (HTTP 錯誤代碼 = 503) 伺服器過載。伺服器無法及時處理請求。重試相同的請求,但您必須:
- 如果 Retry-After 標頭包含在 FCM 連線伺服器的回應中,則遵守該標頭。
- 在重試機制中實施指數退避。 (例如,如果您在第一次重試之前等待一秒,則在下一次重試之前至少等待兩秒,然後等待 4 秒,依此類推)。如果您要傳送多個訊息,請考慮套用抖動。有關更多信息,請參閱處理重試。造成問題的寄件者可能會被列入拒絕名單。
INTERNAL (HTTP 錯誤代碼 = 500) 發生未知內部錯誤。伺服器在嘗試處理請求時遇到錯誤。您可以按照處理重試中的建議重試相同的請求。如果錯誤仍然存在,請聯絡 Firebase 支援。
THIRD_PARTY_AUTH_ERROR (HTTP 錯誤代碼 = 401)APN 憑證或 Web 推送驗證金鑰無效或遺失。無法傳送針對 iOS 裝置或 Web 推播註冊的訊息。檢查您的開發和生產憑證的有效性。

管理錯誤代碼

下表列出了 Firebase 管理 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 Cloud Messaging 主題發送訊息與向單一裝置或使用者群組發送訊息非常相似。應用程式伺服器將to鍵設定為/topics/yourTopic之類的值。開發者可以選擇任何與正規表示式相符的主題名稱: "/topics/[a-zA-Z0-9-_.~%]+"

若要傳送到多個主題的組合,應用程式伺服器必須將condition鍵(而不是to鍵)設定為指定目標主題的布林條件。例如,要將訊息傳送到訂閱TopicA以及TopicBTopicC的裝置:

'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 秒的延遲。確保在請求中相應地設定應用程式伺服器的逾時值。

向設備群組發送訊息

使用已棄用的舊版 API 向裝置群組發送訊息與向單一裝置發送訊息非常相似。將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 管理 Node.js SDK 支援基於舊版 FCM 伺服器 API傳送 (FCM) 訊息的方法。與send()方法相比,這些方法接受不同的參數。您應盡可能使用send()方法,並且僅在向單一裝置或裝置群組傳送訊息時使用本頁中所述的方法。

發送到各個設備

您可以將註冊令牌傳遞給sendToDevice()方法以向該設備發送訊息:

Node.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()方法還可以透過傳遞註冊令牌數組而不是僅傳遞單一註冊令牌來發送多播訊息(即,向多個裝置發送訊息):

Node.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()傳回的 Promise 會被拒絕並出現錯誤。有關錯誤代碼的完整清單(包括說明和解決步驟),請參閱管理 FCM API 錯誤

傳送到設備組

sendToDeviceGroup()方法可讓您透過指定設備群組的通知鍵來傳送訊息給該裝置群組:

Node.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()傳回的 Promise 會被拒絕並出現錯誤。有關錯誤代碼的完整清單(包括說明和解決步驟),請參閱管理 FCM API 錯誤

定義訊息負載

上述基於 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 小時後過期:

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