開始在 Flutter 應用程式中使用 Firebase 雲端通訊

選取平台: iOS+ Android 網頁 Flutter Unity C++


本指南說明如何在 Flutter 用戶端應用程式中開始使用 Firebase Cloud Messaging,以便可靠地傳送訊息。

視您指定的平台而定,您可能需要採取一些額外的必要設定步驟。

iOS+

方法交換

如要在 Apple 裝置上使用 FCM Flutter 外掛程式,必須採用方法交換。否則 FCM 註冊處理等 Firebase 關鍵功能將無法正常運作。

Android

Google Play 服務

FCM 用戶端需要搭載 Android 7.0 以上版本且已安裝 Google Play 服務的裝置,或搭載 Android 7.0 且具備 Google API 的模擬器。請注意,您不一定要透過 Google Play 商店部署 Android 應用程式。

如果應用程式仰賴 Play 服務 SDK,則應一律先檢查裝置是否有相容的 Google Play 服務 APK,再存取 Google Play 服務功能。建議您在兩個位置執行這項操作:主要活動的 onCreate() 方法和 onResume() 方法。onCreate() 中的檢查可確保應用程式在檢查成功後才能使用。onResume() 中的檢查可確保使用者透過其他方式 (例如返回按鈕) 返回執行中的應用程式時,仍會執行檢查。

如果裝置沒有相容版本的 Google Play 服務,應用程式可以呼叫 GoogleApiAvailability.makeGooglePlayServicesAvailable(),讓使用者從 Play 商店下載 Google Play 服務。

網頁

使用 FCM 設定網路憑證

FCM 網頁介面會使用稱為「自願應用程式伺服器識別」或「VAPID」金鑰的網頁憑證,授權傳送要求至支援的網頁推播服務。如要讓應用程式訂閱推播通知,您必須將一組金鑰與 Firebase 專案建立關聯。您可以透過 Firebase 控制台產生新的金鑰組,或匯入現有的金鑰組。

安裝 FCM 外掛程式

  1. 如果尚未安裝及初始化 Flutter 適用的 Firebase 外掛程式,請先完成這項操作。

  2. 在 Flutter 專案的根目錄中,執行下列指令來安裝外掛程式:

    flutter pub add firebase_messaging
    
  3. 完成後,請重建 Flutter 應用程式:

    flutter run
    

要求通知權限

如要將通知訊息傳送至裝置,您必須使用 register() 向 FCM 註冊裝置。如果尚未授予通知權限,這個方法會要求使用者授予通知權限。否則,系統會在成功時透過 onRegistered 傳送 FID,或因錯誤而拒絕 Future。

之前,無法保證已收到 APNs 權杖。
// You may set the permission requests to "provisional" which allows the user to choose what type
// of notifications they would like to receive once the user receives a notification.
final notificationSettings = await FirebaseMessaging.instance.requestPermission(provisional: true);

// For apple platforms, make sure the APNS token is available before making any FCM plugin API calls
final apnsToken = await FirebaseMessaging.instance.getAPNSToken();
if (apnsToken != null) {
 // APNS token is available, make FCM plugin API requests...
}

存取 Firebase 安裝 ID

啟用使用 Firebase 安裝 ID 註冊的功能

如要使用 Firebase 安裝 ID (FID) 啟用應用程式例項向 FCM 註冊的功能,請先在 Android 和 Apple 平台的應用程式設定中啟用 FID (網頁上不需要靜態選擇加入設定):

Android

在 AndroidManifest.xml 的 <application> 元素中加入下列 <meta-data> 元素:

<meta-data android:name="firebase_messaging_installation_id_enabled"
           android:value="true" />

iOS+

在 Info.plist 中新增 FirebaseMessagingInstallationIdEnabled 鍵,並將其設為 true (YES):

<key>FirebaseMessagingInstallationIdEnabled</key>
<true/>

訂閱 onRegistered 串流

