使用 Firebase Cloud Messaging 發送和接收 Flutter 應用程式的通知

一、簡介

最後更新: 2022-04-04

此 Codelab 將引導您完成使用 Flutter 透過 Firebase Cloud Messaging (FCM) 開發多平台應用程式的過程。您將編寫應用程式的一部分實現,然後在三個平台上建置並無縫運行它:Android、iOS 和 Web。您還將學習如何將 FCM 整合到 Flutter 中以及如何編寫程式碼來接收和發送訊息。最後,Codelab 介紹了 FCM HTTP v1 API 的平台特定區塊功能,該功能可讓您傳送一條在不同平台上具有不同行為的訊息。

先決條件

對 Flutter 的基本了解。

你將學到什麼

  • 如何設定和建立 Flutter 應用程式。
  • 如何新增 FCM 依賴項。
  • 如何將單一 FCM 訊息傳送到您的應用程式。
  • 如何將主題 FCM 訊息傳送到您的應用程式。

你需要什麼

  • 配置了 Dart 和 Flutter 外掛程式的Android Studio最新穩定版本。

您可以使用以下任何設備運行 Codelab:

(可選)要使用 iOS 平台運行 Codelab,您需要 iOS 裝置、Apple 開發者帳戶和安裝了 XCode 的 macOS 裝置。

2. 顫振設置

如果您已經設定了 Flutter 開發環境,請跳過本節。

若要設定 Flutter 開發環境,請依照下列步驟操作:

  1. 下載並安裝適合您作業系統的 Flutter:安裝 |撲
  2. 確保 Flutter 工具已新增到您的路徑中。
  3. 為 Flutter 設定編輯器,如設定編輯器 |所示。 Flutter請務必為您的編輯器安裝 Flutter 和 Dart 外掛。對於本 Codelab 的其餘部分,您將使用 Android Studio。
  4. 從命令列執行flutter doctor ,它會掃描您的設定並列出任何需要修復的缺失依賴項。按照說明修復任何重要的缺失依賴項。請注意,某些依賴項可能不是必需的。例如,如果您不打算為 iOS 進行開發,缺少 CocoaPods 依賴項不會成為阻塞問題。
  5. 執行此命令在fcmflutter目錄flutter create --org com.flutter.fcm --project-name fcmflutter fcmflutter中創建 Flutter 應用程序,然後將目錄更改為fcmflutter
  1. 在 Android Studio 中,前往File -> Open ,找到 Flutter 應用程式的路徑,然後按一下Open以在 Android Studio 中開啟專案。應用程式程式碼位於檔案lib/main.dart中。

在 Android Studio 工具列上,按一下向下箭頭以選擇 Android 裝置。如果目標選擇器為空,請安裝虛擬 Android 設備,或者如果您希望從 Web 瀏覽器或 iOS 設備啟動應用程序,請安裝Chrome 瀏覽器或 iOS 模擬器。您可能需要手動啟動設備並刷新清單才能找到目標設備。

Android Studio 工具列,其中反白顯示了建置目標選單下拉箭頭。

點擊運行Android Studio 中的運行按鈕啟動應用程式。

已啟動的 Flutter 演示應用程式的 UI

恭喜!您已成功建立 Flutter 應用程式。

3. Firebase 和 FlutterFire 設定

要使用 Flutter 開發與 Firebase Cloud Messaging 整合的應用,您需要:

  • Firebase 專案。
  • 一個有效的 Firebase CLI。
  • FlutterFire 的安裝。
  • 使用flutterfire configure配置和產生的應用程式。

建立您的 Firebase 項目

如果您已有 Firebase 項目,則可以跳過此步驟。

  1. 如果您有 Google 帳戶,請開啟Firebase並使用您的 Google 帳戶登錄,然後點擊前往控制台
  2. 在 Firebase 控制台中,按一下新增項目。按照說明建立項目。不要選取為此專案啟用 Google Analytics,因為您不會在此專案中使用它。
  3. 建立項目後,透過點擊項目概述旁邊的齒輪圖示導航到項目的項目設定

Firebase 控制台的裁剪螢幕截圖,突出顯示項目設定選單的圖示和

