פיתוח בקשות לשליחה בשרת האפליקציה

באמצעות הפרוטוקולים של שרת האפליקציות Firebase Admin SDK או FCM, אפשר ליצור בקשות להעברת הודעות ולשלוח אותן ליעדים מהסוגים הבאים:

  • שם הנושא
  • תנאי
  • טוקן לרישום מכשיר
  • שם קבוצת המכשירים (פרוטוקול בלבד)

אפשר לשלוח הודעות עם עומס נתונים של התראה שמורכב משדות מוגדרים מראש, עומס נתונים של שדות מוגדרים על ידי המשתמש או הודעה שמכילה את שני סוגי עומסי הנתונים. למידע נוסף, ראו סוגי הודעות.

בדוגמאות בדף הזה מוסבר איך לשלוח הודעות התראה באמצעות Firebase Admin SDK (עם תמיכה ב-Node, ב-Java, ב-Python, ב-C# וב-Go) ופרוטוקול HTTP בגרסה 1. יש גם הנחיות לשליחת הודעות באמצעות פרוטוקולים קודמים של 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);
  });

Java

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

Go

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

REST

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:

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

אם הפעולה מסתיימת ללא שגיאות, כל שיטת שליחה מחזירה מזהה הודעה. הפונקציה Firebase Admin SDK מחזירה את מחרוזת המזהה בפורמט projects/{project_id}/messages/{message_id}. תגובת פרוטוקול ה-HTTP היא מפתח JSON יחיד:

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

שליחת הודעות למספר מכשירים

ממשקי ה-API של האדמין FCM מאפשרים לשלוח הודעה ברשת ה-Multicast לרשימה של אסימוני רישום של מכשירים. אפשר לציין עד 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');
  });

Java

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

Go

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

Java

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

Go

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

Java

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

Go

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

REST

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

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

פקודת cURL:

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

כדי לשלוח הודעה לשילוב של נושאים, צריך לציין תנאי, שהוא ביטוי בוליאני שמציין את נושאי היעד. לדוגמה, התנאי הבא ישלח הודעות למכשירים שנרשמו ל-TopicA ול-TopicB או ל-TopicC:

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

הפונקציה FCM מחשבת קודם את כל התנאים בסוגריים, ואז מחשבת את הביטוי מימין לשמאל. בביטוי שלמעלה, משתמש שנרשם לכל נושא בנפרד לא יקבל את ההודעה. באופן דומה, משתמש שלא נרשם ל-TopicA לא יקבל את ההודעה. השילובים הבאים מקבלים אותו:

  • TopicA וגם TopicB
  • TopicA וגם TopicC

אפשר לכלול עד חמישה נושאים בביטוי המותנה.

כדי לשלוח לתנאי:

Node.js

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
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);
  });

Java

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

Go

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

REST

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

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

פקודת cURL:

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

שליחת הודעות לקבוצות של מכשירים

כדי לשלוח הודעות לקבוצות של מכשירים, משתמשים ב-HTTP v1 API. אם אתם שולחים כרגע לקבוצות של מכשירים באמצעות ממשקי ה-API הקודמים של HTTP או XMPP, או באמצעות אחת מהגרסאות הקודמות של Firebase Admin SDK ל-Node.js שמבוססות על הפרוטוקולים הקודמים, מומלץ מאוד לעבור ל-HTTP v1 API בהקדם האפשרי. ממשקי ה-API הקודמים לשליחה יושבתו ויוסרו ביוני 2024.

שליחת הודעות לקבוצת מכשירים דומה מאוד לשליחת הודעות למכשיר ספציפי, וניתן להשתמש באותה שיטה כדי להעניק הרשאה לבקשות שליחה. מגדירים את השדה token למפתח ההתראות הקבוצתי:

REST

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

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

שליחת קבוצה של הודעות

ערכות ה-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');
  });

Java

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

Go

// 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 או ממשקי ה-API הקודמים של HTTP. לפני ששולחים הודעות למכשירים במצב הפעלה ישיר, צריך לוודא שהשלמתם את השלבים להפעלת מכשירי הלקוח כדי לקבל הודעות FCM במצב הפעלה ישיר.

שליחה באמצעות FCM v1 HTTP API

בקשת ההודעה חייבת לכלול את המפתח "direct_boot_ok" : true באפשרויות AndroidConfig של גוף הבקשה. לדוגמה:

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 API הקודם ל-HTTP

