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 先后台的推送都已调通,多个手机测试过。