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

Flutter FCM前台通知点击回调失效,后台正常问题求助

前台通知点击回调失效问题排查与解决方案

问题原因分析

结合代码和现象,前台通知点击无响应的核心原因包括:

  • 通知ID重复导致旧通知被覆盖,无法触发对应回调
  • iOS平台前台通知缺少交互权限配置
  • 初始化顺序问题导致回调未正确绑定
  • iOS本地通知权限未单独请求

具体解决方案

1. 修复通知ID重复问题

当前使用DateTime.now().microsecond作为通知ID,该值范围仅0-999999,短时间内多通知会重复,导致新通知覆盖旧通知,点击时无法匹配回调逻辑。

修改LocalNotificationHelper的showNotification方法,使用唯一ID:

static Future<void> showNotification(RemoteMessage message) async {
  final data = message.data;

  final title = data['title'] ?? message.notification?.title;
  final body = data['body'] ?? message.notification?.body;

  final androidDetails = AndroidNotificationDetails(
    'high_importance_channel',
    'High Importance Notifications',
    importance: Importance.high,
    priority: Priority.high,
  );

  final iosDetails = DarwinNotificationDetails(
    presentAlert: true,
    presentBadge: true,
    presentSound: true,
  );

  // 使用messageId作为唯一ID, fallback到时间戳确保唯一性
  final notificationId = message.messageId != null 
      ? int.parse(message.messageId!) 
      : DateTime.now().millisecondsSinceEpoch;

  await _plugin.show(
    notificationId,
    title,
    body,
    NotificationDetails(
      android: androidDetails,
      iOS: iosDetails,
    ),
    payload: jsonEncode(data),
  );
}

2. 完善iOS前台通知交互配置

在DarwinNotificationDetails中显式配置交互权限,确保前台通知可被点击:

final iosDetails = DarwinNotificationDetails(
  presentAlert: true,
  presentBadge: true,
  presentSound: true,
);

3. 调整初始化顺序

将通知相关初始化放在runApp之前,确保Flutter环境完全准备好后再注册回调:
修改main函数:

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  /// Disable rotation
  if (Platform.isIOS || Platform.isAndroid) {
    SystemChrome.setPreferredOrientations(
        [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown]);
  }
  
  // 先完成异步初始化再启动App
  await _initializeAsync();
  runApp(AppRoot());
}

4. 单独请求iOS本地通知权限

FCM的权限请求不覆盖flutter_local_notifications的本地通知权限,在LocalNotificationHelper.init()中添加权限请求:

static Future<void> init() async {
  const android = AndroidInitializationSettings('@mipmap/retiq');
  const ios = DarwinInitializationSettings();

  const settings = InitializationSettings(android: android, iOS: ios);

  await _plugin.initialize(
    settings,
    onDidReceiveNotificationResponse: (response) {
      print("前台通知点击触发:${response.payload}"); // 添加日志验证回调是否执行
      if (response.payload != null) {
        final data = jsonDecode(response.payload!);
        NotificationRouter.handle(data);
      }
    },
  );

  // 请求iOS本地通知权限
  await _plugin.resolvePlatformSpecificImplementation<
      IOSFlutterLocalNotificationsPlugin>()
      ?.requestPermissions(
    alert: true,
    badge: true,
    sound: true,
  );

  await _createChannels();
}

5. 修复Payload字段拼写错误

后端Payload中字段为taks_id,但NotificationRouter中使用task_id,会导致导航逻辑失效,同步修正字段名:

// 后端Payload修改为正确拼写
"data": {
  "type": "chat",
  "id": "123",
  "task_id": "123",
  "taskable_id": "123"
}

验证步骤

  1. 运行修改后的代码,前台收到通知后点击,查看控制台是否打印前台通知点击触发日志
  2. 确认导航逻辑是否正常执行
  3. 测试多通知场景,确保每个通知点击都能触发对应回调

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 22:24:53