בקשת ההודעה חייבת לכלול את המפתח "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 וגם פרוטוקול ה-HTTP של FCM v1 מאפשרים להגדיר את כל השדות הזמינים באובייקט message בבקשות להעברת הודעות. אפשר לצלם:

  • קבוצה משותפת של שדות שכל המופעים של האפליקציה שמקבלים את ההודעה צריכים לפרש.
  • קבוצות של שדות ספציפיות לפלטפורמה, כמו AndroidConfig ו-WebpushConfig, שמתפרשות רק על ידי מכונות של אפליקציות שפועלות בפלטפורמה שצוינה.

באמצעות חסימה ספציפית לפלטפורמה, תוכלו להתאים אישית הודעות לפלטפורמות שונות כדי לוודא שהן יטופלו כראוי כשהן יתקבלו. הקצה העורפי של FCM יביא בחשבון את כל הפרמטרים שצוינו ויתאים אישית את ההודעה לכל פלטפורמה.

מתי כדאי להשתמש בשדות נפוצים

כדאי להשתמש בשדות נפוצים במקרים הבאים:

  • טירגוט למופעים של האפליקציה בכל הפלטפורמות – Apple,‏ Android והאינטרנט
  • שליחת הודעות לנושאים

כל המופעים של האפליקציה, ללא קשר לפלטפורמה, יכולים לפרש את השדות הנפוצים הבאים:

מתי כדאי להשתמש בשדות ספציפיים לפלטפורמה

כדאי להשתמש בשדות ספציפיים לפלטפורמה במקרים הבאים:

  • שליחת שדות רק לפלטפורמות מסוימות
  • שליחת שדות ספציפיים לפלטפורמה בנוסף לשדות הנפוצים

אם אתם רוצים לשלוח ערכים רק לפלטפורמות מסוימות, אל תשתמשו בשדות נפוצים, אלא בשדות ספציפיים לפלטפורמה. לדוגמה, כדי לשלוח התראה רק לפלטפורמות של Apple ולאינטרנט, אבל לא ל-Android, צריך להשתמש בשתי קבוצות נפרדות של שדות, אחת ל-Apple ואחת לאינטרנט.

כששולחים הודעות עם אפשרויות שליחה ספציפיות, צריך להשתמש בשדות ספציפיים לפלטפורמה כדי להגדיר אותן. אם רוצים, אפשר לציין ערכים שונים לכל פלטפורמה. עם זאת, גם אם רוצים להגדיר ערך זהה במהותו בפלטפורמות שונות, צריך להשתמש בשדות ספציפיים לפלטפורמה. הסיבה לכך היא שכל פלטפורמה יכולה לפרש את הערך בצורה שונה במקצת. לדוגמה, משך החיים מוגדר ב-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);
  });

Java

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',
)

Go

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",
};

REST

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

REST

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

REST

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

REST

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 מפורטים כל המפתחות שזמינים בבלוק ספציפי לפלטפורמה בגוף ההודעה.

קודי שגיאה ב-REST ל-API v1 של HTTP

תגובות שגיאה של HTTP ב-API v1 של HTTP מכילות קוד שגיאה, הודעת שגיאה וסטטוס שגיאה. הן עשויות להכיל גם מערך details עם פרטים נוספים על השגיאה.

לפניכם שתי תגובות לדוגמה לשגיאות:

דוגמה 1: תגובת שגיאה מבקשת API של HTTP v1 עם ערך לא חוקי בהודעת נתונים

