إرسال رسائل إلى أجهزة متعددة على منصات أبل

لتوجيه رسالة إلى أجهزة متعددة، استخدم مراسلة الموضوع . تتيح لك هذه الميزة إرسال رسالة إلى أجهزة متعددة اشتركت في موضوع معين.

يركز هذا البرنامج التعليمي على إرسال رسائل الموضوع من خادم التطبيق الخاص بك باستخدام Admin SDK أو REST API لـ FCM، واستلامها والتعامل معها في تطبيق Apple. تسرد هذه الصفحة جميع الخطوات اللازمة لتحقيق ذلك، بدءًا من الإعداد وحتى التحقق - لذلك قد تغطي الخطوات التي أكملتها بالفعل إذا قمت بإعداد تطبيق عميل Apple لـ FCM أو اتبعت خطوات إرسال رسالتك الأولى .

أضف Firebase إلى مشروع Apple الخاص بك

يغطي هذا القسم المهام التي قد تكون أكملتها إذا قمت بالفعل بتمكين ميزات Firebase الأخرى لتطبيقك. بالنسبة إلى FCM على وجه التحديد، ستحتاج إلى تحميل مفتاح مصادقة APNs الخاص بك والتسجيل للحصول على الإشعارات عن بعد .

المتطلبات الأساسية

  • قم بتثبيت ما يلي:

    • Xcode 14.1 أو الأحدث
  • تأكد من أن مشروعك يلبي هذه المتطلبات:

    • يجب أن يستهدف مشروعك إصدارات النظام الأساسي هذه أو الإصدارات الأحدث:
      • دائرة الرقابة الداخلية 11
      • ماك 10.13
      • تي في او اس 12
      • واتش او اس 6
  • قم بإعداد جهاز Apple فعلي لتشغيل تطبيقك، وأكمل هذه المهام:

    • احصل على مفتاح مصادقة إشعارات Apple Push لحساب Apple Developer الخاص بك.
    • قم بتمكين الإشعارات الفورية في XCode ضمن التطبيق > القدرات .

إذا لم يكن لديك مشروع Xcode بالفعل وتريد فقط تجربة أحد منتجات Firebase، فيمكنك تنزيل أحد نماذج البدء السريع الخاصة بنا.

إنشاء مشروع Firebase

قبل أن تتمكن من إضافة Firebase إلى تطبيق Apple الخاص بك، تحتاج إلى إنشاء مشروع Firebase للاتصال بتطبيقك. قم بزيارة فهم مشاريع Firebase لمعرفة المزيد حول مشاريع Firebase.

سجل تطبيقك مع Firebase

لاستخدام Firebase في تطبيق Apple الخاص بك، يتعين عليك تسجيل تطبيقك في مشروع Firebase الخاص بك. غالبًا ما يُطلق على تسجيل تطبيقك اسم "إضافة" تطبيقك إلى مشروعك.

  1. انتقل إلى وحدة تحكم Firebase .

  2. في وسط صفحة النظرة العامة على المشروع، انقر فوق أيقونة iOS+ لبدء سير عمل الإعداد.

    إذا قمت بالفعل بإضافة تطبيق إلى مشروع Firebase الخاص بك، فانقر على إضافة تطبيق لعرض خيارات النظام الأساسي.

  3. أدخل معرف حزمة التطبيق الخاص بك في حقل معرف الحزمة .

  4. (اختياري) أدخل معلومات التطبيق الأخرى: لقب التطبيق ومعرف متجر التطبيقات .

  5. انقر فوق تسجيل التطبيق .

أضف ملف تكوين Firebase

  1. انقر فوق Download GoogleService-Info.plist للحصول على ملف تكوين منصات Firebase Apple ( GoogleService-Info.plist ).

  2. انقل ملف التكوين الخاص بك إلى جذر مشروع Xcode الخاص بك. إذا طُلب منك ذلك، حدد إضافة ملف التكوين إلى كافة الأهداف.

إذا كان لديك معرفات حزمة متعددة في مشروعك، فيجب عليك ربط كل معرف حزمة بتطبيق مسجل في وحدة تحكم Firebase حتى يتمكن كل تطبيق من الحصول على ملف GoogleService-Info.plist الخاص به.