項目ID用於唯一標識項目,它可能與項目名稱不同。項目 ID將用於稍後設定 FlutterFire。

Firebase 控制台的裁剪螢幕截圖,突出顯示項目 ID

恭喜!您已成功建立 Firebase 專案。

設定 Firebase CLI

如果您已設定 Firebase CLI,則可以跳過此步驟。

前往Firebase CLI 參考以下載並安裝 Firebase CLI。使用以下命令使用您的 Google 帳戶登入 Firebase:

firebase login

設定 FlutterFire

  1. 使用指令安裝 FlutterFire 外掛: flutter pub add firebase_core
  2. 安裝FCM外掛: flutter pub add firebase_messaging
  3. 設定 FlutterFire CLI: dart pub global activate flutterfire_cli
  4. 在 Flutter 上設定 Firebase 專案: flutterfire configure --project=fcm4flutter.使用箭頭鍵和空白鍵選擇平台,或按 Enter 鍵使用預設平台。

此 Codelab 使用預設平台(Android、iOS 和 Web),但您只能選擇一兩個平台。如果提示輸入 iOS 捆綁包 ID,請輸入com.flutter.fcm.fcmflutter或您自己的 iOS 捆綁包 ID,格式為[company domain name].[project name] 。指令完成後,刷新 Firebase 控制台頁面。您將看到它已在 Firebase 專案下為所選平台建立了應用程式。

Firebase 控制台的裁剪螢幕截圖,顯示為所選平台建立的應用程式

指令在lib目錄下產生一個firebase_options.dart文件,其中包含初始化所需的所有選項。

設定 iOS 版雲端訊息傳遞

  1. 導覽至 Apple開發人員頁面,然後按一下「金鑰」標籤上的「建立金鑰」

Apple 開發者頁面的裁切螢幕截圖,突出顯示了用於建立金鑰的頁面元件

  1. 輸入金鑰的名稱並選取Apple 推播通知服務 (APN)Apple 開發者頁面的裁切螢幕截圖,突出顯示新金鑰名稱的文字框
  2. 下載金鑰文件,其文件副檔名為.p8Apple 開發者頁面的裁切螢幕截圖,突出顯示了下載金鑰的按鈕
  3. Firebase 控制台中,導覽至專案的「專案設定」並選擇「雲端訊息傳遞」標籤。

Firebase 控制台頁面的裁切螢幕截圖,突出顯示用於更新專案設定的元件

Firebase 控制台頁面的裁切螢幕截圖,突出顯示「雲端訊息傳遞」標籤

  1. 雲端訊息傳遞標籤中上傳 iOS 應用程式的 APNs 金鑰檔案。輸入「雲端訊息」標籤中的 APN 金鑰 ID 和團隊 ID(可在 Apple 會員中心找到)。 Firebase 控制台頁面的裁剪螢幕截圖,突出顯示用於上傳 APNs 驗證金鑰的按鈕

4. FCM 準備

在應用程式可以從 FCM 接收訊息之前,它需要:

  • 初始化 FlutterFire。
  • 請求通知權限。
  • 向 FCM 註冊以獲得註冊令牌。

初始化

若要初始化服務,請將 main 函數 ( lib/main.dart ) 替換為以下程式碼:

// core Flutter primitives
import 'package:flutter/foundation.dart';
// core FlutterFire dependency
import 'package:firebase_core/firebase_core.dart';
// generated by 
flutterfire configure
import 'firebase_options.dart';
// FlutterFire's Firebase Cloud Messaging plugin
import 'package:firebase_messaging/firebase_messaging.dart';

// TODO: Add stream controller
// TODO: Define the background message handler

Future<void> main() async {
 WidgetsFlutterBinding.ensureInitialized();
 await Firebase.initializeApp(
   options: DefaultFirebaseOptions.currentPlatform,
 );

 // TODO: Request permission
 // TODO: Register with FCM
 // TODO: Set up foreground message handler
 // TODO: Set up background message handler

 runApp(MyApp());
}

然後在 Android Studio 中執行Tools -> Flutter -> Flutter Pub Get來載入在Set up FlutterFire中新增的套件,並在 Android Studio 中使用適當的 Intellisense 設定顯示程式碼。

