Android应用点击通知跳转投票Fragment时崩溃 非发送端设备闪退
问题根因定位
- 崩溃核心触发点从堆栈可以直接定位:导航组件跳转投票页时抛出类型不匹配异常,明确提示
surveyId参数要求传入String类型,实际传入值类型不符合要求。 - 逻辑错误出在通知跳转参数的获取逻辑:你构建通知跳转的PendingIntent时,参数全部取自本地进程内的
SurveySingleton单例对象。这个单例的数据只存在于当前运行的应用进程内存里:管理员操作发通知的设备,当时刚走完投票创建流程,单例里已经存了本次投票的有效surveyId字符串,所以点击通知能正常跳转;其他用户设备收到通知时,要么应用没启动单例根本没初始化,要么单例里没有存本次投票的对应数据,此时getSurveyId()取到的是null或者单例默认的非String类型值(比如你可能在单例里把surveyId定义成了long/int类型),直接触发导航组件的参数类型校验,导致崩溃。 - 额外隐藏问题:你现在的自定义通知构建逻辑写在
onMessageReceived里,这个回调只有应用在前台活跃时才会被Firebase触发。如果应用在后台、或者被系统杀死,Firebase会直接走系统默认通知通道,不会执行你写的这段代码,哪怕修复了当前崩溃,后台场景下的通知跳转也会失效。
修复方案
- 第一步:替换参数获取逻辑,禁止依赖本地单例传推送跳转参数
管理员推送通知时,把投票需要的surveyId、email、storyNumber等字段放到Firebase消息的data载荷里,客户端收到消息时直接从消息载荷中取参数,不要读取本地内存的单例数据,同时加非空兜底避免参数缺失:// 删除原来从SurveySingleton取参数的代码,替换为以下逻辑 Bundle args = new Bundle(); // 从推送消息的data字段取参数,推送端需保证这些字段随消息下发 Map<String, String> pushData = remoteMessage.getData(); String surveyId = pushData.get("surveyId"); String email = pushData.get("email"); String storyNumStr = pushData.get("storyNumber"); int storyNumber = 0; if (!TextUtils.isEmpty(storyNumStr)) { try { storyNumber = Integer.parseInt(storyNumStr); } catch (NumberFormatException e) { storyNumber = 0; } } // 空值兜底,避免传null触发类型校验异常 args.putString("surveyId", surveyId == null ? "" : surveyId); args.putString("email", email == null ? "" : email); args.putInt("storyNumber", storyNumber); - 第二步:对齐导航图的参数类型定义
打开nav_graph.xml,找到surveyFragment对应的配置项,确认所有参数的argType和你传入的类型完全匹配,参考配置如下:<fragment android:id="@+id/surveyFragment" android:name="praksa.atos.evotingsystem.view.SurveyFragment"> <argument android:name="surveyId" app:argType="string" android:defaultValue="" /> <argument android:name="email" app:argType="string" android:defaultValue="" /> <argument android:name="storyNumber" app:argType="integer" android:defaultValue="0" /> </fragment> - 第三步:兼容应用后台/被杀场景的通知跳转
不要完全依赖onMessageReceived里的自定义通知逻辑:当应用不在前台时Firebase不会触发该回调,会自动根据notification字段生成系统通知,你需要给推送消息配置对应导航目的地的deeplink,或者在MainActivity的onCreate和onNewIntent生命周期里统一解析Intent携带的参数,手动触发导航到投票页,保证所有场景下点击通知都能正常跳转。 - 第四步:在Fragment侧加参数兜底
在SurveyFragment取启动参数时,先做类型校验和非空判断,不要直接强转取值,避免极端场景下参数缺失导致崩溃。
内容的提问来源于stack exchange,提问作者zmesinger
相关产品推荐
相关产品推荐

