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

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

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

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

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

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
}

הודעות שנשלחות עם המפתח הזה בגוף הבקשה יכולות להיות מטופלות על ידי אפליקציות במכשירים שנמצאים כרגע במצב הפעלה ישיר (וגם כשהם לא במצב הזה).

התאמה אישית של הודעות בפלטפורמות שונות

פרוטוקול ה-HTTP של 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 של HTTP v1

תגובות שגיאה של 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) עם השהיה ראשונית מינימלית של דקה כדי לנסות לשלוח שוב.
UNAVAILABLE (קוד שגיאת HTTP = 503) השרת עמוס. השרת לא הצליח לעבד את הבקשה בזמן. מנסים שוב את אותה בקשה, אבל צריך:
- לפעול לפי הכותרת Retry-After אם היא כלולה בתגובה משרת החיבור של FCM.
- הטמעת השהיה מעריכית לפני ניסיון חוזר (exponential backoff) במנגנון הניסיונות החוזרים. (לדוגמה, אם המתינו שנייה אחת לפני הניסיון הראשון, צריך להמתין לפחות שתי שניות לפני הניסיון הבא, ואז 4 שניות וכן הלאה). אם אתם שולחים כמה הודעות, מומלץ להשתמש בתנודות. למידע נוסף, ראו טיפול בניסיונות חוזרים. שולחים שגורמים לבעיות עלולים להיכלל ברשימת ההחרגות.
INTERNAL (קוד שגיאת HTTP = 500) אירעה שגיאה פנימית לא ידועה. השרת נתקל בשגיאה במהלך הניסיון לעבד את הבקשה. כדי לנסות שוב את אותה בקשה, אפשר להיעזר בהצעות הבאות בקטע טיפול בניסיונות חוזרים. אם השגיאה נמשכת, יש לפנות לתמיכה של Firebase.
THIRD_PARTY_AUTH_ERROR (קוד שגיאת HTTP = 401) האישור של APNs או מפתח האימות של דחיפה לאינטרנט לא תקינים או חסרים. לא ניתן היה לשלוח הודעה שמטורגטת למכשיר iOS או הרשמה לקבלת התראות דחיפה באינטרנט. בודקים את התקינות של פרטי הכניסה לפיתוח ולייצור.

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

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

קוד שגיאה תיאור ושלבי פתרון
messaging/invalid-argument סופק ארגומנט לא חוקי ל-method FCM. הודעת השגיאה אמורה לכלול מידע נוסף.
messaging/invalid-recipient הנמען המיועד של ההודעה לא תקין. הודעת השגיאה אמורה לכלול מידע נוסף.
messaging/invalid-payload אובייקט לא חוקי של עומס נתונים של הודעה סופק. הודעת השגיאה אמורה לכלול מידע נוסף.
messaging/invalid-data-payload-key מטען הנתונים של הודעת הנתונים מכיל מפתח לא חוקי. למידע נוסף על מפתחות מוגבלים, ראו את מאמרי העזרה של DataMessagePayload.
messaging/payload-size-limit-exceeded המטען הייעודי של ההודעות שסופק חורג ממגבלות הגודל של FCM. המגבלה היא 4,096 בייטים ברוב ההודעות. המגבלה על הודעות שנשלחות לנושאים היא 2,048 בייטים. הגודל הכולל של המטען הייעודי (Payload) כולל גם מפתחות וגם ערכים.
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(). כדאי להשתמש ב-method 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.

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