You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 12:24:50