Flutter开发日记:使用FCM向Android/IOS发送前后台消息通知推送

2,036 阅读4分钟

一,基本配置

  1. package使用firebaseMessaging,链接:pub.dev/packages/fi…
  2. 依赖添加到pubspec.yaml并且运行
flutter pub get
  1. 在自己的项目中,根据官网文档进行FirebaseMessaging的android和ios平台配置,链接:firebase.flutter.dev/docs/messag… ,这里要注意,如果使用的是Flutter2,那么不用对android做额外配置。
  2. 顺利的话,至此app已经具备接受push notification的能力了,下面讲一下app内对notification的处理,以及如何方便的进行发送测试。
  3. 记得初始化应用时,在app.dart中请求系统给予通知权限:
await FirebaseMessaging.instance.requestPermission()

二,应用消息处理

使用FCM发送的message,根据其message body和接收到消息的设备上app运行状态,会把消息推送分为两种,一是前台推送(Foreground notification),二是后台推送(Background notification),下面先讲前台推送的处理。

  1. 配置前台handler 这里的前台handler,指的是两种状态,app就在前台正在被使用,和app在后台或者杀掉,但是用户通过点击发送过来的notification消息图标点进了应用,对应的是FirebaseMessaging.instance的三个方法:

image.png

image.png

image.png

方法名称onMessageonMessageOpenedAppgetInitialMessage
触发条件应用在前台应用在后台并通过点击通知|应用被杀并通过点击通知|

要注意的是,onMessage和onMessageOpenedApp都返回一个Stream,因此应该监听该Stream来注册自己的handler,对于getInitialMessage,应该在成功拿到Remote message后用then回掉植入自己的handler,例子:

image.png

这里的NotificationMessageHandler是自己写的handler store,把各类消息的handler在初始化应用时都注册在里边的handlerList。

  1. 配置后台handler 后台的情况,只有一种:

image.png

它对应的情况是当应用在后台,且不希望点击通知进入应用时,做一些处理,因为应用依旧在后台,所以onBackgroundMessage会单开一个isolate(可以理解为新线程dart.dev/guides/lang… )来处理,因为isolate并不共享内存,所以main里启动的应用和注册的各种服务,不能在onBackgroundMessage里使用,如果有需要,应该在方法顶层进行初始化。同时因为是单独isolate处理,这个方法应该存在于app顶层也就是main.dart里,其他地方不会被调用:

FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

image.png

三,消息发送

发送消息有三种方式,第一,走后端服务集成SDK,第二,用工具(比如Postman)调FCM的Rest API,第三,使用FCM的console。具体参考这篇官方文档:firebase.google.com/docs/cloud-… ,这里讲一下REST API从Postman发送请求进行调试的方法。这里要注意,FCM的cosole虽然使用方便,但是不能发data message,title和body是必填项,对应的就是以下notification field里的字段,所以想调试data message还是要从REST或者SDK入手。

  1. V1版本 URL:fcm.googleapis.com/v1/projects…
message: {
    notification: {
        "title": "XXX",
        "body": "XXX"
    },
    data: { "key": "value" },
    token: #device_token,
    android: {
        "priority": "high"
    },
    apns: {
        "payload": {
            "aps": {
                "content-available": 1
            }
        },
        "headers": { #https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns }
    }
}
  1. 老版本
{
    "to": #device_token,
    "notification": {
        "title": "XXX",
        "body": "XXX"
    }
    "data": { "key: value" },
    "priority": "high",
    "content_available": true,
    "apns-priority": 5
}

四,经验总结

  1. 我的项目上,notification专门有个微服务,所有需要发送notificaion的其他服务调用它就可以,然后这个微服务本身使用的是FCM的java-sdk:firebase.google.com/docs/refere… ,当然了,如果作为前端调试或者方便起见,直接用node.js写noti服务也是很方便的:firebase.google.com/docs/refere…

  2. FCM文档上写的前后台推送介绍其实有些confusing,尤其对于初学者,这里用表格总结下他们对应的handler何时会被唤起:

场景ForegroudBackground
app前台使用yesno
app后台运行noyes
app被杀掉noyes

总结而言,就是前后台的handler调用只和app运行状态有关,和message payload有没有notification无关,这里notification有没有,只决定了app里handler获取的数据,以及system层面会不会有一个heads up通知显示。

  1. 使用场景上,一般来说notification就应该字如其名,只作为通知消息来使用,任何breaking的行为和升级,都应该使用比如fore-upgrade,或者http请求来实现,比如大版本的更新,就必须强制更新否则无法使用,比如多地登录导致强制登出,就最好使用http验证权限时候发送403状态码和‘FORCE_LOGOUT‘这样的subcode来实现。如果有更多比如热更新的需求,应该去参考hotfix的android和ios实现,不要全都指望着background message来后台执行更新程序,因为这往往是不靠谱且容易被中断的(ios默认30秒内不能执行完毕的background message任务就会被终结掉且之后长时间不再接受该app的后台推送)。