這會初始化目前平台的 FlutterFire DefaultFirebaseOptions.currentPlatform ,該平台是從生成的firebase_options.dart檔案導入的。請注意, initializeApp是一個非同步函數, await關鍵字確保在執行應用程式之前完成初始化。

請求許可

該應用程式需要徵求用戶的許可才能接收通知。 firebase_messaging提供的requestPermission方法會顯示一個對話框或彈出窗口,提示使用者允許或拒絕該權限。

首先,將此程式碼複製到註解TODO: Request permission下的 main 函數中。傳回的settings告訴您使用者是否已授予權限。我們建議僅當使用者需要使用需要存取權限的功能時(例如,當使用者在應用程式設定中開啟通知時)才請求權限。在此 Codelab 中,為簡單起見,我們請求應用程式啟動權限。

final messaging = FirebaseMessaging.instance;

final settings = await messaging.requestPermission(
 alert: true,
 announcement: false,
 badge: true,
 carPlay: false,
 criticalAlert: false,
 provisional: false,
 sound: true,
);

 if (kDebugMode) {
   print('Permission granted: ${settings.authorizationStatus}');
 }

接下來,在 Android Studio 工具列上,從目標選擇器中選擇Chrome (web) ,然後再次執行應用程式。

Android Studio 工具列的裁切螢幕截圖,其中包含目標選擇器和「運行」按鈕

然後,Chrome 標籤啟動,並彈出一個請求許可的視窗。如果按一下Allow ,您將在 Android Studio 控制台中看到一條日誌: Permission granted: AuthorizationStatus.authorized 。允許或阻止權限請求後,您的回應將與您的應用程式一起儲存在瀏覽器中,並且不會再次顯示彈出視窗。請注意,當您在 Android Studio 上再次執行 Web 應用程式時,系統可能會再次提示您授予權限。 Chrome 標籤頁的裁切螢幕截圖,其中有一個彈出視窗要求

登記

將此程式碼複製到註解TODO: Register with FCM下方的 main 函數中以向 FCM 註冊。 getToken呼叫傳回一個註冊令牌,應用程式伺服器或受信任的伺服器環境可以使用該令牌向使用者傳送訊息。

// It requests a registration token for sending messages to users from your App server or other trusted server environment.
String? token = await messaging.getToken();

if (kDebugMode) {
  print('Registration Token=$token');
}

在 Android Studio 工具列上,選擇 Android 裝置並執行應用程式。在 Android Studio 控制台中,註冊令牌列印如下:

I/flutter ( 3717): Permission granted: AuthorizationStatus.authorized
I/flutter ( 3717): Registration Token=dch. . . D2P:APA9. . .kbb4

將其複製到文字編輯器,因為稍後您將使用它來發送訊息。

uses-sdk:minSdkVersion 16 cannot be smaller than version 19 declared in library [:firebase_messaging]

在網路上接收訊息的額外步驟

Web 應用程式需要兩個額外的步驟來取得註冊權杖並偵聽傳入訊息。 Web 需要將 VAPID 金鑰傳遞給getToken才能授權向支援的 Web 推送服務發送請求。

首先,在 Firebase 控制台中開啟 Firebase 專案的Cloud Messaging選項卡,向下捲動至Web 設定部分以尋找現有金鑰對,或產生新的金鑰對。點擊突出顯示的按鈕複製金鑰,以便將其用作 vapidKey。

Web 設定頁面的 Web 推送憑證元件的裁剪螢幕截圖,突出顯示了金鑰對

接下來,將註冊部分中的註冊代碼替換為以下程式碼,然後更新 vapidKey:

// TODO: replace with your own VAPID key
 const vapidKey = "<YOUR_PUBLIC_VAPID_KEY_HERE>";

 // use the registration token to send messages to users from your trusted server environment
 String? token;

 if (DefaultFirebaseOptions.currentPlatform == DefaultFirebaseOptions.web) {
   token = await messaging.getToken(
     vapidKey: vapidKey,
   );
 } else {
   token = await messaging.getToken();
 }

 if (kDebugMode) {
   print('Registration Token=$token');
 }