أضف حزم Firebase SDK إلى تطبيقك

استخدم Swift Package Manager لتثبيت تبعيات Firebase وإدارتها.

  1. في Xcode، مع فتح مشروع التطبيق الخاص بك، انتقل إلى File > Add Packages .
  2. عندما يُطلب منك ذلك، قم بإضافة مستودع Firebase Apple الأساسي لـ SDK:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. اختر مكتبة Firebase Cloud Messaging.
  5. أضف علامة -ObjC إلى قسم إشارات الرابط الأخرى في إعدادات إنشاء هدفك.
  6. للحصول على تجربة مثالية مع Firebase Cloud Messaging، نوصي بتمكين Google Analytics في مشروع Firebase الخاص بك وإضافة Firebase SDK لـ Google Analytics إلى تطبيقك. يمكنك تحديد المكتبة بدون مجموعة IDFA أو مع مجموعة IDFA.
  7. عند الانتهاء، سيبدأ Xcode تلقائيًا في حل وتنزيل تبعياتك في الخلفية.

قم بتحميل مفتاح مصادقة APNs الخاص بك

قم بتحميل مفتاح مصادقة APNs الخاص بك إلى Firebase. إذا لم يكن لديك بالفعل مفتاح مصادقة APNs، فتأكد من إنشاء واحد في مركز أعضاء مطوري Apple .

  1. داخل مشروعك في وحدة تحكم Firebase، حدد رمز الترس، وحدد إعدادات المشروع ، ثم حدد علامة التبويب Cloud Messaging .

  2. في مفتاح مصادقة APNs ضمن تكوين تطبيق iOS ، انقر فوق الزر تحميل .

  3. استعرض وصولاً إلى الموقع الذي حفظت فيه مفتاحك، وحدده، ثم انقر فوق فتح . أضف معرف المفتاح للمفتاح (المتوفر في مركز أعضاء مطوري Apple ) وانقر فوق تحميل .

قم بتهيئة Firebase في تطبيقك

ستحتاج إلى إضافة رمز تهيئة Firebase إلى تطبيقك. قم باستيراد وحدة Firebase وقم بتكوين مثيل مشترك كما هو موضح:

  1. قم باستيراد وحدة FirebaseCore في UIApplicationDelegate ، بالإضافة إلى أي وحدات Firebase أخرى يستخدمها مندوب تطبيقك. على سبيل المثال، لاستخدام Cloud Firestore والمصادقة:

    سويفتويي

    import SwiftUI
    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    سويفت

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    ج موضوعية

    @import FirebaseCore;
    @import FirebaseFirestore;
    @import FirebaseAuth;
    // ...
          
  2. قم بتكوين مثيل FirebaseApp مشترك في طريقة application(_:didFinishLaunchingWithOptions:) :

    سويفتويي

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    سويفت

    // Use Firebase library to configure APIs
    FirebaseApp.configure()

    ج موضوعية

    // Use Firebase library to configure APIs
    [FIRApp configure];
  3. إذا كنت تستخدم SwiftUI، فيجب عليك إنشاء مفوض تطبيق وإرفاقه ببنية App الخاص بك عبر UIApplicationDelegateAdaptor أو NSApplicationDelegateAdaptor . يجب عليك أيضًا تعطيل swizzling مندوب التطبيق. لمزيد من المعلومات، راجع تعليمات SwiftUI .

    سويفتويي

    @main
    struct YourApp: App {
      // register app delegate for Firebase setup
      @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
      var body: some Scene {
        WindowGroup {
          NavigationView {
            ContentView()
          }
        }
      }
    }
          

سجل للحصول على الإخطارات عن بعد

سواء عند بدء التشغيل، أو عند النقطة المطلوبة في تدفق التطبيق، قم بتسجيل تطبيقك للحصول على إشعارات عن بعد. استدعاء registerForRemoteNotifications كما هو موضح:

سويفت


UNUserNotificationCenter.current().delegate = self

let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
  options: authOptions,
  completionHandler: { _, _ in }
)

