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

如何在Flutter WebView中启用网页原生通知功能?

解决Flutter WebView中网页原生通知不显示的问题

要实现类似Chrome的网页原生通知效果,核心思路是通过JavaScript通道拦截网页的Notification API调用,再借助Flutter本地通知插件触发系统通知,完全适配网页原生的通知逻辑,无需依赖Firebase。

具体实现步骤

1. 添加依赖

在pubspec.yaml中引入必要插件:

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^4.4.0
  flutter_local_notifications: ^16.1.0
  permission_handler: ^10.2.0 # 用于Android 13+动态申请通知权限

2. 核心代码实现

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:permission_handler/permission_handler.dart';

class WebViewWithNotifications extends StatefulWidget {
  final String targetUrl;
  const WebViewWithNotifications({super.key, required this.targetUrl});

  @override
  State<WebViewWithNotifications> createState() => _WebViewWithNotificationsState();
}

class _WebViewWithNotificationsState extends State<WebViewWithNotifications> {
  late WebViewController _webController;
  final FlutterLocalNotificationsPlugin _notificationPlugin = FlutterLocalNotificationsPlugin();

  @override
  void initState() {
    super.initState();
    _requestNotificationPermission();
    _initNotificationPlugin();
    _setupWebViewController();
  }

  // 动态申请Android通知权限
  void _requestNotificationPermission() async {
    if (await Permission.notification.isDenied) {
      await Permission.notification.request();
    }
  }

  // 初始化本地通知插件
  void _initNotificationPlugin() async {
    const AndroidInitializationSettings androidInitSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
    const InitializationSettings initSettings = InitializationSettings(android: androidInitSettings);
    await _notificationPlugin.initialize(
      initSettings,
      onDidReceiveNotificationResponse: (response) {
        // 可选:处理通知点击事件,比如跳转回WebView对应的页面
        _webController.loadRequest(Uri.parse(widget.targetUrl));
      },
    );
  }

  // 配置WebView并拦截通知请求
  void _setupWebViewController() {
    _webController = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      // 添加JS通道,接收网页传递的通知数据
      ..addJavaScriptChannel(
        'WebNotificationChannel',
        onMessageReceived: (JavaScriptMessage message) {
          final Map<String, dynamic> notificationData = Map.castFrom(message.data);
          _showSystemNotification(notificationData);
        },
      )
      ..loadRequest(Uri.parse(widget.targetUrl))
      // 注入JS代码重写Notification构造函数
      ..runJavaScript('''
        const OriginalNotification = window.Notification;
        window.Notification = function(title, options) {
          // 将通知参数发送给Flutter端
          WebNotificationChannel.postMessage({
            title: title,
            body: options?.body || '',
            icon: options?.icon || ''
          });
          // 保留网页内的通知显示(可选,不需要可删除)
          return new OriginalNotification(title, options);
        };
        // 同步原Notification的静态属性和方法
        window.Notification.permission = OriginalNotification.permission;
        window.Notification.requestPermission = OriginalNotification.requestPermission;
      ''');
  }

  // 触发系统本地通知
  void _showSystemNotification(Map<String, dynamic> data) async {
    const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
      'web_page_notifications',
      '网页通知',
      channelDescription: '接收来自内嵌网页的通知消息',
      importance: Importance.max,
      priority: Priority.high,
      showWhen: true,
    );
    const NotificationDetails notificationDetails = NotificationDetails(android: androidDetails);
    
    await _notificationPlugin.show(
      DateTime.now().millisecondsSinceEpoch ~/ 1000,
      data['title'],
      data['body'],
      notificationDetails,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('内嵌网页')),
      body: WebViewWidget(controller: _webController),
    );
  }
}

3. Android平台额外配置

在android/app/src/main/AndroidManifest.xml中添加权限声明:

<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

关键说明

  • 完全适配网页原生的通知流程:保留网页的Notification.requestPermission()授权逻辑,用户授权后网页发起的通知请求会被拦截并转为系统通知。
  • 无需依赖第三方推送服务,仅通过WebView的JS桥接实现,和Chrome浏览器的通知体验一致。
  • 支持通知点击回调,可自定义点击后的跳转逻辑。

内容的提问来源于stack exchange,提问作者Hassaan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 17:01:09