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

Flutter Firebase推送通知报错:Integer.intValue()空对象引用

问题分析与解决方案

根据你提供的错误日志和代码,java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference 错误源自 Android 端的本地通知插件调用,结合代码细节,以下是具体问题和修复方案:

核心问题定位

  1. 冗余的通知展示调用:在 onMessageOpenedApp 中调用 createanddisplaynotification 是不必要的——当应用处于后台时,Firebase 已自动展示通知,重复调用会导致冲突。
  2. 未处理的空值参数:message.notification!.title 和 message.notification!.body 可能为 null,直接使用 ! 强制解包后传递给通知展示方法,会触发 Android 端的空指针异常。
  3. 后台隔离区的错误操作:onDidReceiveBackgroundNotificationResponse 运行在后台隔离区,无法直接使用 Navigator 或 Provider,会导致上下文为空的错误。
  4. 未显式创建通知渠道:虽然插件会自动创建渠道,但显式创建可避免渠道初始化延迟导致的问题。

修复后的代码

LocalNotificationService 类

class LocalNotificationService {
  static final FlutterLocalNotificationsPlugin _notificationsPlugin =
      FlutterLocalNotificationsPlugin();

  static void initialize() {
    const InitializationSettings initializationSettings =
        InitializationSettings(
      android: AndroidInitializationSettings("@mipmap/ic_launcher"),
    );

    // 显式创建通知渠道
    const AndroidNotificationChannel channel = AndroidNotificationChannel(
      "ikwteat_push_notification",
      "ikwteatpushnotificationappchannel",
      importance: Importance.max,
      priority: Priority.high,
      description: "推送通知渠道",
    );
    _notificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.createNotificationChannel(channel);

    _notificationsPlugin.initialize(
      initializationSettings,
      onDidReceiveBackgroundNotificationResponse: (details) {
        print("后台通知 payload: ${details.payload}");
        // 后台隔离区禁止使用 Navigator/Provider,仅做日志记录
      },
      onDidReceiveNotificationResponse: (details) {
        print("前台通知 payload: ${details.payload}");
        final context = navigatorkey.currentContext;
        if (context == null) return;

        if (details.payload == 'Offer Section') {
          if (tokenValue != null) {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => OfferMeScreen()),
            );
          }
        } else if (details.payload == 'Surprise Me Section') {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => HomeScreen(index: 2)),
          );
        } else {
          final generalController = Provider.of<GeneralController>(context, listen: false);
          if (generalController.notification_name == 'Restaurant' && details.payload != null) {
            Provider.of<FoodController>(context, listen: false)
                .restaurantDetailApi(context, id: details.payload!);
          }
        }
      },
    );
  }

  static void createanddisplaynotification(RemoteMessage message) async {
    try {
      final id = DateTime.now().millisecondsSinceEpoch ~/ 1000;
      const NotificationDetails notificationDetails = NotificationDetails(
        android: AndroidNotificationDetails(
          "ikwteat_push_notification",
          "ikwteatpushnotificationappchannel",
          importance: Importance.max,
          priority: Priority.high,
        ),
      );

      Map<String, dynamic> data = message.data;
      String linkTo = data['notification_link_to'] ?? '';

      if (linkTo == 'Restaurant') {
        final context = navigatorkey.currentContext;
        if (context != null) {
          Provider.of<GeneralController>(context, listen: false)
              .updateNotification(value: linkTo);
          if (data['restaurant_id'] != null) {
            linkTo = data['restaurant_id']!;
            print("餐厅 ID: ${linkTo}");
          }
        }
      }

      print("通知 ID: ${id.runtimeType}");
      await _notificationsPlugin.show(
        id,
        message.notification?.title ?? '',
        message.notification?.body ?? '',
        notificationDetails,
        payload: linkTo,
      );
    } on Exception catch (e) {
      print("展示通知错误: $e");
    }
  }
}

FirebaseFunctions 函数

void FirebaseFunctions() {
  // 处理应用终止状态下的通知点击
  FirebaseMessaging.instance.getInitialMessage().then(
    (message) {
      print("FirebaseMessaging.instance.getInitialMessage");
      if (message != null) {
        print("从终止状态打开通知");
        _handleNotificationNavigation(message);
      }
    },
  );

  // 处理应用前台状态下的通知接收
  FirebaseMessaging.onMessage.listen(
    (message) {
      print("FirebaseMessaging.onMessage.listen");
      if (message.notification != null) {
        print(message.notification!.title ?? '无标题');
        print(message.notification!.body ?? '无内容');
        Map<String, dynamic> data = message.data;
        String linkTo = data['notification_link_to'] ?? '';
        print("跳转目标: ${linkTo}");
        LocalNotificationService.createanddisplaynotification(message);
      }
    },
  );

  // 处理应用后台状态下的通知点击
  FirebaseMessaging.onMessageOpenedApp.listen(
    (message) {
      print("FirebaseMessaging.onMessageOpenedApp.listen");
      if (message.notification != null) {
        print(message.notification!.title ?? '无标题');
        print(message.notification!.body ?? '无内容');
        _handleNotificationNavigation(message);
      }
    },
  );
}

// 统一处理通知跳转逻辑
void _handleNotificationNavigation(RemoteMessage message) {
  final context = navigatorkey.currentContext;
  if (context == null) return;

  Map<String, dynamic> data = message.data;
  String linkTo = data['notification_link_to'] ?? '';
  String? restaurantId = data['restaurant_id'];

  if (linkTo == 'Offer Section') {
    if (tokenValue != null) {
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => OfferMeScreen()),
      );
    }
  } else if (linkTo == 'Surprise Me Section') {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => HomeScreen(index: 2)),
    );
  } else if (linkTo == 'Restaurant' && restaurantId != null) {
    Provider.of<GeneralController>(context, listen: false)
        .updateNotification(value: linkTo);
    Provider.of<FoodController>(context, listen: false)
        .restaurantDetailApi(context, id: restaurantId);
  }
}

额外注意事项

  1. 确保 navigatorkey 已正确绑定到 MaterialApp:
    final GlobalKey<NavigatorState> navigatorkey = GlobalKey<NavigatorState>();
    
    MaterialApp(
      navigatorKey: navigatorkey,
      // ...其他配置
    );
    
  2. 确认 tokenValue 在使用前已完成初始化,避免空值判断错误。

内容的提问来源于stack exchange,提问作者Mussadaq Ahmad Jamil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 07:55:30