application.registerForRemoteNotifications()

ج موضوعية


[UNUserNotificationCenter currentNotificationCenter].delegate = self;
UNAuthorizationOptions authOptions = UNAuthorizationOptionAlert |
    UNAuthorizationOptionSound | UNAuthorizationOptionBadge;
[[UNUserNotificationCenter currentNotificationCenter]
    requestAuthorizationWithOptions:authOptions
    completionHandler:^(BOOL granted, NSError * _Nullable error) {
      // ...
    }];

[application registerForRemoteNotifications];

اشترك في تطبيق العميل في موضوع ما

يمكن لتطبيقات العميل الاشتراك في أي موضوع موجود، أو يمكنها إنشاء موضوع جديد. عندما يشترك تطبيق عميل في اسم موضوع جديد (اسم غير موجود بالفعل لمشروع Firebase الخاص بك)، يتم إنشاء موضوع جديد بهذا الاسم في FCM ويمكن لأي عميل الاشتراك فيه لاحقًا.

للاشتراك في موضوع ما، اتصل بطريقة الاشتراك من الموضوع الرئيسي لتطبيقك (FCM ليس آمنًا لسلسلة الرسائل). إذا فشل طلب الاشتراك في البداية، تقوم FCM بإعادة المحاولة تلقائيًا. بالنسبة للحالات التي لا يمكن فيها إكمال الاشتراك، يُظهر الاشتراك خطأ يمكنك اكتشافه في معالج الإكمال كما هو موضح:

سويفت

Messaging.messaging().subscribe(toTopic: "weather") { error in
  print("Subscribed to weather topic")
}

ج موضوعية

[[FIRMessaging messaging] subscribeToTopic:@"weather"
                                completion:^(NSError * _Nullable error) {
  NSLog(@"Subscribed to weather topic");
}];

يقوم هذا الاستدعاء بتقديم طلب غير متزامن إلى الواجهة الخلفية لـ FCM ويشترك العميل في الموضوع المحدد. قبل الاتصال بـ subscribeToTopic:topic ، تأكد من أن مثيل تطبيق العميل قد تلقى بالفعل رمزًا مميزًا للتسجيل عبر رد الاتصال didReceiveRegistrationToken .

في كل مرة يتم فيها تشغيل التطبيق، تتأكد FCM من الاشتراك في جميع المواضيع المطلوبة. لإلغاء الاشتراك، اتصل بـ unsubscribeFromTopic:topic ، وستقوم FCM بإلغاء الاشتراك في الموضوع في الخلفية.

تلقي والتعامل مع رسائل الموضوع

تقوم FCM بتسليم رسائل الموضوع بنفس طريقة تسليم الرسائل الأخرى.

قم بتنفيذ application(_:didReceiveRemoteNotification:fetchCompletionHandler:) كما هو موضح:

سويفت

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
}

ج موضوعية

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

بناء طلبات الإرسال

بعد إنشاء موضوع، إما عن طريق اشتراك مثيلات تطبيق العميل في الموضوع من جانب العميل أو عبر واجهة برمجة تطبيقات الخادم ، يمكنك إرسال رسائل إلى الموضوع. إذا كانت هذه هي المرة الأولى التي تقوم فيها بإنشاء طلبات إرسال لـ 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);

بايثون

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

ج #

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

// See documentation on defining a message payload.
var message = new Message()
{
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
    Topic = topic,
};

// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

استراحة

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

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

أمر الضفيرة:

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

لإرسال رسالة إلى مجموعة من المواضيع، حدد شرطًا ، وهو عبارة عن تعبير منطقي يحدد الموضوعات المستهدفة. على سبيل المثال، سيؤدي الشرط التالي إلى إرسال رسائل إلى الأجهزة المشتركة في TopicA وإما 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);

بايثون

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

ج #

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

// See documentation on defining a message payload.
var message = new Message()
{
    Notification = new Notification()
    {
        Title = "$GOOG up 1.43% on the day",
        Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
    },
    Condition = condition,
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

استراحة

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

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

أمر الضفيرة:

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

الخطوات التالية