Firebase Cloud Messaging(FCM)是一種跨平臺的消息傳遞解決方案,可以讓您可靠地免費發送消息。android
使用FCM,您能夠通知客戶端應用程序能夠同步新電子郵件或其餘數據。您能夠發送通知消息來推進用戶的從新參與和保留。對於即時消息之類的用例,一條消息能夠將最多4 KB的有效負載傳輸到客戶端應用程序。ios
如下內容基於flutter 1.22.4
版本git
在開始以前,該文檔假定您可以建立(或具備現有的)Flutter項目,而且還具備使用中的Firebase項目。若是您不知足這些先決條件,請參考準備工做github
dependencies:
flutter:
sdk: flutter
firebase_core: "^0.5.3"
firebase_messaging: "^8.0.0-dev.11"
複製代碼
2.下載依賴項web
$ flutter pub get
複製代碼
參考:firebase.flutter.dev/docs/messag…shell
若是您正在使用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,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 |
默認狀況下,在應用程序處於前臺時到達的通知消息在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());
}
}
});
複製代碼
當前,在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('從後臺打開!');
});
複製代碼
onBackgroundMessage
是沒法監聽到此種通知的行爲的,可是能夠接收到用戶對此種通知的點擊行爲:
getInitialMessage():若是從終止狀態打開應用程序,則將返回包含RemoteMessage的Future。一旦使用完畢,RemoteMessage將被刪除。
///應用從終止狀態打開
var m = await FirebaseMessaging.instance.getInitialMessage();
if (m != null) {
print('應用從終止狀態打開:${m?.notification?.title}');
}
複製代碼
要展現通知必須包含nofitication
字段
因爲通知是可見的提示,所以用戶一般會與通知進行交互(點擊通知)。 Android和iOS上的默認行爲是打開應用程序。若是應用程序終止,它將啓動;若是它在後臺,它將被帶到前臺。
firebase-messaging
軟件包提供了兩種方法來處理此交互(上文一提到,再着重介紹下):
建議同時處理兩種狀況。
///點擊後臺消息打開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
.
若是您沒法使用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 先後臺的推送都已調通,多個手機測試過。