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

Flutter本地通知:实现前后台差异化通知展示逻辑

实现Flutter本地通知:前台自定义弹窗/后台默认展示

核心思路

借助flutter_local_notifications包的前台通知回调拦截机制:应用处于前台时,阻止系统默认通知展示,转而弹出自定义Dialog;后台时让系统按默认逻辑处理通知。

步骤1:添加依赖与基础配置

在pubspec.yaml中引入依赖:

dependencies:
  flutter_local_notifications: ^16.1.0

安卓配置(android/app/src/main/AndroidManifest.xml)

添加必要权限:

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

iOS配置(ios/Runner/Info.plist)

添加通知权限描述与后台模式:

<key>NSUserNotificationUsageDescription</key>
<string>需要通知权限来推送提醒</string>
<key>UIBackgroundModes</key>
<array>
  <string>fetch</string>
  <string>remote-notification</string>
</array>

步骤2:初始化通知插件

创建全局通知实例,初始化时配置前台通知处理逻辑:

import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/timezone.dart' as tz;

final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin();

// 初始化通知插件
Future<void> initNotifications() async {
  // 安卓初始化设置
  const AndroidInitializationSettings androidInit =
      AndroidInitializationSettings('@mipmap/ic_launcher');
  
  // iOS初始化设置
  const DarwinInitializationSettings iosInit = DarwinInitializationSettings(
    requestAlertPermission: true,
    requestBadgePermission: true,
    requestSoundPermission: true,
  );

  const InitializationSettings initSettings = InitializationSettings(
    android: androidInit,
    iOS: iosInit,
  );

  // 初始化并设置通知点击回调
  await notificationsPlugin.initialize(
    initSettings,
    onDidReceiveNotificationResponse: (response) {
      if (response.payload != null) {
        debugPrint('通知负载:${response.payload}');
      }
    },
  );

  // 请求安卓通知权限
  await notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
      ?.requestNotificationsPermission();
  
  // 请求iOS通知权限
  await notificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
      ?.requestPermissions(alert: true, badge: true, sound: true);
}

步骤3:前台拦截与自定义弹窗实现

通过监听应用生命周期和通知流,实现前台拦截逻辑:

class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    initNotifications();
    // iOS前台禁用默认通知弹窗
    notificationsPlugin.resolvePlatformSpecificImplementation<IOSFlutterLocalNotificationsPlugin>()
        ?.setForegroundNotificationPresentationOptions(alert: false, badge: true, sound: true);
    // 注册前台通知监听
    _setupForegroundNotificationHandler();
  }

  void _setupForegroundNotificationHandler() {
    // 监听通知到达事件
    notificationsPlugin.notificationStream.listen((response) {
      if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed) {
        // 应用在前台,弹出自定义弹窗
        _showCustomDialog(response);
        // 取消系统默认通知(安卓需要手动取消)
        notificationsPlugin.cancel(response.id!);
      }
    });
  }

  void _showCustomDialog(NotificationResponse response) {
    showDialog(
      context: context,
      builder: (_) => AlertDialog(
        title: Text(response.notificationTitle ?? '新通知'),
        content: Text(response.notificationBody ?? ''),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('关闭'),
          ),
        ],
      ),
    );
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    // 应用回到前台时重新监听
    if (state == AppLifecycleState.resumed) {
      _setupForegroundNotificationHandler();
    }
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }
}

步骤4:创建定时通知

实现定时触发逻辑,区分前后台展示规则:

Future<void> scheduleTimedNotification() async {
  const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
    'timed_notification_channel',
    '定时通知渠道',
    channelDescription: '用于展示定时提醒',
    importance: Importance.max,
    priority: Priority.high,
  );

  const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(
    presentAlert: false, // iOS前台不展示默认弹窗
    presentBadge: true,
    presentSound: true,
  );

  const NotificationDetails notificationDetails = NotificationDetails(
    android: androidDetails,
    iOS: iosDetails,
  );

  // 10秒后触发定时通知
  await notificationsPlugin.zonedSchedule(
    0,
    '定时提醒',
    '这是一条前台弹窗、后台系统通知的定时消息',
    tz.TZDateTime.now(tz.local).add(const Duration(seconds: 10)),
    notificationDetails,
    androidAllowWhileIdle: true,
    uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
  );
}

注意事项

  • 安卓需确保通知渠道已创建,首次初始化插件时会自动生成渠道。
  • 测试时需分别验证前台、后台状态下的通知表现,确保权限请求成功。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:13:20