如要將訊息傳送至特定裝置上的應用程式執行個體,您需要該應用程式執行個體向 FCM 註冊後的 Firebase 安裝 ID (FID)。FID 會透過 onRegistered 串流以非同步方式傳送。

在 Android 和 Apple 平台上,如果啟用自動初始化功能 (預設),FCM 會在啟動時自動註冊應用程式執行個體。不過,您必須明確呼叫 register():

  • 在網頁上。您可以選擇傳遞 vapidKey 和 serviceWorkerScriptPath。
  • 在 Android 和 Apple 平台上,如果自動初始化功能已停用,或在呼叫 unregister() 後。您也可以隨時呼叫 register(),使用已註冊的 FID 觸發 onRegistered。

請務必先訂閱 onRegistered 再呼叫 register(),確保在發出註冊事件時,接聽程式處於啟用狀態:

final messaging = FirebaseMessaging.instance;

messaging.onRegistered
    .listen((String installationId) {
      // TODO: Send the Firebase Installation ID (FID) to your application server.
    })
    .onError((err) {
      // Error getting Firebase Installation ID.
    });

// Required on Web, and on Android/Apple if auto-initialization is disabled.
await messaging.register(
  // Optional on Web (ignored on Android and Apple platforms)
  vapidKey: "BKagOny0KF_2pCJQ3m....moL0ewzQ8rZu",
);

在下列情況下,onRegistered 串流會發出 FID:

  1. 在 Android 和 Apple 平台上,如果啟用自動初始化功能,系統會在應用程式首次啟動時自動初始化,並定期同步。
  2. 每次手動 register() 呼叫完成時 (即使應用程式執行個體已註冊,onRegistered 仍會發出已註冊的 FID)。
  3. 每當系統偵測到 Firebase 安裝 ID 變更,且應用程式重新向 FCM 註冊時,或是在網頁上觸發 pushsubscriptionchange 事件時。

取得 Firebase 安裝 ID (FID) 後,請將其傳送至應用程式伺服器,並使用偏好的方法儲存。

存取註冊權杖 (已淘汰)

如要傳送訊息到特定裝置,您必須知道裝置的註冊權杖。如要擷取應用程式執行個體的註冊權杖,請呼叫 getToken()。如果尚未授予通知權限,這個方法會要求使用者授予通知權限。否則,系統會傳回權杖,或因錯誤而拒絕 Future。

在網頁平台上,將 VAPID 公開金鑰傳遞至 getToken():

final fcmToken = await FirebaseMessaging.instance.getToken(vapidKey: "BKagOny0KF_2pCJQ3m....moL0ewzQ8rZu");

如要在權杖更新時收到通知,請訂閱 onTokenRefresh 串流:

FirebaseMessaging.instance.onTokenRefresh
    .listen((fcmToken) {
      // TODO: If necessary send token to application server.

      // Note: This callback is fired at each app startup and whenever a new
      // token is generated.
    })
    .onError((err) {
      // Error getting token.
    });

防止自動初始化

產生 FCM 註冊時,程式庫會將 ID 和設定資料上傳至 Firebase。如要避免自動註冊,請在建構時停用自動初始化。

停用自動初始化功能後,您可以在執行階段呼叫 register(),明確註冊應用程式執行個體 (請務必先訂閱 onRegistered,才能接收 Firebase 安裝 ID):

await FirebaseMessaging.instance.register();

iOS

在 iOS 上,將中繼資料值新增至 Info.plist:

FirebaseMessagingAutoInitEnabled = NO

Android

在 Android 上,將下列中繼資料值新增至 AndroidManifest.xml,即可停用 Analytics 收集功能和 FCM 自動初始化功能 (您必須同時停用這兩項功能):

<meta-data
    android:name="firebase_messaging_auto_init_enabled"
    android:value="false" />
<meta-data
    android:name="firebase_analytics_collection_enabled"
    android:value="false" />

在執行階段重新啟用 FCM 自動初始化

