Gửi tin nhắn tới nhiều thiết bị trên nền tảng Apple

Để nhắm mục tiêu tin nhắn đến nhiều thiết bị, hãy sử dụng Tin nhắn theo chủ đề . Tính năng này cho phép bạn gửi tin nhắn đến nhiều thiết bị đã chọn tham gia vào một chủ đề cụ thể.

Hướng dẫn này tập trung vào việc gửi thông báo chủ đề từ máy chủ ứng dụng của bạn bằng SDK quản trị hoặc API REST cho FCM, đồng thời nhận và xử lý chúng trong ứng dụng Apple. Trang này liệt kê tất cả các bước để đạt được điều 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 thành nếu bạn đã thiết lập ứng dụng khách Apple cho FCM hoặc đã thực hiện các bước Gửi tin nhắn đầu tiên của mình .

Thêm Firebase vào dự án Apple của bạn

Phần này bao gồm các nhiệm vụ bạn có thể đã hoàn thành nếu bạn đã bật các tính năng Firebase khác cho ứng dụng của mình. Cụ thể đối với FCM, bạn sẽ cần tải khóa xác thực APN của mình lênđăng ký nhận thông báo từ xa .

Điều kiện tiên quyết

  • Cài đặt như sau:

    • Xcode 14.1 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 mục tiêu các phiên bản nền tảng này trở lên:
      • iOS 11
      • macOS 10.13
      • tvOS 12
      • watchOS 6
  • Thiết lập thiết bị Apple vật lý để chạy ứng dụng của bạn và hoàn thành các tác vụ sau:

Nếu bạn chưa có dự án Xcode và chỉ muốn dùng thử sản phẩm Firebase, bạn có thể tải xuống một trong các mẫu bắt đầu nhanh của chúng tôi.

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 dự án Firebase để kết nối với ứng dụng của mình. Truy cập Tìm hiểu dự án Firebase để tìm hiểu thêm về các 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 với dự án Firebase của mình. Đăng ký ứng dụng của bạn thường được gọi là "thêm" ứng dụng vào dự án của bạn.

  1. Chuyển đến bảng điều khiển Firebase .

  2. Ở giữa trang tổng quan dự án, hãy nhấp vào biểu tượng iOS+ để khởi chạy quy trình thiết lập.

    Nếu bạn đã thêm ứng dụng vào dự án Firebase của mình, hãy nhấp vào Thêm ứng dụng để hiển thị các tùy chọn nền tảng.

  3. Nhập ID gói ứng dụng của bạn vào trường ID gói .

  4. (Tùy chọn) Nhập thông tin ứng dụng khác: Biệt hiệu ứng dụngID App Store .

  5. Nhấn vào Đăng ký ứng dụng .

Thêm tệp cấu hình Firebase

  1. Nhấp vào Tải xuống GoogleService-Info.plist để lấy tệp cấu hình nền tảng Firebase Apple của bạn ( GoogleService-Info.plist ).

  2. Di chuyển tệp cấu hình của bạn vào thư mục gốc của dự án Xcode của bạn. 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 ID gói trong dự án của mình, bạn phải liên kết từng ID 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 của bạn

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 của Firebase.

  1. Trong Xcode, khi dự án ứng dụng của bạn đang mở, hãy điều hướng đến File > Add Packages .
  2. Khi được nhắc, hãy thêm kho lưu trữ SDK nền tảng Firebase của Apple:
  3.   https://github.com/firebase/firebase-ios-sdk.git
  4. Chọn thư viện Nhắn tin qua đám mây Firebase.
  5. Thêm cờ -ObjC vào phần Cờ liên kết khác trong cài đặt bản dựng của mục tiêu của bạn.
  6. Để có trải nghiệm tối ưu với Nhắn tin qua đám mây của Firebase, chúng tôi khuyên 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 của mình. Bạn có thể chọn thư viện không có bộ sưu tập IDFA hoặc có bộ sưu tập IDFA.
  7. Khi hoàn tất, Xcode sẽ tự động bắt đầu phân giải và tải xuống các phần phụ thuộc của bạn ở chế độ nền.

Tải khóa xác thực APN của bạn lên

Tải khóa xác thực APN của bạn lên Firebase. Nếu bạn chưa có khóa xác thực APN, hãy đảm bảo tạo một khóa trong Trung tâm thành viên nhà phát triển của Apple .

  1. 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 Cài đặt dự án rồi chọn tab Nhắn tin qua đám mây .

  2. Trong khóa xác thực APN trong cấu hình ứng dụng iOS , hãy nhấp vào nút Tải lên .

  3. Duyệt đến vị trí bạn đã lưu khóa, chọn nó và nhấp vào Mở . Thêm ID khóa cho khóa (có sẵn trong Apple Developer Member Center ) và nhấp vào Tải lên .

Khởi tạo Firebase trong ứng dụng của bạn

