Flutter集成Firebase Cloud Messaging(FCM)

Firebase Cloud Messaging

Firebase Cloud Messaging(FCM)是一種跨平臺的消息傳遞解決方案,可以讓您可靠地免費發送消息。android

使用FCM,您能夠通知客戶端應用程序能夠同步新電子郵件或其餘數據。您能夠發送通知消息來推進用戶的從新參與和保留。對於即時消息之類的用例,一條消息能夠將最多4 KB的有效負載傳輸到客戶端應用程序。ios

如下內容基於flutter 1.22.4版本git

準備工做

在開始以前,該文檔假定您可以建立(或具備現有的)Flutter項目,而且還具備使用中的Firebase項目。若是您不知足這些先決條件,請參考準備工做github

安裝

1.添加依賴項

dependencies:
  flutter:
    sdk: flutter
  firebase_core: "^0.5.3"
  firebase_messaging: "^8.0.0-dev.11"
複製代碼

2.下載依賴項web

$ flutter pub get
複製代碼

3. ios集成

參考:firebase.flutter.dev/docs/messag…shell

4. android集成

若是您正在使用Flutter Android Embedding V2(Flutter版本> = 1.12),則Android不須要其餘集成步驟。—— 好比我。json

低版本請參考:Flutte接入firebase messagingapi

使用

在使用Firebase Cloud Messaging以前,您必須首先確保已初始化FlutterFire。bash

await Firebase.initializeApp();
複製代碼

根據設備狀態,傳入消息的處理方式有所不一樣。要了解這些狀況以及如何將FCM集成到您本身的應用程序中,首先重要的是肯定設備能夠處於的各類狀態:服務器

狀態 描述
Foreground 當應用程序打開時,且在前臺顯示時。
Background 打開應用程序時,可是在後臺(最小化)。當用戶按下設備上的「主頁」按鈕,經過應用程序切換器切換到另外一個應用程序或在其餘選項卡(Web)上打開應用程序時,一般會發生這種狀況。
Terminated 設備鎖定或應用程序未運行時。用戶能夠經過設備上的應用程序切換器用戶界面「將其刷掉」或關閉標籤頁(web)來終止應用程序。
  • 不論哪一種狀況,該應用程序必須至少打開一次(以容許在FCM中註冊,必需要能鏈接到谷歌)。

  • 在Android上,若是強行終止程序,那麼是收不到推送的。

  • 在iOS上,若是用戶從應用切換器上滑動了該應用程序,則必須再次手動將其從新打開,以使後臺消息從新開始工做。

申請許可(ios,Mac和Web)

在iOS,macOS和Web上,必須先徵詢用戶許可,而後才能在設備上接收FCM有效負載。

不須要在Android應用程序上請求權限。

代碼:

FirebaseMessaging messaging = FirebaseMessaging.instance;

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

print('用戶授予權限結果: ${settings.authorizationStatus}');
複製代碼

authorizationStatus屬性能夠返回一個值,該值可用於肯定用戶的整體決策:

  • authorized: 用戶已授予權限。
  • denied: 用戶拒絕了權限。
  • notDetermined: 用戶還沒有選擇是否授予許可。
  • provisional:用戶授予了臨時權限(請參閱[臨時權限](firebase.flutter.dev/docs/messag…

在Android上,authorizationStatus始終是authorized。

NotificationSettings上的其餘屬性返回在當前設備上是啓用,禁用仍是不支持特定權限。

有關更多信息,請查看Permissions文檔。

處理消息

消息類型

根據應用程序的當前狀態,傳入的有效負載須要不一樣的實現來處理它們:

Foreground Background Terminated
Notification onMessage onBackgroundMessage onBackgroundMessage
Data onMessage onBackgroundMessage (*see below*) onBackgroundMessage (*see below*)
Notification & Data onMessage onBackgroundMessage onBackgroundMessage

前臺消息(Foreground)

默認狀況下,在應用程序處於前臺時到達的通知消息在Android和iOS上均不會顯示可見的通知。可是,能夠覆蓋此行爲:在前臺收到推送時裏用flutter_local_notifications來顯示一條通知。

///前臺消息
    FirebaseMessaging.onMessage.listen((RemoteMessage message) {
      print('在前臺收到消息!');

      if (message.notification != null) {
        RemoteNotification notification = message.notification;

        ///顯示通知
        if (notification != null && notification.android != null) {
          FlutterLocalNotificationsPlugin().show(
              notification.hashCode,
              notification.title,
              notification.body,
              NotificationDetails(
                android: AndroidNotificationDetails(
                  channel.id,
                  channel.name,
                  channel.description,
									// TODO 向android添加適當的可繪製資源(在drawable下)
                  icon: 'launch_background',
                ),
              ),
              payload: message.data.toString());
        }
      }
    });
複製代碼

後臺消息(Background)

當前,在Android / Apple和基於Web的平臺上處理後臺消息的過程有所不一樣。

在後臺運行應用程序時處理消息有些不一樣。能夠經過onBackgroundMessage處理程序處理消息。

收到隔離信息後,就會生成隔離信息(僅適用於Android,iOS / macOS不須要單獨的隔離信息,APNS真牛逼),即便您的應用程序未運行,也能夠處理消息。

關於後臺消息處理的方法,須要牢記如下幾點:

  • 它不能是匿名函數。
  • 它必須是頂層函數(例如,不是須要初始化的類方法)。
static Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
    print("收到後臺消息: ${message.messageId}");
  }  

...
///後臺消息
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
複製代碼

收到後臺消息的時候,運行長時間的繁重任務會影響設備性能,並可能致使操做系統終止該過程。若是任務運行時間超過30秒,則設備可能會自動終止該進程。

onMessageOpenedApp:當從後臺狀態打開應用程序時,該流會發送RemoteMessage。此時能夠監聽到用戶對此種通知的點擊行爲:

///點擊後臺消息打開App
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print('從後臺打開!');
    });
