หากต้องการกำหนดเป้าหมายข้อความไปยังอุปกรณ์หลายเครื่อง ให้ใช้การรับส่งข้อความตามหัวข้อ ฟีเจอร์นี้ช่วยให้คุณส่งข้อความไปยังอุปกรณ์หลายเครื่องที่เลือกใช้หัวข้อหนึ่งๆ ได้
บทแนะนำนี้มุ่งเน้นที่การส่งข้อความหัวข้อจากเซิร์ฟเวอร์แอปโดยใช้ Admin SDK หรือ REST API สำหรับ FCM รวมถึงการรับและจัดการข้อความเหล่านั้นในแอป Apple หน้านี้จะแสดงขั้นตอนทั้งหมดตั้งแต่การตั้งค่าไปจนถึงการยืนยัน ดังนั้นจึงอาจครอบคลุมขั้นตอนที่คุณได้ทำไปแล้วหากคุณได้ตั้งค่าแอปไคลเอ็นต์ Apple สำหรับ FCM หรือทำตามขั้นตอนเพื่อส่งข้อความแรกแล้ว
เพิ่ม Firebase ไปยังโปรเจ็กต์ Apple
ส่วนนี้จะกล่าวถึงงานที่คุณอาจทําเสร็จแล้วหากเปิดใช้ฟีเจอร์อื่นๆ ของ Firebase สําหรับแอปแล้ว สําหรับ FCM โดยเฉพาะ คุณจะต้องอัปโหลดคีย์การตรวจสอบสิทธิ์ APNs และลงทะเบียนเพื่อรับการแจ้งเตือนจากระยะไกล
ข้อกำหนดเบื้องต้น
ติดตั้งรายการต่อไปนี้
- Xcode 15.2 ขึ้นไป
ตรวจสอบว่าโปรเจ็กต์เป็นไปตามข้อกำหนดต่อไปนี้
- โปรเจ็กต์ต้องกำหนดเป้าหมายเป็นแพลตฟอร์มเวอร์ชันต่อไปนี้หรือเวอร์ชันที่ใหม่กว่า
- iOS 13
- macOS 10.15
- tvOS 13
- watchOS 7
- โปรเจ็กต์ต้องกำหนดเป้าหมายเป็นแพลตฟอร์มเวอร์ชันต่อไปนี้หรือเวอร์ชันที่ใหม่กว่า
ตั้งค่าอุปกรณ์ Apple จริงเพื่อเรียกใช้แอป และทํางานต่อไปนี้
- รับคีย์การตรวจสอบสิทธิ์ข้อความ Push ของ Apple สำหรับบัญชีนักพัฒนาแอป Apple
- เปิดใช้ข้อความ Push ใน XCode ในส่วนแอป > ความสามารถ
- ลงชื่อเข้าใช้ Firebase โดยใช้บัญชี Google
หากยังไม่มีโปรเจ็กต์ Xcode และต้องการลองใช้ผลิตภัณฑ์ Firebase เพียงอย่างเดียว คุณสามารถดาวน์โหลดตัวอย่างการเริ่มต้นใช้งานอย่างรวดเร็วของเรา
สร้างโปรเจ็กต์ Firebase
คุณต้องสร้างโปรเจ็กต์ Firebase เพื่อเชื่อมต่อกับแอปก่อนจึงจะเพิ่ม Firebase ในแอป Apple ได้ โปรดไปที่ทําความเข้าใจโปรเจ็กต์ Firebase เพื่อดูข้อมูลเพิ่มเติมเกี่ยวกับโปรเจ็กต์ Firebase
ลงทะเบียนแอปกับ Firebase
หากต้องการใช้ Firebase ในแอป Apple คุณต้องลงทะเบียนแอปกับโปรเจ็กต์ Firebase การลงทะเบียนแอปมักเรียกว่า "การเพิ่ม" แอปลงในโปรเจ็กต์
ไปที่คอนโซล Firebase
คลิกไอคอน iOS+ ตรงกลางหน้าภาพรวมโปรเจ็กต์เพื่อเปิดเวิร์กโฟลว์การตั้งค่า
หากเพิ่มแอปลงในโปรเจ็กต์ Firebase อยู่แล้ว ให้คลิกเพิ่มแอปเพื่อแสดงตัวเลือกแพลตฟอร์ม
ป้อนรหัสกลุ่มของแอปในช่องรหัสกลุ่ม
(ไม่บังคับ) ป้อนข้อมูลอื่นๆ ของแอป ได้แก่ ชื่อเล่นของแอปและ App Store ID
คลิกลงทะเบียนแอป
เพิ่มไฟล์การกําหนดค่า Firebase
คลิกดาวน์โหลด GoogleService-Info.plist เพื่อรับไฟล์การกําหนดค่าแพลตฟอร์ม Apple ของ Firebase (
GoogleService-Info.plist
)ย้ายไฟล์การกําหนดค่าไปยังรูทของโปรเจ็กต์ Xcode หากได้รับข้อความแจ้ง ให้เลือกเพิ่มไฟล์กำหนดค่าลงในเป้าหมายทั้งหมด
หากมีรหัสกลุ่มหลายรายการในโปรเจ็กต์ คุณต้องเชื่อมโยงรหัสกลุ่มแต่ละรายการกับแอปที่ลงทะเบียนในคอนโซล Firebase เพื่อให้แต่ละแอปมีไฟล์ GoogleService-Info.plist
เป็นของตัวเอง
เพิ่ม Firebase SDK ลงในแอป
ใช้ Swift Package Manager เพื่อติดตั้งและจัดการทรัพยากร Dependency ของ Firebase
- เปิดโปรเจ็กต์แอปใน Xcode แล้วไปที่ไฟล์ > เพิ่มแพ็กเกจ
- เมื่อได้รับข้อความแจ้ง ให้เพิ่มที่เก็บ Firebase SDK สําหรับแพลตฟอร์ม Apple ดังนี้
- เลือกคลัง Firebase Cloud Messaging
- เพิ่ม Flag
-ObjC
ลงในส่วน Other Linker Flags ของการตั้งค่าบิลด์เป้าหมาย - เราขอแนะนําให้เปิดใช้ Google Analytics ในโปรเจ็กต์ Firebase และเพิ่ม Firebase SDK สําหรับ Google Analytics ลงในแอปเพื่อให้ได้รับประสบการณ์การใช้งาน Firebase Cloud Messaging ที่ดีที่สุด คุณสามารถเลือกคลังแบบไม่เก็บรวบรวม IDFA หรือแบบเก็บรวบรวม IDFA ก็ได้
- เมื่อเสร็จแล้ว Xcode จะเริ่มจับคู่ข้อมูลและดาวน์โหลดทรัพยากร Dependency ในเบื้องหลังโดยอัตโนมัติ
https://github.com/firebase/firebase-ios-sdk.git
อัปโหลดคีย์การตรวจสอบสิทธิ์ APNs
อัปโหลดคีย์การตรวจสอบสิทธิ์ APNs ไปยัง Firebase หากยังไม่มีคีย์การตรวจสอบสิทธิ์ APNs โปรดสร้างคีย์ในศูนย์สมาชิกนักพัฒนาแอปของ Apple
-
ในโปรเจ็กต์ในคอนโซล Firebase ให้เลือกไอคอนรูปเฟือง เลือกการตั้งค่าโปรเจ็กต์ แล้วเลือกแท็บการรับส่งข้อความระบบคลาวด์
-
ในส่วนคีย์การตรวจสอบสิทธิ์ APNs ใต้การกำหนดค่าแอป iOS ให้คลิกปุ่มอัปโหลด
-
เรียกดูตำแหน่งที่คุณบันทึกคีย์ไว้ เลือกคีย์ แล้วคลิกเปิด เพิ่มรหัสคีย์สำหรับคีย์ (ดูได้ใน ศูนย์สมาชิกนักพัฒนาแอปของ Apple) แล้วคลิกอัปโหลด
เริ่มต้นใช้งาน Firebase ในแอป
คุณจะต้องเพิ่มโค้ดการเริ่มต้น Firebase ลงในแอปพลิเคชัน นําเข้ามอดุล Firebase และกำหนดค่าอินสแตนซ์ที่แชร์ดังที่แสดง
- นําเข้าโมดูล
FirebaseCore
ในUIApplicationDelegate
รวมถึงโมดูล Firebase อื่นๆ ที่ผู้รับมอบสิทธิ์ของแอปใช้ ตัวอย่างเช่น หากต้องการใช้ Cloud Firestore และ Authentication ให้ทำดังนี้SwiftUI
import SwiftUI import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Swift
import FirebaseCore import FirebaseFirestore import FirebaseAuth // ...
Objective-C
@import FirebaseCore; @import FirebaseFirestore; @import FirebaseAuth; // ...
- กำหนดค่าอินสแตนซ์ที่แชร์ในเมธอด
application(_:didFinishLaunchingWithOptions:)
ของตัวแทนแอป ดังนี้FirebaseApp
SwiftUI
// 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];
- หากใช้ SwiftUI คุณต้องสร้างผู้รับมอบสิทธิ์แอปพลิเคชันและแนบไปกับ
App
struct ผ่านUIApplicationDelegateAdaptor
หรือNSApplicationDelegateAdaptor
นอกจากนี้ คุณยังต้องปิดใช้การสลับผู้รับมอบสิทธิ์แอปด้วย ดูข้อมูลเพิ่มเติมได้ที่วิธีการ SwiftUISwiftUI
@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 ของคุณ) ระบบจะสร้างหัวข้อใหม่ชื่อนั้นใน 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
แล้ว 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);
});
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
คุณใส่หัวข้อในนิพจน์เงื่อนไขได้สูงสุด 5 หัวข้อ
หากต้องการส่งไปยังเงื่อนไข
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
ขั้นตอนถัดไป
- คุณสามารถใช้เซิร์ฟเวอร์เพื่อสมัครใช้บริการอินสแตนซ์แอปไคลเอ็นต์กับหัวข้อและดําเนินการด้านการจัดการอื่นๆ ได้ ดูหัวข้อจัดการการติดตามหัวข้อในเซิร์ฟเวอร์