Flutter Firebase推送通知报错:Integer.intValue()空对象引用
问题分析与解决方案
根据你提供的错误日志和代码,java.lang.NullPointerException: Attempt to invoke virtual method 'int java.lang.Integer.intValue()' on a null object reference 错误源自 Android 端的本地通知插件调用,结合代码细节,以下是具体问题和修复方案:
核心问题定位
- 冗余的通知展示调用:在
onMessageOpenedApp中调用createanddisplaynotification是不必要的——当应用处于后台时,Firebase 已自动展示通知,重复调用会导致冲突。 - 未处理的空值参数:
message.notification!.title和message.notification!.body可能为 null,直接使用!强制解包后传递给通知展示方法,会触发 Android 端的空指针异常。 - 后台隔离区的错误操作:
onDidReceiveBackgroundNotificationResponse运行在后台隔离区,无法直接使用Navigator或Provider,会导致上下文为空的错误。 - 未显式创建通知渠道:虽然插件会自动创建渠道,但显式创建可避免渠道初始化延迟导致的问题。
修复后的代码
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); } }
额外注意事项
- 确保
navigatorkey已正确绑定到MaterialApp:final GlobalKey<NavigatorState> navigatorkey = GlobalKey<NavigatorState>(); MaterialApp( navigatorKey: navigatorkey, // ...其他配置 ); - 确认
tokenValue在使用前已完成初始化,避免空值判断错误。
内容的提问来源于stack exchange,提问作者Mussadaq Ahmad Jamil
相关产品推荐
相关产品推荐