複製代碼

應用終止時點擊通知打開App(Terminated)

onBackgroundMessage是沒法監聽到此種通知的行爲的,可是能夠接收到用戶對此種通知的點擊行爲:

getInitialMessage():若是從終止狀態打開應用程序,則將返回包含RemoteMessage的Future。一旦使用完畢,RemoteMessage將被刪除。

///應用從終止狀態打開
    var m = await FirebaseMessaging.instance.getInitialMessage();
    if (m != null) {
      print('應用從終止狀態打開:${m?.notification?.title}');
    }
複製代碼

要展現通知必須包含nofitication字段

處理交互

因爲通知是可見的提示,所以用戶一般會與通知進行交互(點擊通知)。 Android和iOS上的默認行爲是打開應用程序。若是應用程序終止,它將啓動;若是它在後臺,它將被帶到前臺。

firebase-messaging軟件包提供了兩種方法來處理此交互(上文一提到,再着重介紹下):

  • getInitialMessage():若是從終止狀態打開應用程序,則將返回包含RemoteMessage的Future。一旦使用完畢,RemoteMessage將被刪除。
  • onMessageOpenedApp:當從後臺狀態打開應用程序時,該流會發送RemoteMessage。

建議同時處理兩種狀況。

///點擊後臺消息打開App
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      print('從後臺打開!');
    });

    ///應用從終止狀態打開
    var m = await FirebaseMessaging.instance.getInitialMessage();
    if (m != null) {
      print('應用從終止狀態打開:${m?.notification?.title}');
    }
複製代碼

如下是官方示例:

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

class _Application extends State<Application> {
  @override
  void initState() async {
    super.initState();

    // 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?.data['type'] == 'chat') {
      Navigator.pushNamed(context, '/chat',
          arguments: ChatArguments(initialMessage));
    }

    // Also handle any interaction when the app is in the background via a
    // Stream listener
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
      if (message.data['type'] == 'chat') {
        Navigator.pushNamed(context, '/chat',
          arguments: ChatArguments(message));
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Text("...");
  }
}
複製代碼

處理交互的方式取決於您的應用程序設置,可是上面的示例顯示了一個使用StatefulWidget的基本示例。

至於前臺通知的點擊,請查看flutter_local_notifications來設置.

主題

用戶能夠訂閱一個主題,咱們發推送的時候對某一主題發出推送,訂閱了這個主題的用戶就會收到。

起到一個發送給多個用戶推送的做用。

主要是我沒找到經過http取到發推送的時候如何對全部用戶發送。

訂閱主題:

要訂閱設備,請使用主題名稱調用subscribeToTopic方法:

await FirebaseMessaging.instance.subscribeToTopic('weather');
複製代碼

取消訂閱主題

要取消訂閱主題,請使用主題名稱調用unsubscribeFromTopic方法:

await FirebaseMessaging.instance.unsubscribeFromTopic('weather');
複製代碼

此處的意思是主題名稱爲weather.

經過Http發推送

若是您沒法使用Firebase Admin SDK,則Firebase還支持經過HTTP, POST請求將消息發送到設備:

Authorization:服務器密鑰

POST	https://fcm.googleapis.com/fcm/send 	HTTP/1.1

//請求頭
Content-Type: application/json
Authorization: key={服務器密鑰}

//body
{
	"to": "{fcmtoken}",
	"notification": {
		"icon": "juno_icon",
		"title": "本身的土",
		"body": "本身的地🤮",
		"sound": "default",
		"badge": 1,
		"content_available": true
	},
	"data": {
		"title": "本身的土",
		"body": "本身的地",
		"id": 1,
		"type": 2,
		"route": "ceceapp://main/fortune"
	}
}
複製代碼

ios後臺推送要添加content_available才能收到回調 相關文檔

基於此寫的示例項目已發佈到github Android,ios 先後臺的推送都已調通,多個手機測試過。

相關文章
相關標籤/搜索