استنادًا إلى نموذج النشر/الاشتراك، تتيح لك رسائل المواضيع في "FCM" إرسال رسالة. على أجهزة متعددة تم تفعيل موضوع معين فيها. يمكنك إنشاء رسائل المواضيع كما هو مطلوب، ويتولى FCM توجيه الرسائل وتسليمها بشكل موثوق إلى الأجهزة المناسبة.
على سبيل المثال، مستخدمو المد المحلي إمكانية تفعيل تطبيق للتوقّعات في "تنبيهات تيارات المد والجزر" الموضوع وتلقي والظروف المثلى لصيد المياه المالحة في مناطق محددة. مستخدمو تطبيق رياضي يمكنهم الاشتراك في التحديثات التلقائية في نتائج المباريات المباشرة لمبارياتهم المفضلة الفرق.
في ما يلي بعض النقاط التي يجب أخذها في الاعتبار بشأن المواضيع:
- تكون ميزة "الرسائل المتعلّقة بالموضوع" مناسبة بشكلٍ أفضل للمحتوى المتعلّق مثلاً بالطقس أو أي معلومات أخرى متاحة للجميع.
- يتم تحسين رسائل المواضيع لزيادة معدل نقل البيانات بدلاً من تقليل وقت الاستجابة. للتسليم السريع والآمن إلى أجهزة فردية أو مجموعات صغيرة من الأجهزة، أو استهداف الرسائل برموز التسجيل المميّزة وليس موضوعات.
- إذا كنت بحاجة إلى إرسال رسائل إلى أجهزة متعدّدة لكل مستخدم، ننصحك المراسلة الجماعية على الأجهزة لحالات الاستخدام هذه.
- تتيح ميزة "المراسلة حسب المواضيع" إمكانية الاشتراك في عدد غير محدود من المواضيع. ومع ذلك، تفرض FCM
حدودًا في هذه المجالات:
- لا يمكن اشتراك نسخة واحدة من التطبيق في أكثر من 2000 موضوع.
- في حال استخدام استيراد مُجمَّع للاشتراك في مثيلات التطبيقات، يمكن أن يقتصر كل طلب على 1, 000 نسخة افتراضية من التطبيق.
- يتم تحديد معدّل تكرار الاشتراكات الجديدة لكل مشروع. إذا أرسلت عددًا كبيرًا جدًا من
طلبات الاشتراك في فترة زمنية قصيرة، ستستجيب خوادم FCM باستخدام ردّ
429 RESOURCE_EXHAUSTED
("تم تجاوز الحصة"). إعادة المحاولة باستخدام تراجعًا أسيًا.
إشراك تطبيق العميل في موضوع
يمكن للتطبيقات التابعة للعملاء الاشتراك في أي موضوع حالي، أو يمكنها إنشاء موضوع جديد. عندما يشترك تطبيق عميل في اسم موضوع جديد (اسم موضوع غير موجود سلفًا لمشروعك في Firebase)، فسيكون موضوع جديد بهذا الاسم الذي تم إنشاؤه في FCM ويمكن لأي عميل الاشتراك فيه في وقت لاحق.
للاشتراك في موضوع، يمكنك استدعاء طريقة الاشتراك من سلسلة المهام الرئيسية لتطبيقك (FCM غير آمن في سلسلة المهام). وإذا تعذّر طلب الاشتراك في البداية، ستتم إعادة محاولة FCM تلقائيًا. في الحالات التي يتعذّر فيها إكمال الاشتراك، يُرسِل الاشتراك خطأً يمكنك رصده في معالج الإكمال كما هو موضّح:
Swift
Messaging.messaging().subscribe(toTopic: "weather") { error in print("Subscribed to weather topic") }
Objective-C
[[FIRMessaging messaging] subscribeToTopic:@"weather" completion:^(NSError * _Nullable error) { NSLog(@"Subscribed to weather topic"); }];
تؤدي هذه المكالمة إلى إجراء
طلب غير متزامن إلى الواجهة الخلفية FCM ويشترك العميل في
للموضوع المحدد. قبل استدعاء subscribeToTopic:topic
، تأكَّد من أنّه سبق أن تلقّت
مثيل تطبيق العميل رمز تنشيط التسجيل من خلال callback didReceiveRegistrationToken
.
في كل مرة يبدأ فيها التطبيق،
يضمن FCM أن جميع المواضيع المطلوبة قد تم الاشتراك فيها. لإلغاء الاشتراك، اتصل بالرقم unsubscribeFromTopic:topic
،
وسيؤدي ذلك إلى إلغاء الاشتراك في الموضوع في الخلفية.
إدارة اشتراكات المواضيع على الخادم
Firebase Admin SDK إجراء تجارب ومهام إدارة الموضوعات من جانب الخادم. استنادًا إلى رموزها المميّزة لتسجيلها، يمكنك الاشتراك في نُسخ تطبيق العميل وإلغاء الاشتراك فيها بشكل مجمّع باستخدام منطق الخادم.
يمكنك الاشتراك في النُسخ الافتراضية من تطبيق العميل في أي موضوع حالي. يمكنك إنشاء موضوع جديد عند استخدام واجهة برمجة التطبيقات لإشتراك تطبيق العميل في موضوع جديد (موضوع غير متوفّر حاليًا لمشروعك على Firebase)، يتم إنشاء موضوع جديد بهذا الاسم في خدمة "مراسلة Firebase" ويمكن لأي عميل إشتراكه بعد ذلك.
يمكنك تمرير قائمة بالرموز المميّزة للتسجيل إلى Firebase Admin SDK. للاشتراك في الأجهزة المقابلة في موضوع معيّن:
Node.js
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'YOUR_REGISTRATION_TOKEN_1',
// ...
'YOUR_REGISTRATION_TOKEN_n'
];
// Subscribe the devices corresponding to the registration tokens to the
// topic.
getMessaging().subscribeToTopic(registrationTokens, topic)
.then((response) => {
// See the MessagingTopicManagementResponse reference documentation
// for the contents of response.
console.log('Successfully subscribed to topic:', response);
})
.catch((error) => {
console.log('Error subscribing to topic:', error);
});
جافا
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n"
);
// Subscribe the devices corresponding to the registration tokens to the
// topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().subscribeToTopic(
registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were subscribed successfully");
Python
# These registration tokens come from the client FCM SDKs.
registration_tokens = [
'YOUR_REGISTRATION_TOKEN_1',
# ...
'YOUR_REGISTRATION_TOKEN_n',
]
# Subscribe the devices corresponding to the registration tokens to the
# topic.
response = messaging.subscribe_to_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were subscribed successfully')
انتقال
// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
}
// Subscribe the devices corresponding to the registration tokens to the
// topic.
response, err := client.SubscribeToTopic(ctx, registrationTokens, topic)
if err != nil {
log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were subscribed successfully")
#C
// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
};
// Subscribe the devices corresponding to the registration tokens to the
// topic
var response = await FirebaseMessaging.DefaultInstance.SubscribeToTopicAsync(
registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were subscribed successfully");
تسمح لك واجهة برمجة التطبيقات Admin FCM API أيضًا بإلغاء الاشتراك في الأجهزة من موضوع معيّن. من خلال تمرير رموز التسجيل المميزة إلى القسم :
Node.js
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
'YOUR_REGISTRATION_TOKEN_1',
// ...
'YOUR_REGISTRATION_TOKEN_n'
];
// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
getMessaging().unsubscribeFromTopic(registrationTokens, topic)
.then((response) => {
// See the MessagingTopicManagementResponse reference documentation
// for the contents of response.
console.log('Successfully unsubscribed from topic:', response);
})
.catch((error) => {
console.log('Error unsubscribing from topic:', error);
});
جافا
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n"
);
// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
TopicManagementResponse response = FirebaseMessaging.getInstance().unsubscribeFromTopic(
registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " tokens were unsubscribed successfully");
Python
# These registration tokens come from the client FCM SDKs.
registration_tokens = [
'YOUR_REGISTRATION_TOKEN_1',
# ...
'YOUR_REGISTRATION_TOKEN_n',
]
# Unubscribe the devices corresponding to the registration tokens from the
# topic.
response = messaging.unsubscribe_from_topic(registration_tokens, topic)
# See the TopicManagementResponse reference documentation
# for the contents of response.
print(response.success_count, 'tokens were unsubscribed successfully')
انتقال
// These registration tokens come from the client FCM SDKs.
registrationTokens := []string{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
}
// Unsubscribe the devices corresponding to the registration tokens from
// the topic.
response, err := client.UnsubscribeFromTopic(ctx, registrationTokens, topic)
if err != nil {
log.Fatalln(err)
}
// See the TopicManagementResponse reference documentation
// for the contents of response.
fmt.Println(response.SuccessCount, "tokens were unsubscribed successfully")
#C
// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
"YOUR_REGISTRATION_TOKEN_1",
// ...
"YOUR_REGISTRATION_TOKEN_n",
};
// Unsubscribe the devices corresponding to the registration tokens from the
// topic
var response = await FirebaseMessaging.DefaultInstance.UnsubscribeFromTopicAsync(
registrationTokens, topic);
// See the TopicManagementResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} tokens were unsubscribed successfully");
تؤدي الطريقتان subscribeToTopic()
وunsubscribeFromTopic()
إلى ناتج هو
عنصر يحتوي على الردّ من FCM. يكون نوع الإرجاع بالشكل
نفسه بغض النظر عن عدد الرموز المميّزة للتسجيل المحدّدة في
الطلب.
حدوث خطأ (تعذُّر المصادقة أو ظهور رمز أو موضوع غير صالح أو غير ذلك) إلى حدوث خطأ باستخدام هذه الطرق. للحصول على قائمة كاملة برموز الخطأ، بما في ذلك الأوصاف وخطوات الحلّ، يُرجى الاطّلاع على أخطاء واجهة برمجة التطبيقات Admin FCM.
تلقّي رسائل المواضيع والتعامل معها
تُرسِل FCM رسائل المواضيع بالطريقة نفسها التي تُرسِل بها رسائل الأخرى.
نفِّذ application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
كما هو موضّح:
Swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) async -> UIBackgroundFetchResult { // If you are receiving a notification message while your app is in the background, // this callback will not be fired till the user taps on the notification launching the application. // TODO: Handle data of notification // With swizzling disabled you must let Messaging know about the message, for Analytics // Messaging.messaging().appDidReceiveMessage(userInfo) // Print message ID. if let messageID = userInfo[gcmMessageIDKey] { print("Message ID: \(messageID)") } // Print full message. print(userInfo) return UIBackgroundFetchResult.newData }
Objective-C
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // If you are receiving a notification message while your app is in the background, // this callback will not be fired till the user taps on the notification launching the application. // TODO: Handle data of notification // With swizzling disabled you must let Messaging know about the message, for Analytics // [[FIRMessaging messaging] appDidReceiveMessage:userInfo]; // ... // Print full message. NSLog(@"%@", userInfo); completionHandler(UIBackgroundFetchResultNewData); }
إنشاء طلبات الإرسال
بعد إنشاء موضوع، إما من خلال اشتراك مثيلات تطبيق العميل في الموضوع من جانب العميل أو عبر server API، يمكنك إرسال رسائل إلى الموضوع. إذا كانت هذه هي المرة الأولى التي ترسل فيها طلبات لإنشاء FCM، اطّلِع على دليل بيئة الخادم وFCM على الخلفية ومعلومات الإعداد المهمة.
في منطق الإرسال في الخلفية، حدِّد اسم الموضوع المطلوب كما هو موضّح:
Node.js
// The topic name can be optionally prefixed with "/topics/".
const topic = 'highScores';
const message = {
data: {
score: '850',
time: '2:45'
},
topic: topic
};
// Send a message to devices subscribed to the provided topic.
getMessaging().send(message)
.then((response) => {
// Response is a message ID string.
console.log('Successfully sent message:', response);
})
.catch((error) => {
console.log('Error sending message:', error);
});
جافا
// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";
// See documentation on defining a message payload.
Message message = Message.builder()
.putData("score", "850")
.putData("time", "2:45")
.setTopic(topic)
.build();
// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Python
# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'
# See documentation on defining a message payload.
message = messaging.Message(
data={
'score': '850',
'time': '2:45',
},
topic=topic,
)
# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
انتقال
// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Topic: topic,
}
// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
#C
// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";
// See documentation on defining a message payload.
var message = new Message()
{
Data = new Dictionary<string, string>()
{
{ "score", "850" },
{ "time", "2:45" },
},
Topic = topic,
};
// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
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
لإرسال رسالة إلى مجموعة من المواضيع،
حدِّد شرطًا، وهو تعبير منطقي يحدِّد topics المستهدفة. على سبيل المثال، سيؤدي الشرط التالي إلى إرسال رسائل إلى
الأجهزة المشتركة في 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);
});
جافا
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
Message message = Message.builder()
.setNotification(Notification.builder()
.setTitle("$GOOG up 1.43% on the day")
.setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
.build())
.setCondition(condition)
.build();
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
Python
# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"
# See documentation on defining a message payload.
message = messaging.Message(
notification=messaging.Notification(
title='$GOOG up 1.43% on the day',
body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
),
condition=condition,
)
# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)
انتقال
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"
// See documentation on defining a message payload.
message := &messaging.Message{
Data: map[string]string{
"score": "850",
"time": "2:45",
},
Condition: condition,
}
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)
#C
// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";
// See documentation on defining a message payload.
var message = new Message()
{
Notification = new Notification()
{
Title = "$GOOG up 1.43% on the day",
Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
},
Condition = condition,
};
// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);
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
الخطوات التالية
- مزيد من المعلومات حول الطريقة الأخرى لإرسال الرسائل إلى أجهزة متعدّدة - المراسلة الجماعية للأجهزة