إرسال رسائل إلى أجهزة متعددة على أنظمة Apple الأساسية

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

يركّز هذا الدليل التوجيهي على إرسال رسائل بشأن مواضيع من خادم التطبيق باستخدام SDK للمشرف أو واجهة برمجة تطبيقات RST خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" واستلامها ومعالجتها في تطبيق Apple. تسرد هذه الصفحة جميع خطوات تحقيق ذلك، بدءًا من الإعداد إلى لإثبات الهوية، لذلك قد يشمل الخطوات التي سبق أن أكملتها إذا كان لديك إعداد تطبيق عميل Apple لخدمة "المراسلة عبر السحابة الإلكترونية من Firebase" أو راجعت خطوات إرسال الرسالة الأولى.

إضافة Firebase إلى مشروع Apple

يتناول هذا القسم المهام التي قد تكون أكملتها إذا سبق لك تفعيلها. ميزات Firebase الأخرى لتطبيقك. بالنسبة إلى "المراسلة عبر السحابة الإلكترونية من Firebase" تحديدًا، بحاجة إلى تحميل مفتاح مصادقة أسماء نقاط الوصول (APN) التسجيل لتلقي الإشعارات عن بُعد.

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

  • ثبِّت ما يلي:

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

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

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

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

إنشاء مشروع على Firebase

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

تسجيل تطبيقك في Firebase

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

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

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

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

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

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

  5. انقر على تسجيل التطبيق.

إضافة ملف إعداد Firebase

  1. انقر على تنزيل GoogleService-Info.plist للحصول على جهاز Firebase Apple. ملف إعداد الأنظمة الأساسية (GoogleService-Info.plist).

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

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

إضافة حِزم تطوير البرامج (SDK) لمنصة Firebase إلى تطبيقك

يمكنك استخدام "مدير حزم Swift" لتثبيت اعتماديات Firebase وإدارتها.

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

تحميل مفتاح مصادقة أسماء نقاط الوصول (APN)

حمِّل مفتاح مصادقة أسماء نقاط الوصول إلى Firebase. إذا لم يكن لديك مفتاح مصادقة لأسماء نقاط الوصول (APN)، احرص على إنشاء مفتاح في مركز أعضاء مطوّري برامج Apple

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

  2. في مفتاح مصادقة أسماء نقاط الوصول (APN) ضمن ضبط تطبيق iOS، انقر على تحميل .

  3. تصفح المكان الذي حفظت فيه مفتاحك، وحدده، ثم انقر انقر على فتح. أضِف معرّف المفتاح للمفتاح (المتوفّر في Apple Developer Member Center) وانقر على تحميل:

إعداد Firebase في تطبيقك

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

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

    واجهة المستخدم

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

    Swift

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    Objective-C

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

    واجهة المستخدم

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

    Swift

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

    Objective-C

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

    واجهة المستخدم

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

التسجيل لتلقّي الإشعارات عن بُعد

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

Swift


UNUserNotificationCenter.current().delegate = self

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

application.registerForRemoteNotifications()

Objective-C


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

[application registerForRemoteNotifications];

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

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

للاشتراك في موضوع، يمكنك طلب طريقة الاشتراك. من سلسلة التعليمات الرئيسية للتطبيق (ميزة "المراسلة عبر السحابة الإلكترونية من Firebase" غير ملائمة لسلاسل المحادثات). وإذا تعذّر طلب الاشتراك في البداية، ستحاول خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" تلقائيًا المحاولة. بالنسبة إلى الحالات التي يتعذّر فيها إكمال الاشتراك، يعرض الاشتراك خطأً يمكنك اكتشافه في معالج الإكمال كما هو موضح:

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

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

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

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

تعرض خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" رسائل المواضيع بنفس طريقة تسليم الرسائل الأخرى الرسائل.

تنفيذ 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، يمكنك إرسال رسائل إلى الموضوع. إذا كانت هذه هي المرة الأولى التي تنشئ فيها طلبات إرسال إلى "المراسلة عبر السحابة الإلكترونية من Firebase"، اطّلِع على دليل بيئة الخادم و"المراسلة عبر السحابة الإلكترونية من Firebase" الخلفية ومعلومات الإعداد المهمة.

في منطق الإرسال في الخلفية، حدِّد اسم الموضوع المطلوب كما هو موضح:

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

لإرسال رسالة إلى مجموعة من المواضيع، تحديد condition، وهو تعبير منطقي يحدد الموضوعات المستهدفة. على سبيل المثال، سيؤدي الشرط التالي إلى إرسال رسائل إلى الأجهزة المشتركة في TopicA وإما TopicB أو TopicC:

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

تقيّم خدمة "المراسلة عبر السحابة الإلكترونية من Firebase" أولاً أي شروط بين قوسين، ثم تقيّم التعبير من اليسار إلى اليمين. في التعبير أعلاه، اشترك مستخدم في لا يتلقى أي موضوع فردي الرسالة. وبالمثل، فإن المستخدم الذي لا الاشتراك في 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

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