透過 Apple 平台將訊息傳送至多部裝置

如要指定訊息給多部裝置,請使用 主題訊息:這個 功能 傳送訊息給已選擇加入特定主題的多部裝置。

本教學課程著重於使用如何從應用程式伺服器傳送主題訊息: Admin SDKREST API 以接收及處理 FCM 。本頁面將列出從設定到執行的所有步驟 其中可能包含你已完成的步驟 (如果有的話) 為 FCM設定 Apple 用戶端應用程式 或按照傳送第一則訊息的步驟。

將 Firebase 新增至您的 Apple 專案

這個部分涵蓋您已啟用的 還有應用程式適用的其他 Firebase 功能針對 FCM,您應該 需要 上傳 APN 驗證金鑰註冊遠端通知

事前準備

  • 安裝下列項目:

    • Xcode 15.2 以上版本
  • 確認專案符合下列規定:

    • 您的專案必須指定下列平台版本或更新版本:
      • iOS 13
      • macOS 10.15
      • tvOS 13
      • watchOS 7
  • 設定實體 Apple 裝置執行應用程式。 並完成以下工作:

  • 使用 Google 帳戶。

如果您沒有 Xcode 專案,只想試用 Firebase 產品,您可以下載其中一個快速入門導覽課程範例

建立 Firebase 專案

您需要先建立 Firebase,才能將 Firebase 新增到 Apple 應用程式 連線至應用程式前往 如要進一步瞭解 Firebase 專案,請參閱這篇文章 Firebase 專案。

透過 Firebase 註冊應用程式

如要在 Apple 應用程式中使用 Firebase,請向以下應用程式註冊應用程式: Firebase 專案。註冊應用程式通常稱為「新增」將應用程式 專案。

  1. 前往 Firebase 控制台

  2. 按一下專案總覽頁面中央的「iOS+」圖示 啟動設定工作流程

    如果您已在 Firebase 專案中加入應用程式,請按一下「新增應用程式」 顯示平台選項

  3. 在「bundle ID」欄位中輸入應用程式的軟體包 ID。

    ,瞭解如何調查及移除這項存取權。
  4. (選用) 輸入其他應用程式資訊: 「應用程式暱稱」和「App Store ID」

  5. 按一下 [Register app] (註冊應用程式)

新增 Firebase 設定檔

  1. 點選「Download GoogleService-Info.plist」,取得 Firebase Apple 平台設定檔 (GoogleService-Info.plist)。

  2. 將設定檔移至 Xcode 專案的根目錄。如果出現提示訊息 選取即可將設定檔新增至所有目標。

如果專案中有多個軟體包 ID,就必須將每個軟體包建立關聯 與 Firebase 控制台中已註冊應用程式的 ID,讓每個應用程式可擁有 自己的 GoogleService-Info.plist 檔案

在應用程式中新增 Firebase SDK

使用 Swift Package Manager 安裝及管理 Firebase 依附元件。

  1. 在 Xcode 中保持開啟應用程式專案,然後前往「檔案」檔案 >新增套件
  2. 在系統提示時,新增 Firebase Apple 平台 SDK 存放區:
  3.   https://github.com/firebase/firebase-ios-sdk.git
    敬上
  4. 選擇 Firebase Cloud Messaging 程式庫。
  5. 在目標建構設定的「Other Linker Flags」部分中新增 -ObjC 標記。
  6. 為透過 Firebase Cloud Messaging 獲得最佳體驗,建議你 正在啟用 Google Analytics ,然後將 Google Analytics 專用 Firebase SDK 加進應用程式。你可以 選取沒有收集廣告識別碼 (IDFA) 或收集廣告識別碼的程式庫。
  7. 完成後,Xcode 會自動開始解析並下載 複製到背景依附元件

上傳 APN 驗證金鑰

將 APN 驗證金鑰上傳至 Firebase。 如果您還沒有 APN 驗證金鑰,請務必前往 Apple Developer Member Center

  1. Firebase 控制台的專案中,選取 齒輪圖示,選取 「Project Settings」,然後選取 「雲端通訊」分頁。

  2. 在「iOS 應用程式設定」下方的「APNs 驗證金鑰」中, 按一下「上傳」圖示 按鈕。

  3. 瀏覽至儲存金鑰的位置並選取金鑰,然後按一下 開啟。加入金鑰的金鑰 ID (位於 Apple Developer Member Center 時,按一下 按一下「上傳」

在應用程式中初始化 Firebase

您必須將 Firebase 初始化程式碼加進應用程式。匯入 並設定共用執行個體,如下所示:

  1. FirebaseCore 模組匯入至 UIApplicationDelegate和任何其他 應用程式委派所用的 Firebase 模組。 例如,如要使用 Cloud FirestoreAuthentication

    SwiftUI

    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:) 方法:

    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];
  3. 如果您使用 SwiftUI,則必須建立並附加應用程式委派 透過 UIApplicationDelegateAdaptorApp NSApplicationDelegateAdaptor。您也必須停用應用程式委派功能切換功能。適用對象 詳情請參閱 SwiftUI 操作說明

    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 專案尚不存在的新主題,但這個名稱的新主題會是 在 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 前,請確認 用戶端應用程式執行個體已透過 回呼 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

如要傳送訊息給主題的組合, 指定條件,這是一種布林值運算式,可以指定 指定主題。舉例來說,當郵件符合下列條件時, 訂閱 TopicATopicBTopicC 的裝置:

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

FCM 會先評估括號中的任何條件,���後進行評估 運算式則從左到右依序為在上述運算式中,有一位使用者訂閱 任何主題都不會收到訊息。同樣地,如果使用者未 訂閱 TopicA 並未收到訊息。這些組合 收到:

  • TopicATopicB
  • TopicATopicC

條件運算式最多可加入五個主題。

如要傳送至條件:

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

後續步驟