然後,在專案根目錄的web/目錄下建立一個firebase-messaging-sw.js檔案。將以下內容複製到firebase-messaging-sw.js以允許 Web 應用程式接收onMessage事件。有關更多信息,請參閱在 Service Worker 中設定通知選項

importScripts("https://www.gstatic.com/firebasejs/9.6.10/firebase-app-compat.js");
importScripts("https://www.gstatic.com/firebasejs/9.6.10/firebase-messaging-compat.js");

// todo Copy/paste firebaseConfig from Firebase Console
const firebaseConfig = {
 apiKey: "...",
 authDomain: "...",
 databaseURL: "...",
 projectId: "...",
 storageBucket: "...",
 messagingSenderId: "...",
 appId: "...",
};

firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();

// todo Set up background message handler

之後,在Project Settings -> General標籤下,向下捲動並找到Web App ,複製firebaseConfig程式碼部分並將其貼到firebase-messaging-sw.js中。 Firebase 設定頁面的 Web 應用程式元件的裁剪螢幕截圖

最後,在 Android Studio 工具列上,在目標選擇器中選擇Chrome (web)並執行應用程式。在 Android Studio 控制台中,註冊令牌列印如下:

Debug service listening on ws://127.0.0.1:61538/BLQQ3Fg-h7I=/ws
Permission granted: AuthorizationStatus.authorized
Registration Token=fH. . .ue:APA91. . .qwt3chpv

將註冊令牌複製到文字編輯器中,以便稍後可以使用它來發送訊息。

在 iOS 上接收訊息的額外步驟

若要從 FCM 接收訊息,iOS 裝置需要在 Xcode 上啟用推播通知後台模式

  1. 在 Android Studio 中,右鍵點選專案名稱,然後選擇Flutter -> Open iOS module in Xcode裁剪後的螢幕截圖
  2. Xcode 啟動後,在專案目標的「簽章和功能」標籤中啟用推播通知背景模式。有關詳細信息,請參閱配置您的應用程式
  3. 在 Android Studio 工具列上,在目標選擇器中選擇 iOS 裝置並執行應用程式。授予通知權限後,註冊令牌將列印在 Android Studio 控制台中。

請求發送通知權限的 iOS 應用程式的裁切螢幕截圖

恭喜,您已成功向 FCM 註冊您的應用程式。您已準備好接收訊息,如下一節所述。

5.接收FCM的訊息

設定訊息處理程序

當應用程式處於前台模式時訊息到達時,應用程式需要處理onMessage事件;當應用程式處於背景模式時,應用程式需要處理onBackgroundMessage事件。

前台訊息處理程序

首先,在檔案main.dart中的註解TODO: Add stream controller ,以便將訊息從事件處理程序傳遞到 UI。

import 'package:rxdart/rxdart.dart';
// used to pass messages from event handler to the UI
final _messageStreamController = BehaviorSubject<RemoteMessage>();

若要新增相依性 rxdart,請從專案目錄執行下列指令: flutter pub add rxdart

接下來,在 Android Studio 中執行Tools -> Flutter -> Flutter Pub Get來載入rxdart.dart套件,並在 Android Studio 中使用適當的 Intellisense 設定顯示程式碼。

然後,在註解TODO: Set up foreground message handler後面新增一個事件處理程序來偵聽前台訊息。它會列印日誌並將訊息發佈到流控制器。

 FirebaseMessaging.onMessage.listen((RemoteMessage message) {
   if (kDebugMode) {
     print('Handling a foreground message: ${message.messageId}');
     print('Message data: ${message.data}');
     print('Message notification: ${message.notification?.title}');
     print('Message notification: ${message.notification?.body}');
   }

   _messageStreamController.sink.add(message);
 });

之後,用此程式碼取代檔案main.dart中的原始 State 小工具,這會將訂閱者新增至 State 小工具中的串流控制器,並在小工具上顯示最後一則訊息。

class _MyHomePageState extends State<MyHomePage> {
 String _lastMessage = "";

