Flutter Web前台无法显示Firebase推送通知问题求助
Flutter Web Firebase推送前台显示通知弹窗解决方案
你的问题核心在于:Firebase Web Messaging中,前台消息不会触发Service Worker的setBackgroundMessageHandler,只有应用在后台/关闭状态时才会走这个逻辑。前台消息会直接发送到页面端,需要在Flutter代码中主动监听并触发通知弹窗。
以下是具体解决步骤:
1. 完善Service Worker代码(优化后台通知)
当前你的Service Worker中通知标题是固定值,先修改为从推送payload中读取实际内容,同时确保数据传递正确:
importScripts("https://www.gstatic.com/firebasejs/7.5.0/firebase-app.js"); importScripts("https://www.gstatic.com/firebasejs/7.5.0/firebase-messaging.js"); firebase.initializeApp({ apiKey: "", authDomain: "", projectId: "", messagingSenderId: "", appId: "", measurementId: '', }); const messaging = firebase.messaging(); messaging.setBackgroundMessageHandler(function (payload) { // 从payload中提取通知标题和内容 const notificationTitle = payload.notification?.title || "新消息"; const notificationOptions = { body: payload.notification?.body || "", data: payload.data || {} // 保留点击跳转所需数据 }; const promiseChain = clients .matchAll({ type: "window", includeUncontrolled: true }) .then(windowClients => { for (let i = 0; i < windowClients.length; i++) { const windowClient = windowClients[i]; windowClient.postMessage(payload); } }) .then(() => { return registration.showNotification(notificationTitle, notificationOptions); }); return promiseChain; }); self.addEventListener('notificationclick', function (event) { const clickedNotification = event.notification; clickedNotification.close(); const actionUrl = event.notification.data.url || '/'; clients.openWindow(actionUrl); });
2. 在Flutter Dart代码中监听前台消息并触发通知
因为Flutter Web没有原生的桌面通知API,需要通过JS互调实现:
步骤2.1 添加依赖
在pubspec.yaml中添加必要依赖:
dependencies: flutter: sdk: flutter firebase_core: ^2.15.0 firebase_messaging: ^14.6.5 js: ^0.6.7
执行flutter pub get安装依赖。
步骤2.2 编写Dart代码
import 'package:flutter/material.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:js/js.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await Firebase.initializeApp(); runApp(const MyApp()); } // 定义JS互调函数 @JS() external void showNotification(String? title, String? body); class MyApp extends StatefulWidget { const MyApp({super.key}); @override State<MyApp> createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { final FirebaseMessaging _messaging = FirebaseMessaging.instance; @override void initState() { super.initState(); _setupMessaging(); } Future<void> _setupMessaging() async { // 请求用户授权通知权限 NotificationSettings settings = await _messaging.requestPermission( alert: true, badge: true, sound: true, ); if (settings.authorizationStatus == AuthorizationStatus.authorized) { // 监听前台消息 FirebaseMessaging.onMessage.listen((RemoteMessage message) { // 调用JS函数显示通知弹窗 showNotification( message.notification?.title, message.notification?.body, ); }); } } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: const Text("Flutter Web Firebase推送")), body: const Center(child: Text("前台可接收通知弹窗")), ), ); } }
步骤2.3 在web/index.html中添加JS实现
在<body>标签末尾添加以下JS代码:
<script> function showNotification(title, body) { // 检查浏览器支持性和权限 if (!("Notification" in window)) { alert("当前浏览器不支持桌面通知"); return; } if (Notification.permission === "granted") { // 已授权,直接显示通知 new Notification(title, { body: body }); } else if (Notification.permission !== "denied") { // 未授权,请求权限后显示 Notification.requestPermission().then(permission => { if (permission === "granted") { new Notification(title, { body: body }); } }); } } </script>
关键说明
- 前台消息流:应用前台时,Firebase会直接将消息推送到页面的Messaging实例,而非Service Worker,因此必须在Dart代码中监听
onMessage事件。 - 权限检查:必须确保用户已授权通知权限,否则无法显示弹窗。
- 版本兼容:你当前使用的Firebase JS版本是7.5.0,建议保持与Flutter插件版本的兼容性,若出现问题可尝试升级到较新的Firebase JS版本(如9.x+)。
内容的提问来源于stack exchange,提问作者Krishna B
相关产品推荐
相关产品推荐