{
  "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: תגובת שגיאה מבקשת API של HTTP v1 עם אסימון רישום לא חוקי

{
  "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. בהרבה מהשגיאות, מערך הפרטים מכיל את המידע הדרוש לניפוי באגים ולפתרון הבעיה.

בטבלה הבאה מפורטים קודי השגיאה של ה-API ל-REST של FCM v1 והתיאורים שלהם.

קוד שגיאה תיאור ושלבי פתרון
UNSPECIFIED_ERROR אין מידע נוסף על השגיאה הזו. אין.
INVALID_ARGUMENT (קוד שגיאת HTTP = 400) פרמטרים של הבקשה לא תקינים. תוחזר תוספת מסוג google.rpc.BadRequest כדי לציין איזה שדה לא תקין. בין הסיבות האפשריות: רישום לא תקין, שם חבילת נתונים לא תקין, הודעה גדולה מדי, מפתח נתונים לא תקין, TTL לא תקין או פרמטרים לא תקינים אחרים.
רישום לא חוקי: בודקים את הפורמט של אסימון הרישום שמעבירים לשרת. חשוב לוודא שהוא תואם לאסימון הרישום שאפליקציית הלקוח מקבלת מהרישום ב-FCM. אין לקצר את האסימון או להוסיף תווים נוספים.
שם החבילה לא חוקי: צריך לוודא שההודעה נשלחה לאסימון רישום ששם החבילה שלו תואם לערך שהוענק בבקשה.
ההודעה גדולה מדי: צריך לוודא שהגודל הכולל של נתוני המטען הייעודי (payload) שכלולים בהודעה לא חורג מהמגבלות של FCM: 4096 בייטים ברוב ההודעות, או 2048 בייטים במקרה של הודעות לנושאים. הנתון הזה כולל גם את המפתחות וגם את הערכים.
מפתח נתונים לא חוקי: צריך לוודא שנתוני המטען הייעודי לא מכילים מפתח (כמו from או gcm או כל ערך עם הקידומת google) ש-FCM משתמש בו באופן פנימי. הערה: מילים מסוימות (כמו collapse_key) משמשות גם את FCM, אבל הן מותרות בתוכן המועמס. במקרה כזה, הערך של תוכן המועמס יוחלף בערך של FCM.
משך זמן ל-TTL לא תקין: צריך לוודא שהערך שצוין ב-ttl הוא מספר שלם שמייצג משך זמן בשניות בין 0 ל-2,419,200 (4 שבועות).
פרמטרים לא חוקיים: צריך לבדוק שהפרמטרים שסופקו הם מהסוג והשם הנכונים.
UNREGISTERED (קוד שגיאה HTTP = 404) מופע האפליקציה לא נרשם ב-FCM. בדרך כלל המשמעות היא שהאסימון שבו נעשה שימוש כבר לא תקף, וצריך להשתמש באסימון חדש. השגיאה הזו יכולה להיגרם מטוקני רישום חסרים או מטוקנים לא רשומים.
Registration חסר: אם היעד של ההודעה הוא ערך token, צריך לבדוק שהבקשה מכילה אסימון רישום.
לא רשום: אסימון רישום קיים עשוי להפסיק להיות תקף במספר תרחישים, כולל:
- אם אפליקציית הלקוח מבטלת את הרישום ב-FCM.
- אם אפליקציית הלקוח לא רשומה באופן אוטומטי, מה שעלול לקרות אם המשתמש מסיר את האפליקציה. לדוגמה, ב-iOS, אם שירות המשוב של APNs דיווח שהאסימון של APNs לא תקין.
‎- אם פג התוקף של אסימון הרישום (לדוגמה, Google עשויה להחליט לרענן את אסימוני הרישום, או שתוקף האסימון של APNs פג במכשירי iOS).
- אם אפליקציית הלקוח עודכנה אבל הגרסה החדשה לא מוגדרת לקבלת הודעות.
בכל המקרים האלה, צריך להסיר את אסימון הרישום הזה משרת האפליקציה ולהפסיק להשתמש בו כדי לשלוח הודעות.
SENDER_ID_MISMATCH (קוד שגיאת HTTP = 403) מזהה השולח המאומת שונה ממזהה השולח של אסימון הרישום. אסימון רישום מקושר לקבוצה מסוימת של שולחים. כשאפליקציית לקוח נרשמת ל-FCM, היא צריכה לציין אילו שולחים מורשים לשלוח הודעות. צריך להשתמש באחד ממזהי השולח האלה כששולחים הודעות לאפליקציית הלקוח. אם עוברים לשולח אחר, אסימוני ההרשמה הקיימים לא יפעלו.
QUOTA_EXCEEDED (קוד שגיאת HTTP = 429) חרגת ממגבלת השליחה של היעד של ההודעה. המערכת מחזירה תוסף מסוג google.rpc.QuotaFailure כדי לציין את המכסה שעברה את המגבלה. השגיאה הזו יכולה להיגרם בגלל חרגה ממכסת קצב שליחת ההודעות, חרגה ממכסת קצב שליחת ההודעות במכשיר או חרגה ממכסת קצב שליחת ההודעות בנושא.
חריגה מקצב שליחת ההודעות: קצב שליחת ההודעות גבוה מדי. עליכם להפחית את הקצב הכולל שבו אתם שולחים הודעות. שימוש בהשהיה מעריכית לפני ניסיון חוזר (exponential backoff) עם עיכוב ראשוני מינימלי של דקה אחת כדי לנסות שוב לשלוח הודעות שנדחו.
חריגה משיעור ההודעות למכשיר: שיעור ההודעות למכשיר מסוים גבוה מדי. מגבלת קצב שליחת ההודעות למכשיר אחד כדאי לצמצם את מספר ההודעות שנשלחות למכשיר הזה ולהשתמש בהשהיה מעריכית לפני ניסיון חוזר כדי לנסות לשלוח שוב.
חריגה מהשיעור של הודעות בנושא: שיעור ההודעות שנשלחות למנויים בנושא מסוים גבוה מדי. כדאי להפחית את מספר ההודעות שנשלחות בנושא הזה ולהשתמש בהשהיה מעריכית לפני ניסיון חוזר (exponential backoff) עם עיכוב ראשוני מינימלי של דקה אחת כדי לנסות שוב לשלוח את ההודעה.
UNAVAILABLE (קוד שגיאת HTTP = 503) השרת עמוס. השרת לא הצליח לעבד את הבקשה בזמן. מנסים שוב את אותה בקשה, אבל צריך:
- לפעול לפי הכותרת Retry-After אם היא כלולה בתגובה משרת החיבור של FCM.
- הטמעת השהיה מעריכית לפני ניסיון חוזר (exponential backoff) במנגנון הניסיונות החוזרים. (לדוגמה, אם המתינו שנייה אחת לפני הניסיון הראשון, צריך להמתין לפחות שתי שניות לפני הניסיון הבא, ואז 4 שניות וכן הלאה). אם אתם שולחים כמה הודעות, מומלץ להשתמש בתנודות. מידע נוסף זמין במאמר טיפול בניסיונות חוזרים. שולחים שגורמים לבעיות עלולים להיכלל ברשימת ההחרגות.
INTERNAL (קוד שגיאת HTTP = 500) אירעה שגיאה פנימית לא ידועה. השרת נתקל בשגיאה במהלך הניסיון לעבד את הבקשה. אפשר לנסות שוב את אותה בקשה לפי ההצעות במאמר טיפול בניסיונות חוזרים. אם השגיאה נמשכת, יש לפנות לתמיכה של Firebase.
THIRD_PARTY_AUTH_ERROR (קוד שגיאת HTTP = 401) האישור של APNs או מפתח האימות של דחיפה לאינטרנט לא תקינים או חסרים. לא ניתן היה לשלוח הודעה שמטורגטת למכשיר iOS או הרשמה לקבלת התראות דחיפה באינטרנט. בודקים את התקינות של פרטי הכניסה לפיתוח ולייצור.

קודי שגיאה של אדמין

בטבלה הבאה מפורטים קודי השגיאה של FCM API לניהול ב-Firebase והתיאורים שלהם, כולל שלבים מומלצים לפתרון.

קוד שגיאה תיאור ושלבי פתרון
messaging/invalid-argument סופק ארגומנט לא חוקי לשיטה FCM. הודעת השגיאה אמורה לכלול מידע נוסף.
messaging/invalid-recipient הנמען המיועד של ההודעה לא תקין. הודעת השגיאה אמורה לכלול מידע נוסף.
messaging/invalid-payload אובייקט לא חוקי של עומס נתונים של הודעה סופק. הודעת השגיאה אמורה לכלול מידע נוסף.
messaging/invalid-data-payload-key מטען הנתונים של הודעת הנתונים מכיל מפתח לא חוקי. למידע נוסף על מפתחות מוגבלים, ראו את מאמרי העזרה של DataMessagePayload.
messaging/payload-size-limit-exceeded עומס העבודה של ההודעה שצוין חורג ממגבלות הגודל של FCM. המגבלה היא 4,096 בייטים ברוב ההודעות. מגבלת הגודל של הודעות שנשלחות לנושאים היא 2,048 בייטים. גודל המטען הכולל כולל גם מפתחות וגם ערכים.
messaging/invalid-options אובייקט לא חוקי של אפשרויות שליחת הודעות סופק. הודעת השגיאה אמורה לכלול מידע נוסף.
messaging/invalid-registration-token טוקן הרישום שסופק לא תקין. מוודאים שהוא תואם לאסימון הרישום שאפליקציית הלקוח מקבלת מהרישום ב-FCM. אין לקצר אותו או להוסיף לו תווים נוספים.
messaging/registration-token-not-registered טוקן הרישום שסופק לא רשום. יש מגוון סיבות לכך שאפשר לבטל את הרישום של טוקן רישום שתקף בעבר, כולל:
  • אפליקציית הלקוח ביטלה את הרישום שלה ב-FCM.
  • אפליקציית הלקוח נמחקה באופן אוטומטי. המצב הזה יכול לקרות אם המשתמש מסיר את האפליקציה, או בפלטפורמות של Apple, אם שירות המשוב של APNs דיווח על אסימון APNs לא תקין.
  • פג התוקף של טוקן הרישום. לדוגמה, Google עשויה לחדש את אסימוני הרישום, או שפג התוקף של אסימון APNs במכשירי Apple.
  • אפליקציית הלקוח עודכנה, אבל הגרסה החדשה לא מוגדרת לקבל הודעות.
בכל המקרים האלה, צריך להסיר את טוקן הרישום הזה ולהפסיק להשתמש בו כדי לשלוח הודעות.
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 כי אישור ה-SSL הנדרש של APNs לא הועלה או שתוקפו פג. בודקים את התוקף של אישורי הפיתוח והייצור.
messaging/mismatched-credential לפרטי הכניסה ששימשו לאימות ה-SDK הזה אין הרשאה לשלוח הודעות למכשיר התואם לטוקן ההרשמה שסופק. חשוב לוודא שהפרטים האישיים והאסימון לרישום שייכים לאותו פרויקט ב-Firebase. במאמר הוספת Firebase לאפליקציה מוסבר איך מבצעים אימות של הערכים ב-Firebase Admin SDK.
messaging/authentication-error לא ניתן היה לבצע אימות של ה-SDK בשרתים של FCM. חשוב לוודא שאתם מאמתים את Firebase Admin SDK באמצעות פרטי כניסה שיש להם את ההרשאות המתאימות לשליחת הודעות FCM. במאמר הוספת Firebase לאפליקציה מוסבר איך מבצעים אימות של הערכים ב-Firebase Admin SDK.
messaging/server-unavailable שרת FCM לא הצליח לעבד את הבקשה בזמן. כדאי לנסות שוב את אותה בקשה, אבל צריך:
  • מכבדים את הכותרת Retry-After אם היא כלולה בתגובה מ-FCM Connection Server.
  • מטמיעים השהיה מעריכית לפני ניסיון חוזר (exponential backoff) במנגנון הניסיון החוזר. לדוגמה, אם המתינו שנייה אחת לפני הניסיון הראשון, צריך להמתין לפחות שתיים לפני הניסיון הבא, ואז ארבע שניות, וכן הלאה. אם שולחים כמה הודעות, כדאי לעכב כל אחת מהן בנפרד בזמן אקראי נוסף כדי להימנע משליחת בקשה חדשה לכל ההודעות באותו זמן.
שולחים שגורמים לבעיות עלולים להיכלל ברשימת ההסרה.
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 מספק כמה אפשרויות אחרות לתשובות. פורמט התגובה מהשרת

הרשימה המלאה של אפשרויות ההודעות שזמינות כששולחים הודעות במורד הזרם לאפליקציות לקוח מפורטת במסמכי העזרה של פרוטוקול שרת החיבור שבחרתם, HTTP או XMPP.

שליחת הודעות לנושאים

שליחת הודעות לנושא Firebase Cloud Messaging דומה מאוד לשליחת הודעות למכשיר ספציפי או לקבוצת משתמשים. שרת האפליקציה מגדיר את המפתח to עם ערך כמו /topics/yourTopic. מפתחים יכולים לבחור כל שם נושא שתואם לביטוי הרגולרי: "/topics/[a-zA-Z0-9-_.~%]+".

כדי לשלוח לשילובים של כמה נושאים, שרת האפליקציה צריך להגדיר את המפתח condition (במקום את המפתח to) לתנאי בוליאני שמציין את נושאי היעד. לדוגמה, כדי לשלוח הודעות למכשירים שנרשמו ל-TopicA ול-TopicB או ל-TopicC:

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

הפונקציה FCM מחשבת קודם את כל התנאים בסוגריים, ואז מחשבת את הביטוי מימין לשמאל. בביטוי שלמעלה, משתמש שנרשם לנושא יחיד לא יקבל את ההודעה. באופן דומה, משתמש שלא נרשם לנושא א' לא יקבל את ההודעה. השילובים הבאים מקבלים אותו:

  • TopicA ו-TopicB
  • TopicA ו-TopicC

אפשר לכלול עד חמישה נושאים בביטוי המותנה, ואפשר להשתמש בסוגריים. האופרטורים הנתמכים: &&, ‏ ||.

בקשת 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"
}

צפוי עיכוב של עד 30 שניות לפני שהשרת FCM ישיב על בקשות השליחה של הנושאים בתגובה של הצלחה או כישלון. חשוב להגדיר את ערך הזמן הקצוב לתפוגה של שרת האפליקציה בבקשה בהתאם.

שליחת הודעות לקבוצות של מכשירים

שליחת הודעות לקבוצת מכשירים באמצעות ממשקי ה-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 של קבוצת מכשירים

זו דוגמה לתוצאה 'success' – ל-notification_key משויכים 2 אסימוני רישום, וההודעה נשלחה בהצלחה לשניהם:

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

דוגמה ל'הצלחה חלקית' – ל-notification_key משויכים 3 אסימוני רישום. ההודעה נשלחה בהצלחה לאחד מאסימוני ההרשמה בלבד. הודעת התגובה כוללת את אסימוני ההרשמה (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.

דוגמה לתוצאה 'success' – ל-notification_key משויכים 3 אסימוני הרשמה, וההודעה נשלחה בהצלחה לכל אחד מהם:

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

דוגמה ל'הצלחה חלקית' – ל-notification_key משויכים 3 אסימוני רישום. ההודעה נשלחה בהצלחה לאחד מאסימוני ההרשמה בלבד. הודעת התגובה כוללת את אסימוני ההרשמה שלא קיבלו את ההודעה:

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

כששרת החיבור של FCM לא מצליח להעביר את ההודעה לכל המכשירים בקבוצה. שרת האפליקציה יקבל תגובה מסוג nack.

לרשימה המלאה של אפשרויות ההודעות, אפשר לעיין במסמכי העזר של פרוטוקול שרת החיבור שבחרתם, HTTP או XMPP.

Firebase Admin SDK שיטות שליחה מדור קודם

ה-SDK של Firebase Admin ל-Node.js תומך בשיטות לשליחת הודעות (FCM) על סמך Legacy FCM server API. השיטות האלה מקבלות ארגומנטים שונים בהשוואה לשיטה 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() מחזירה הבטחה (promise) שמתקבלת עם אובייקט MessagingDevicesResponse שמכיל את התגובה מ-FCM. פורמט הטיפוס המוחזר זהה כשעובר אסימון רישום יחיד או מערך של אסימוני רישום.

במקרים מסוימים, כמו שגיאת אימות או הגבלת קצב, המערכת לא מצליחה לעבד את ההודעה כולה. במקרים כאלה, ההבטחה שמוחזרת על ידי sendToDevice() נדחית עם שגיאה. רשימה מלאה של קודי השגיאות, כולל תיאורים ושלבי פתרון, מופיעה במאמר שגיאות API של FCM לאדמינים.

שליחה לקבוצת מכשירים

השיטה 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() מחזירה הבטחה (promise) שמתקבלת עם אובייקט MessagingDevicesResponse שמכיל את התגובה מ-FCM.

במקרים מסוימים, כמו שגיאת אימות או הגבלת קצב, המערכת לא מצליחה לעבד את ההודעה כולה. במקרים כאלה, ההבטחה שמוחזרת על ידי sendToDeviceGroup() נדחית עם שגיאה. רשימה מלאה של קודי השגיאות, כולל תיאורים ושלבי פתרון, מופיעה במאמר שגיאות API של FCM לאדמינים.

הגדרת עומס העבודה של ההודעה

השיטות שלמעלה, שמבוססות על הפרוטוקולים הקודמים של 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.