Flutter集成FCM离线推送---完整步骤

flutter中使用消息推送的方式有很多,若要实现离线推送等功能,需要集成第三方的推送,flutter官方推荐使用Firebase Cloud Messaging (FCM) 。

  • 如果App针对的是国内用户的话,不用考虑这个,FCM推送的必要条件是:有VPN,且安卓手机拥有谷歌三大件

前置

  • 需要先完成firebase配置,这一步请参考Flutter集成apple、google登陆,其中的:1. firebase项目创建、2. firebase配置章节
  • 需要拥有firebase账号,科学上网,一部有google三大件且能翻墙的安卓手机或模拟器,android studio模拟器如何上网请参考:Android虚拟机如何联网
  • 如果是iOS设备,必需使用真机进行调试,模拟器是无法收到消息的

Android接入FCM

下载依赖

pubspec.yaml

yml 复制代码
dependencies:
	# FCM推送
  firebase_messaging: ^14.7.2
  flutter_local_notifications: ^16.1.0

封装代码

lib/firebase/fcm/fcm_utils.dart

  • 具体代码可以通过调试,加深理解
  • 具体意思可以看看注释
dart 复制代码
import 'dart:convert';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
// 这两个是封装的路由,可不用
import 'package:planx_app/router/navigator_util.dart';
import 'package:planx_app/router/routes.dart';

class FirebaseApi {
  final _firebaseMessaging = FirebaseMessaging.instance;
  final _localNotifications = FlutterLocalNotificationsPlugin();
  final _androidChannel = const AndroidNotificationChannel(
    'planx', 'PlanX Android',  // 这些信息根据自己的app定义
    description: "PlanX Android description",
    importance: Importance.defaultImportance);

  // 本地消息,处理android的前台消息
  Future initLocalNotifications() async {
    const iOS = DarwinInitializationSettings();
    // @drawable/ic_launcher是应用的图标,路径是:android/app/src/main/res/drawable/ic_launcher.png
    const android = AndroidInitializationSettings('@drawable/ic_launcher');
    const settings = InitializationSettings(android: android, iOS: iOS);
    await _localNotifications.initialize(settings,
     onDidReceiveNotificationResponse: (NotificationResponse response) {
       // android 前台消息点击
       final message = RemoteMessage.fromMap(jsonDecode(response.payload!));
       print(response);
       // 处理收到消息
       handleMessage(message);
     });
    final platform = _localNotifications.resolvePlatformSpecificImplementation<
      AndroidFlutterLocalNotificationsPlugin>();
    await platform?.createNotificationChannel(_androidChannel);
  }

  // 初始化,获取设备token
  Future<void> initNotifications() async {
    await _firebaseMessaging.requestPermission();
    final fCMToken = await _firebaseMessaging.getToken();
    print(fCMToken); // 这个就是设备token,后端通过这token给设备发送信息
    initPushNotifications();
    initLocalNotifications();
  }

  // 初始化接收消息的各种回调
  Future initPushNotifications() async {
    await _firebaseMessaging.setForegroundNotificationPresentationOptions(
      alert: true, badge: true, sound: true);

    // 打开app时,会执行该回调,获取消息(通常是程序终止时,点击消息打开app的回调)
    _firebaseMessaging.getInitialMessage().then(
      (RemoteMessage? message) {
        if (message == null) return; // 没有消息不执行后操作
        handleMessage(message);
      },
    );

    // 后台程序运行时,点击消息触发
    FirebaseMessaging.onMessageOpenedApp
      .listen((RemoteMessage message) => handleMessage(message));

    // 前台消息,android不会通知,所以需要自定义本地通知(iOS没有前台消息,iOS的前台消息和后台运行时一样的效果)
    FirebaseMessaging.onMessage.listen((message) {
      final notification = message.notification;
      if (notification == null) return;
      if (Platform.isIOS) return;
      _localNotifications.show(
        notification.hashCode,
        notification.title,
        notification.body,
        NotificationDetails(
          android: AndroidNotificationDetails(
            _androidChannel.id,
            _androidChannel.name,
            channelDescription: _androidChannel.description,
            icon: '@drawable/ic_launcher',
          )),
        payload: jsonEncode(message.toMap()));
    });

    // 后台处理,后台程序运行时收到消息,不打开app也会执行的回调
    // FirebaseMessaging.onBackgroundMessage(FirebaseApi.handleBackgroundMessage);
  }