 _MyHomePageState() {
   _messageStreamController.listen((message) {
     setState(() {
       if (message.notification != null) {
         _lastMessage = 'Received a notification message:'
             '\nTitle=${message.notification?.title},'
             '\nBody=${message.notification?.body},'
             '\nData=${message.data}';
       } else {
         _lastMessage = 'Received a data message: ${message.data}';
       }
     });
   });
 }

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text(widget.title),
     ),
     body: Center(
       child: Column(
         mainAxisAlignment: MainAxisAlignment.center,
         children: <Widget>[
           Text('Last message from Firebase Messaging:',
               style: Theme.of(context).textTheme.titleLarge),
           Text(_lastMessage, style: Theme.of(context).textTheme.bodyLarge),
         ],
       ),
     ),
   );
 }
}

適用於 Android/iOS 的後台訊息處理程序

當應用程式處於背景時,訊息由onBackgroundMessage處理程序處理。處理程序應該是頂級函數。當應用程式進入前台時,可以透過處理訊息(請參閱處理互動)或與應用程式伺服器同步來更新 UI。

在註解TODO: Define the background message handler程序,並在註解TODO: Set up background message handler之後在主函數中呼叫它。

// TODO: Define the background message handler
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
 await Firebase.initializeApp();

 if (kDebugMode) {
   print("Handling a background message: ${message.messageId}");
   print('Message data: ${message.data}');
   print('Message notification: ${message.notification?.title}');
   print('Message notification: ${message.notification?.body}');
 }
}

void main() {
 ...

 // TODO: Set up background message handler
 FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

 runApp(MyApp());
}

Web 後台訊息處理程序

從 FlutterFire firebase_messaging版本 11.2.8 開始,在基於 Web 的平台上處理後台訊息需要不同的流程。因此,您需要在服務工作執行緒web/firebase-messaging-sw.js中新增單獨的訊息處理程序。

messaging.onBackgroundMessage((message) => {
 console.log("onBackgroundMessage", message);
});

設定應用程式伺服器

  1. 透過在 Android Studio 中開啟 https://github.com/FirebaseExtended/firebase_fcm_flutter/tree/main/server 專案來匯入起始伺服器程式碼。該伺服器是一個基於 Gradle 的 Java 項目,依賴firebase-admin SDK,它提供 FCM 訊息發送功能。
  2. 設定一個 Firebase 服務帳戶,讓 Firebase 管理 SDK 授權對 FCM API 的呼叫。在 Firebase 控制台中開啟「專案設定」 ,然後選擇「服務帳戶」標籤。選擇“Java”並點擊Generate new private key以下載配置片段。 裁切後的螢幕截圖,突出顯示專案設定頁面的服務帳戶元件的管理 SDK 設定片段
  3. 將檔案重新命名為service-account.json並將其複製到伺服器專案的src/main/resources路徑中。

發送測試訊息

FcmSender.java檔案中, sendMessageToFcmRegistrationToken將通知訊息與資料負載組合在一起。註冊令牌針對訊息傳送到的應用程式實例。

private static void sendMessageToFcmRegistrationToken() throws Exception {
   String registrationToken = "REPLACE_WITH_FCM_REGISTRATION_TOKEN";
   Message message =
       Message.builder()
           .putData("FCM", "https://firebase.google.com/docs/cloud-messaging")
           .putData("flutter", "https://flutter.dev/")
           .setNotification(
               Notification.builder()
                   .setTitle("Try this new app")
                   .setBody("Learn how FCM works with Flutter")
                   .build())
           .setToken(registrationToken)
           .build();

   FirebaseMessaging.getInstance().send(message);

   System.out.println("Message to FCM Registration Token sent successfully!!");
 }
  1. 複製從註冊部分複製的 Android 註冊令牌,並將其貼上到變數registrationToken的值中。
  2. 點擊運行Android Studio 中的運行按鈕執行 main 函數並透過 FCM 向使用者發送訊息。 Android Studio 中 FcmSender.java 主函數旁邊顯示的運行圖示的裁切螢幕截圖

當 Android 應用程式在背景運行時,該訊息將顯示在通知托盤中。

Android 通知托盤中顯示的訊息的裁剪螢幕截圖

當 Android 應用程式位於前台時,您將在 Android Studio 控制台中看到一條日誌:「處理前台訊息」。訊息內容也會顯示在 UI 中,因為 UI 訂閱了流控制器以取得新訊息。