如要為特定應用程式執行個體啟用自動初始化,請呼叫 setAutoInitEnabled():

await FirebaseMessaging.instance.setAutoInitEnabled(true);

設定後,即使重新啟動應用程式,這個值仍會保留。

傳送測試通知訊息

  1. 在目標裝置上安裝並執行應用程式。在 Apple 裝置上,您必須接受權限要求,才能接收遠端通知。

  2. 確認裝置上的應用程式在背景執行。

  3. 在 Firebase 控制台中,依序前往 「DevOps & Engagement」(開發運作與參與度) > 「Messaging」(訊息)。

  4. 建立廣告活動。

    • 如果這是您的第一則訊息:

      1. 選取「建立第一個廣告活動」。

      2. 依序選取「Firebase 通知訊息」和「建立」。

    • 如果您先前已建立廣告活動:

      1. 在「廣告活動」分頁中,選取「新增廣告活動」。

      2. 按一下「通知」。

  5. 輸入訊息文字。

  6. 在右側窗格中選取「傳送測試訊息」。

  7. 在標示為「新增 Firebase 安裝 ID 或FCM 註冊權杖」的欄位中,輸入已註冊的 Firebase 安裝 ID 或 註冊權杖。

  8. 選取「測試」。

選取「測試」後,目標用戶端裝置應會收到通知,且應用程式會在背景執行。

如要深入瞭解應用程式的訊息傳遞情形,請前往 Firebase 控制台的「DevOps & Engagement」 >「Messaging」 >「Reports」資訊主頁。這個資訊主頁會記錄在 Apple 和 Android 裝置上傳送及開啟的訊息數量,以及 Android 應用程式的「曝光」資料 (使用者看到的通知)。

處理互動

使用者輕觸通知時,Android 和 iOS 預設都會開啟應用程式。如果應用程式已終止,系統會啟動應用程式;如果應用程式在背景執行,系統會將其移至前景。

視通知內容而定,您可能需要在應用程式開啟時處理使用者的互動。舉例來說,如果使用者透過通知傳送新的即時通訊訊息並選取該訊息,您可能會希望在應用程式開啟時,開啟特定對話。

firebase-messaging 套件提供兩種處理這項互動的方法:

  1. getInitialMessage(): 如果應用程式是從終止狀態開啟,這個方法會傳回包含 RemoteMessage 的 Future。RemoteMessage一經使用就會移除。
  2. onMessageOpenedApp:當應用程式從背景狀態開啟時,會發布 RemoteMessage 的 Stream。

為確保使用者享有流暢體驗,請務必處理這兩種情況。以下程式碼範例說明如何達成這個目標:

class Application extends StatefulWidget {
  @override
  State createState() => _Application();
}

class _Application extends State {
  // In this example, suppose that all messages contain a data field with the key 'type'.
  Future setupInteractedMessage() async {
    // Get any messages which caused the application to open from
    // a terminated state.
    RemoteMessage? initialMessage =
        await FirebaseMessaging.instance.getInitialMessage();

    // If the message also contains a data property with a "type" of "chat",
    // navigate to a chat screen
    if (initialMessage != null) {
      _handleMessage(initialMessage);
    }

    // Also handle any interaction when the app is in the background using a
    // Stream listener
    FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
  }

  void _handleMessage(RemoteMessage message) {
    if (message.data['type'] == 'chat') {
      Navigator.pushNamed(context, '/chat',
        arguments: ChatArguments(message),
      );
    }
  }

  @override
  void initState() {
    super.initState();

    // Run code required to handle interacted messages in an async function
    // as initState() must not be async
    setupInteractedMessage();
  }

  @override
  Widget build(BuildContext context) {
    return Text("...");
  }
}

互動的處理方式取決於您的設定。上述範例是使用 StatefulWidget 的基本範例。

後續步驟

完成設定步驟後,您可以選擇以下幾種方式繼續使用 Flutter FCM: