Flutter集成Firebase Messaging时本地通知触发空指针异常致应用崩溃
崩溃根因定位
从报错栈可以直接定位到,最终触发崩溃的空指针异常出在FlutterLocalNotificationsPlugin.setSmallIcon方法:插件在渲染通知时,需要查找对应的Android小图标资源,但最终拿到的资源ID是null,对这个null值做int拆箱时直接抛出异常,导致应用被系统杀死。
结合你的代码实现,对应的问题点有三个:
- 通知图标资源匹配失败:初始化Android通知时你传的图标标识是
app_icon,自定义聊天样式的Person对象里引用的图标是daisy,这两个标识对应的文件都要放到Android项目的drawable资源目录下。只要文件不存在、文件名大小写不匹配,插件找资源时就会返回null,直接触发本次崩溃。 - 通知接口调用错了:你本来是收到FCM实时推送要弹通知,结果调用的是
showDailyAtTime——这个接口是用来注册每日定时触发的系统通知的,不是即时弹通知用的。当系统的定时通知接收器ScheduledNotificationReceiver被唤起、开始渲染通知时,就会因为找不到图标资源直接抛错。 - 缺空值防护:代码里直接从推送消息里取
message["data"]["title"]、message["data"]["message"]组装通知内容,如果FCM下发的消息结构和预期不一样,这些值就会是null,虽然不是这次崩溃的直接原因,但后续会引发通知样式渲染的异常。
具体修复步骤
- 先把通知图标资源配对
把代码里用到的app_icon、daisy两个图标,全部放到android/app/src/main/res/drawable的对应分辨率子目录里,保证文件名和代码里传的字符串完全一致,不要带后缀、不要出现大小写不匹配的情况。这里要注意:这个插件找图标只会扫drawable目录,把图标放到mipmap目录是识别不到的,一样会触发资源找不到的空指针。 - 把弹通知的接口换成即时触发的
把原来调showDailyAtTime的地方,换成插件提供的即时弹出接口show,同时给所有从推送消息里取的值加空值兜底,核心代码改成这样:await flutterLocalNotificationsPlugin.show( 1, message["data"]?["title"] ?? "默认通知标题", message["data"]?["message"] ?? "默认通知内容", platformChannelSpecifics, ); - 提前创建高版本Android要求的通知渠道
Android 8.0以上的系统,所有通知必须绑定预先注册好的通知渠道才能正常弹出来。你代码里AndroidNotificationDetails用的渠道ID是1234,得在插件初始化的时候就把这个渠道创建好,不然就算没崩溃,通知也不会弹。加的代码大概是这样:// 放在initializeFCMNotification方法里,插件初始化的逻辑后面 const AndroidNotificationChannel pushChannel = AndroidNotificationChannel( '1234', 'Yeni Mesaj', 'your channel description', importance: Importance.max, ); await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(pushChannel); - 给后台消息回调加初始化兜底
要把全局的flutterLocalNotificationsPlugin实例放在应用启动的最前面完成初始化,别等用户进了页面才初始化,不然系统在后台唤起myBackgroundMessageHandler回调的时候,插件还没初始化好,就会触发空引用。
内容的提问来源于stack exchange,提问作者Serife
相关产品推荐
相关产品推荐

