Để nhắm mục tiêu một tin nhắn đến nhiều thiết bị, hãy sử dụng tính năng Nhắn tin theo chủ đề. Tính năng này cho phép bạn gửi thông báo đến nhiều thiết bị đã chọn sử dụng một chủ đề cụ thể.
Hướng dẫn này tập trung vào việc gửi thông báo theo chủ đề từ máy chủ ứng dụng bằng cách sử dụng Admin SDK hoặc API REST cho FCM, cũng như nhận và xử lý các thông báo đó trong một ứng dụng của Apple. Trang này liệt kê tất cả các bước để thực hiện việc này, từ thiết lập đến xác minh. Vì vậy, trang này có thể bao gồm các bước bạn đã hoàn tất nếu bạn đã thiết lập ứng dụng khách của Apple cho FCM hoặc đã thực hiện các bước để Gửi thông báo đầu tiên.
Thêm Firebase vào dự án Apple
Phần này trình bày các nhiệm vụ mà bạn có thể đã hoàn thành nếu đã bật các tính năng Firebase khác cho ứng dụng của mình. Riêng đối với FCM, bạn sẽ cần tải khoá xác thực APN lên và đăng ký nhận thông báo từ xa.
Điều kiện tiên quyết
Cài đặt các phần sau:
- Xcode 15.2 trở lên
Đảm bảo rằng dự án của bạn đáp ứng các yêu cầu sau:
- Dự án của bạn phải nhắm đến các phiên bản nền tảng này trở lên:
- iOS 13
- macOS 10.15
- tvOS 13
- watchOS 7
- Dự án của bạn phải nhắm đến các phiên bản nền tảng này trở lên:
Thiết lập thiết bị Apple thực để chạy ứng dụng và hoàn thành các nhiệm vụ sau:
- Lấy Khoá xác thực thông báo đẩy của Apple cho Tài khoản nhà phát triển của Apple.
- Bật Thông báo đẩy trong XCode trong phần App (Ứng dụng) > Capabilities (Chức năng).
- Đăng nhập vào Firebase bằng Tài khoản Google của bạn.
Nếu chưa có dự án Xcode và chỉ muốn dùng thử một sản phẩm Firebase, bạn có thể tải một trong các mẫu làm quen nhanh của chúng tôi xuống.
Tạo dự án Firebase
Trước khi có thể thêm Firebase vào ứng dụng Apple, bạn cần tạo một dự án Firebase để kết nối với ứng dụng của mình. Hãy truy cập vào bài viết Tìm hiểu về dự án Firebase để tìm hiểu thêm về dự án Firebase.
Đăng ký ứng dụng của bạn với Firebase
Để sử dụng Firebase trong ứng dụng Apple, bạn cần đăng ký ứng dụng của mình với dự án Firebase. Việc đăng ký ứng dụng thường được gọi là "thêm" ứng dụng vào dự án.
Chuyển đến bảng điều khiển Firebase.
Ở trung tâm trang tổng quan của dự án, hãy nhấp vào biểu tượng iOS+ để chạy quy trình thiết lập.
Nếu bạn đã thêm một ứng dụng vào dự án Firebase, hãy nhấp vào Thêm ứng dụng để hiển thị các tuỳ chọn nền tảng.
Nhập mã nhận dạng gói của ứng dụng vào trường mã nhận dạng gói.
(Không bắt buộc) Nhập thông tin khác về ứng dụng: Biệt hiệu ứng dụng và Mã App Store.
Nhấp vào Đăng ký ứng dụng.
Thêm tệp cấu hình Firebase
Nhấp vào Tải GoogleService-Info.plist xuống để lấy tệp cấu hình nền tảng Apple Firebase (
GoogleService-Info.plist
).Di chuyển tệp cấu hình vào thư mục gốc của dự án Xcode. Nếu được nhắc, hãy chọn thêm tệp cấu hình vào tất cả các mục tiêu.
Nếu có nhiều mã nhận dạng gói trong dự án, bạn phải liên kết từng mã nhận dạng gói với một ứng dụng đã đăng ký trong bảng điều khiển Firebase để mỗi ứng dụng có thể có tệp GoogleService-Info.plist
riêng.
Thêm SDK Firebase vào ứng dụng
Sử dụng Trình quản lý gói Swift để cài đặt và quản lý các phần phụ thuộc Firebase.
- Trong Xcode, khi dự án ứng dụng đang mở, hãy chuyển đến File > Add Packages (Tệp > Thêm gói).
- Khi được nhắc, hãy thêm kho lưu trữ SDK của các nền tảng Apple Firebase:
- Chọn thư viện Firebase Cloud Messaging.
- Thêm cờ
-ObjC
vào phần Other Linker Flags (Cờ trình liên kết khác) trong phần cài đặt bản dựng của mục tiêu. - Để có trải nghiệm tối ưu với Firebase Cloud Messaging, bạn nên bật Google Analytics trong dự án Firebase và thêm SDK Firebase cho Google Analytics vào ứng dụng. Bạn có thể chọn thư viện không có tính năng thu thập IDFA hoặc có tính năng thu thập IDFA.
- Khi hoàn tất, Xcode sẽ tự động bắt đầu phân giải và tải các phần phụ thuộc xuống ở chế độ nền.
https://github.com/firebase/firebase-ios-sdk.git
Tải khoá xác thực APN lên
Tải khoá xác thực APN lên Firebase. Nếu bạn chưa có khoá xác thực APNs, hãy nhớ tạo khoá trong Apple Developer Member Center.
-
Bên trong dự án của bạn trong bảng điều khiển Firebase, hãy chọn biểu tượng bánh răng, chọn Project Settings (Cài đặt dự án), sau đó chọn thẻ Cloud Messaging (Thông báo trên đám mây).
-
Trong phần Khoá xác thực APN thuộc Cấu hình ứng dụng iOS, hãy nhấp vào nút Tải lên.
-
Duyệt đến vị trí bạn đã lưu khoá, chọn khoá đó rồi nhấp vào Mở. Thêm mã khoá cho khoá (có trong Trung tâm thành viên dành cho nhà phát triển của Apple) rồi nhấp vào Tải lên.
Khởi động Firebase trong ứng dụng
Bạn cần thêm mã khởi chạy Firebase vào ứng dụng. Nhập mô-đun Firebase và định cấu hình một thực thể dùng chung như sau:
- Nhập mô-đun
FirebaseCore
trongUIApplicationDelegate
, cũng như mọi mô-đun Firebase khác mà ứng dụng của bạn sử dụng. Ví dụ: để sử dụng Cloud Firestore và 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; // ...
- Định cấu hình một bản sao dùng chung
FirebaseApp
trong phương thứcapplication(_:didFinishLaunchingWithOptions:)
của uỷ quyền ứng dụng: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];
- Nếu đang sử dụng SwiftUI, bạn phải tạo một trình uỷ quyền ứng dụng và đính kèm trình uỷ quyền đó vào cấu trúc
App
thông quaUIApplicationDelegateAdaptor
hoặcNSApplicationDelegateAdaptor
. Bạn cũng phải tắt tính năng hoán đổi ứng dụng uỷ quyền. Để biết thêm thông tin, hãy xem hướng dẫn về SwiftUI.SwiftUI
@main struct YourApp: App { // register app delegate for Firebase setup @UIApplicationDelegateAdaptor(AppDelegate.self) var delegate var body: some Scene { WindowGroup { NavigationView { ContentView() } } } }
Đăng ký nhận thông báo từ xa
Khi khởi động hoặc tại thời điểm mong muốn trong luồng ứng dụng, hãy đăng ký ứng dụng của bạn để nhận thông báo từ xa. GọiregisterForRemoteNotifications
như sau:
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];
Đăng ký ứng dụng khách cho một chủ đề
Ứng dụng khách có thể đăng ký bất kỳ chủ đề hiện có nào hoặc tạo một chủ đề mới. Khi một ứng dụng khách đăng ký tên chủ đề mới (chưa có trong dự án Firebase của bạn), một chủ đề mới có tên đó sẽ được tạo trong FCM và sau đó, mọi ứng dụng khách đều có thể đăng ký chủ đề đó.
Để đăng ký một chủ đề, hãy gọi phương thức đăng ký từ luồng chính của ứng dụng (FCM không an toàn về luồng). Nếu yêu cầu đăng ký ban đầu không thành công, FCM sẽ tự động thử lại. Trong trường hợp không thể hoàn tất gói thuê bao, gói thuê bao sẽ gửi một lỗi mà bạn có thể phát hiện trong trình xử lý hoàn tất như sau:
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"); }];
Lệnh gọi này thực hiện một yêu cầu không đồng bộ đến phần phụ trợ FCM và đăng ký ứng dụng với chủ đề đã cho. Trước khi gọi subscribeToTopic:topic
, hãy đảm bảo rằng thực thể ứng dụng khách đã nhận được mã thông báo đăng ký thông qua lệnh gọi lại didReceiveRegistrationToken
.
Mỗi khi ứng dụng khởi động, FCM sẽ đảm bảo rằng tất cả các chủ đề được yêu cầu đều đã được đăng ký. Để huỷ đăng ký, hãy gọi unsubscribeFromTopic:topic
và FCM sẽ huỷ đăng ký chủ đề trong nền.
Nhận và xử lý tin nhắn theo chủ đề
FCM phân phối thông báo theo chủ đề giống như các thông báo hạ nguồn khác.
Triển khai application(_:didReceiveRemoteNotification:fetchCompletionHandler:)
như sau:
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); }
Tạo yêu cầu gửi
Sau khi tạo một chủ đề, bạn có thể gửi thông báo đến chủ đề đó bằng cách đăng ký các thực thể ứng dụng khách cho chủ đề ở phía máy khách hoặc thông qua API máy chủ. Nếu đây là lần đầu tiên bạn tạo yêu cầu gửi cho FCM, hãy xem hướng dẫn về môi trường máy chủ và FCM để biết thông tin quan trọng về nền tảng và cách thiết lập.
Trong logic gửi ở phần phụ trợ, hãy chỉ định tên chủ đề mong muốn như sau:
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)
Tiến hành
// 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);
Kiến trúc chuyển trạng thái đại diện (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"
}
}
}
Lệnh 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
Để gửi thông báo đến một kết hợp các chủ đề, hãy chỉ định một điều kiện. Đây là một biểu thức boolean chỉ định các chủ đề mục tiêu. Ví dụ: điều kiện sau đây sẽ gửi thông báo đến các thiết bị đăng ký TopicA
và TopicB
hoặc TopicC
:
"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"
Trước tiên, FCM sẽ đánh giá mọi điều kiện trong dấu ngoặc đơn, sau đó đánh giá biểu thức từ trái sang phải. Trong biểu thức trên, người dùng đăng ký theo dõi một chủ đề bất kỳ sẽ không nhận được thông báo. Tương tự, người dùng không đăng ký TopicA
sẽ không nhận được thông báo. Các tổ hợp sau đây sẽ nhận được thông báo:
TopicA
vàTopicB
TopicA
vàTopicC
Bạn có thể đưa tối đa 5 chủ đề vào biểu thức có điều kiện.
Cách gửi đến một điều kiện:
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)
Tiến hành
// 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);
Kiến trúc chuyển trạng thái đại diện (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",
}
}
}
Lệnh 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
Các bước tiếp theo
- Bạn có thể sử dụng máy chủ để đăng ký các thực thể ứng dụng khách cho các chủ đề và thực hiện các tác vụ quản lý khác. Xem phần Quản lý gói thuê bao theo chủ đề trên máy chủ.