import 'dart:convert'; import 'dart:io'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:router/componentRouter/component_service_manager.dart'; import 'package:shared/utils/log_utils.dart'; // 定义一个回调函数类型 typedef TokenCallback = void Function(String token); class FcmUtils { //FCM SDK对象 final _firebaseMessaging = FirebaseMessaging.instance; //Notifications插件对象 final _localNotifications = FlutterLocalNotificationsPlugin(); //Android 8+ 的消息通道 final _androidChannel = const AndroidNotificationChannel( 'Normal', //设置 Channel ID 'Channel Normal Android', //设置 Channel 名称 importance: Importance.defaultImportance); //设置该 Channel 的优先级 // 初始化,获取设备token Future initNotifications({ TokenCallback? onToken, // Token回调函数 }) async { //申请动态通知权限 await _firebaseMessaging.requestPermission(); //获取 FCM Token final fCMToken = await _firebaseMessaging.getToken(); if (fCMToken != null) { Log.d("FCM -> Token:$fCMToken"); onToken?.call(fCMToken); // 将初始 Token 通过回调传递 } //刷新 FCM Token 的监听 _firebaseMessaging.onTokenRefresh.listen((newToken) { Log.d("FCM onTokenRefresh -> Token:$newToken"); onToken?.call(newToken); // 将刷新后的 Token 通过回调传递 }); //拿到 FCM Token 之后初始化一些监听 _initPushNotifications(); _initLocalNotifications(); } /// Notifications 插件初始化,监听前台消息 Future _initLocalNotifications() async { const iOS = DarwinInitializationSettings(); // @drawable/ic_launcher是应用的图标,路径是:android/app/src/main/res/mipmap/ic_launcher.png const android = AndroidInitializationSettings('@mipmap/ic_launcher'); // Notifications 插件只需要处理 Android 和 iOS 平台的配置 const settings = InitializationSettings(android: android, iOS: iOS); // Notifications 插件初始化 await _localNotifications.initialize(settings, onDidReceiveNotificationResponse: (NotificationResponse response) { // android 前台消息点击回调 final message = RemoteMessage.fromMap(jsonDecode(response.payload!)); Log.d(response); // 处理收到消息 handleMessage(message); }); //Android 8 以上会通过 Channel 创建对应的通知渠道 final platform = _localNotifications.resolvePlatformSpecificImplementation(); await platform?.createNotificationChannel(_androidChannel); } /// FCM 初始化接收消息的各种回调 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不会弹出通知框,所以需要 Notifications 插件自定义本地通知(iOS没有前台消息,iOS的前台消息和后台运行时一样的效果) FirebaseMessaging.onMessage.listen((message) { Log.d("前台收到的消息 -> message:${message.data}"); 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, icon: '@mipmap/ic_launcher', )), payload: jsonEncode(message.toMap())); }); // 后台处理,后台程序运行时收到消息,不打开app也会执行的回调 // FirebaseMessaging.onBackgroundMessage(FirebaseApi.handleBackgroundMessage); } // 处理收到的消息,比如跳转页面或者其他处理 void handleMessage(RemoteMessage message) { final dataJson = message.data; Log.d("点击消息的处理 handleMessage -> data:$dataJson"); // 1、加入unit成功 ApprovedJoinUnitNotification // 2、加入unit失败 RejectedJoinUnitNotification // 3、online form批准了 ApprovedApplyOnlineFormNotification // 4、online form拒绝了 RejectedApplyOnlineFormNotification // 5、facility 预定成功了(不需要,因为支付了就是预定成功了) // 6、facility 预定失败了(长时间未支付,被系统取消了) FacilityBookingNotPaidCancelNotification // 7、每月物业费账单生成了 // 8、每月停车费账单生成了 // 9、服务订单长时间未支付 PaidServiceOrderNotPaidCancelNotification String? type = dataJson['type']; if (type == 'ApprovedApplyOnlineFormNotification' || type == 'RejectedApplyOnlineFormNotification') { //去 Form 详情 ComponentServiceManager().formService.startFormDetailPage(dataJson['estate_online_form_id'], dataJson['id'], dataJson['online_form_type_id']); } } // static Future 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}'); // } }