  // 处理收到的消息,比如跳转页面之类(这里需要无context跳转,可以参考我写的flutter路由配置篇章介绍)
  void handleMessage(RemoteMessage message) {
    NavigatorUtil.push(Routes.indexPage);
  }

  // static Future<void> handleBackgroundMessage(RemoteMessage message) async {
  //   print('后台消息');
  //   // BotToast.showText(text: '后台消息:${message.toString()}');
  //   print('title:${message.notification?.title}');
  //   print('body:${message.notification?.body}');
  //   print('payload:${message.data}');
  //   print('message:${message}');
  // }
}

在main中初始化

  • 初始化写在firebase配置后面

lib/main.dart

dart 复制代码
// ...
await Firebase.initializeApp(
  options: DefaultFirebaseOptions.currentPlatform);

FcmUtils().initNotifications(); // 初始化,获取token
// ...

运行与测试项目:

  • 点击允许,获取到token

打开firebase console测试

  • 选择发送测试消息
  • 将刚刚获取到的token,粘贴到输入框--->添加设备-->点击测试
  • 成功收到消息,后面再测试:终止程序是否收到消息,或后台运行是否收到消息

iOS接入FCM

配置项目

  • 打开firebase-->项目-->iOS应用
  • 下载这个文件,替换项目中的文件:ios/Runner/GoogleService-Info.plist
  • 点击查看SDK说明-->第四步
  • 根据提示复制到项目中

ios/Runner/AppDelegate.swift

配置证书

生成证书

  • 打开钥匙串,创建证书

输入自己的邮箱--->点击继续

  • 打开开发者后台,创建证书
  • 选择服务
  • 下载证书
  • 双击下载下来的证书
  • 打开钥匙串-->鼠标右键-->导出
  • 设置密码 --> 输入登陆密码--->导出成功,文件是.p12的文件

上传证书到firebase

xcode添加能力

运行和测试项目

  • 代码与android一致,这里就不贴了
  • 需要真机运行,模拟器无法收到消息

此时可能有报错,主要是网络原因

解决方案:

  • 终端开启代理(自行查一下搜索引擎)
  • cd ./ios
  • pod install

再次运行

  • 如果没有获取到token,请检查一下手机是否联网,并且科学上网
  • 获取token,放到firebase中测试,方式与Android一样,这里不细写了

收到消息--测试成功

相关推荐
安和昂4 小时前
iOS 工厂模式
ios
程序猿阿伟4 小时前
《社交应用动态表情:RN与Flutter实战解码》
javascript·flutter·react native
明似水4 小时前
Flutter 开发入门:从一个简单的计数器应用开始
前端·javascript·flutter
周胡杰4 小时前
组件导航 (Navigation)+flutter项目搭建-混合开发+分栏
数码相机·flutter·华为·电脑·harmonyos·鸿蒙
初遇你时动了情4 小时前
flutter flutter run 运行项目卡在Running Gradle task ‘assembleDebug‘...
flutter
龙湾开发5 小时前
轻量级高性能推理引擎MNN 学习笔记 03.在iOS运行MNN的示例
c++·学习·ios·图形渲染·mnn
初遇你时动了情9 小时前
flutter 配置 安卓、Ios启动图
android·flutter·ios
YSoup9 小时前
Android Studio报错Cannot parse result path string:
android·android studio
程序猿阿伟11 小时前
《云端共生体:Flutter与AR Cloud如何改写社交交互规则》
flutter·ar·交互
lpfasd12312 小时前
Flutter与Kotlin Multiplatform(KMP)深度对比及鸿蒙生态适配解析
flutter·kotlin·harmonyos