Bạn sẽ cần thêm mã khởi tạo Firebase vào ứng dụng của mình. Nhập mô-đun Firebase và định cấu hình phiên bản dùng chung như được hiển thị:

  1. Nhập mô-đun FirebaseCore trong UIApplicationDelegate của bạn, cũng như bất kỳ mô-đun Firebase nào khác mà ủy quyền ứng dụng của bạn sử dụng. Ví dụ: để sử dụng Cloud Firestore và Xác thực:

    SwiftUI

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

    Nhanh

    import FirebaseCore
    import FirebaseFirestore
    import FirebaseAuth
    // ...
          

    Mục tiêu-C

    @import FirebaseCore;
    @import FirebaseFirestore;
    @import FirebaseAuth;
    // ...
          
  2. Định cấu hình phiên bản chia sẻ FirebaseApp trong phương thức application(_:didFinishLaunchingWithOptions:) của đại biểu ứng dụng của bạn:

    SwiftUI

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

    Nhanh

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

    Mục tiêu-C

    // Use Firebase library to configure APIs
    [FIRApp configure];
  3. Nếu bạn đang sử dụng SwiftUI, bạn phải tạo một đại biểu ứng dụng và đính kèm nó vào cấu trúc App của mình thông qua UIApplicationDelegateAdaptor hoặc NSApplicationDelegateAdaptor . Bạn cũng phải tắt chức năng chuyển giao ứng dụng. Để biết thêm thông tin, hãy xem hướng dẫn 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 của bạn, hãy đăng ký ứng dụng của bạn để nhận thông báo từ xa. Gọi registerForRemoteNotifications như được hiển thị:

Nhanh


UNUserNotificationCenter.current().delegate = self

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

application.registerForRemoteNotifications()

Mục tiêu-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 theo một chủ đề

Ứng dụng khách có thể đăng ký bất kỳ chủ đề hiện có nào hoặc có thể tạo chủ đề mới. Khi ứng dụng khách đăng ký tên chủ đề mới (tên chủ đề chưa tồn tại cho dự án Firebase của bạn), chủ đề mới có tên đó sẽ được tạo trong FCM và sau đó bất kỳ khách hàng nào cũng có thể đăng ký tên đó.

Để đă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 của bạn (FCM không an toàn cho 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. Đối với trường hợp không thể hoàn thành đăng ký, đăng ký sẽ đưa ra một lỗi mà bạn có thể gặp trong trình xử lý hoàn thành như được hiển thị:

Nhanh

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

Mục tiêu-C

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

Cuộc gọi này thực hiện một yêu cầu không đồng bộ tới phần phụ trợ FCM và đăng ký khách hàng theo chủ đề đã cho. Trước khi gọi subscribeToTopic:topic , hãy đảm bảo rằng phiên bản ứ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 đảm bảo rằng tất cả các chủ đề được yêu cầu đều đã được đăng ký. Để hủy đăng ký, hãy gọi unsubscribeFromTopic:topic và FCM hủy đăng ký chủ đề ở chế độ nền.

Nhận và xử lý tin nhắn chủ đề

FCM gửi các thông điệp chủ đề theo cách tương tự như các thông điệp xuôi dòng khác.

Triển khai application(_:didReceiveRemoteNotification:fetchCompletionHandler:) như được hiển thị:

Nhanh

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
}

Mục tiêu-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);
}

Xây dựng yêu cầu gửi

Sau khi bạn đã tạo một chủ đề, bằng cách đăng ký các phiên bản ứng dụng khách cho chủ đề ở phía máy khách hoặc thông qua API máy chủ , bạn có thể gửi tin nhắn đến chủ đề. Nếu đây là lần đầu tiên bạn xây dựng yêu cầu gửi FCM, hãy xem hướng dẫn về môi trường máy chủ và FCM của bạn để biết thông tin cơ bản và thiết lập quan trọng.

Trong logic gửi của bạn ở phần phụ trợ, hãy chỉ định tên chủ đề mong muốn như được hiển thị:

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)

Đi

// 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);

NGHỈ NGƠI

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 tin nhắn đến một tổ hợp các chủ đề, hãy chỉ định một điều kiện , đây là biểu thức boolean chỉ định các chủ đề đích. Ví dụ: điều kiện sau sẽ gửi tin nhắn đến các thiết bị đã đăng ký TopicATopicB hoặc TopicC :

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

Trước tiên FCM đánh giá mọi điều kiện trong 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ý bất kỳ chủ đề nào sẽ không nhận được tin nhắn. Tương tự, người dùng không đăng ký TopicA sẽ không nhận được tin nhắn. Những kết hợp này nhận được nó:

  • TopicATopicB
  • TopicATopicC

Bạn có thể bao gồm tối đa năm chủ đề trong biểu thức điều kiện của mình.

Để 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)

Đi

// 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);

NGHỈ NGƠI

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

Bước tiếp theo