Android 應用程式中顯示的訊息內容的裁切螢幕截圖

如果您貼上註冊令牌並從應用程式伺服器或其他受信任的伺服器環境發送訊息,您將看到類似的行為:

  • 當網路應用程式在背景時(即,當它被另一個視窗隱藏或另一個標籤處於活動狀態時),您將看到網路通知。

Chrome 瀏覽器中顯示的網路通知的裁切螢幕截圖

  • 當 Web 應用程式位於前台時,您可以透過右鍵點擊 Web 並選擇Inspect在 Chrome 控制台中查看日誌。訊息內容也會顯示在 UI 中。 帶有調試日誌的 Chrome 控制台的裁剪螢幕截圖

6.發送主題訊息

FCM HTTP v1 API 的平台覆蓋功能使訊息傳送請求在不同平台上具有不同的行為。此功能的一個用例是根據平台顯示不同的通知訊息內容。當主題訊息傳遞針對多個裝置(可能跨越多個平台)時,該功能得到最充分的利用。本部分將引導您完成使您的應用程式接收為每個平台定制的主題訊息的步驟。

訂閱客戶端的主題

要訂閱主題,請在 Flutter 應用程式的main.dart檔案中的 main 函數末尾呼叫messaging.subscribeToTopic方法。

// subscribe to a topic.
const topic = 'app_promotion';
await messaging.subscribeToTopic(topic);

[可選] 從 Web 伺服器訂閱主題

如果您不是在Web平台上開發,可以跳過本節。

FCM JS SDK 目前不支援客戶端主題訂閱。相反,您可以使用 Admin SDK 的伺服器端主題管理 API 進行訂閱。此程式碼說明了使用 Java Admin SDK 進行伺服器端主題訂閱。

 private static void subscribeFcmRegistrationTokensToTopic() throws Exception {
   List<String> registrationTokens =
       Arrays.asList(
           "REPLACE_WITH_FCM_REGISTRATION_TOKEN"); // TODO: add FCM Registration Tokens to
   // subscribe
   String topicName = "app_promotion";

   TopicManagementResponse response =     FirebaseMessaging.getInstance().subscribeToTopic(registrationTokens, topicName);
   System.out.printf("Num tokens successfully subscribed %d", response.getSuccessCount());
 }

打開應用程式伺服器並點擊運行Android Studio 中的運行按鈕執行FcmSubscriptionManager.java檔案中的 main 函數:

Android Studio 中 FcmSubscriptionManager.java 主函數旁邊顯示的「執行」圖示的裁切螢幕截圖

向主題發送帶有平台覆蓋的訊息

現在您已準備好發送主題平台覆蓋訊息。在下面的程式碼片段中:

  • 您使用基本訊息和標題「 A new app is available 」來建立發送請求。
  • 該訊息會在 iOS 和 Web 平台上產生標題為「 A new app is available 」的顯示通知。
  • 該訊息會在 Android 裝置上產生標題為「 A new Android app is available 」的顯示通知。
private static void sendMessageToFcmTopic() throws Exception {
   String topicName = "app_promotion";

   Message message =
       Message.builder()
           .setNotification(
               Notification.builder()
                   .setTitle("A new app is available")
                   .setBody("Check out our latest app in the app store.")
                   .build())
           .setAndroidConfig(
               AndroidConfig.builder()
                   .setNotification(
                       AndroidNotification.builder()
                           .setTitle("A new Android app is available")
                           .setBody("Our latest app is available on Google Play store")
                           .build())
                   .build())
           .setTopic("app_promotion")
           .build();

   FirebaseMessaging.getInstance().send(message);

   System.out.println("Message to topic sent successfully!!");
 }

FcmSender.java檔的main函式中,取消註解sendMessageToFcmTopic(); 。點擊運行Android Studio 中的運行按鈕發送主題訊息。

7. 總結與下一步

總而言之,您已經了解如何使用 Flutter 和 FCM 進行多平台應用程式開發,其中包括環境設定、依賴項整合以及訊息接收和發送。若要深入了解,請參閱以下資料:

代碼實驗室

參考