如何将FCM通知的data payload传递给导航图起始目的地Fragment参数
FCM同时携带notification与data字段时参数传递方案
问题根源
当FCM消息同时包含notification和data字段、应用处于后台时,系统会直接生成通知栏消息,用户点击后触发的启动Intent由系统构造,所有data payload参数会直接挂载到目标Activity的intent.extras中。导航组件默认不会自动将Activity Intent的参数同步给导航图的起始目的地,因此无法直接通过Fragment参数获取对应值。
可直接传递参数给起始Fragment的解决方案
不需要强制在Fragment中读取Activity的Intent,通过导航组件原生API即可实现和纯data字段FCM消息完全一致的参数传递逻辑:
- 恢复导航图起始目的地的
startingId参数定义,保留默认值0即可 - 在宿主Activity的
onCreate方法中,设置导航图时传入Activity Intent的extras:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment val navController = navHostFragment.navController // 第二个参数即为传递给起始目的地的参数Bundle navController.setGraph(navController.graph, intent.extras) }
- 之后在起始Fragment中即可直接通过
by navArgs()正常获取参数:
private val args by navArgs<StartFragmentArgs>() private val startingId by lazy { args.startingId }
特殊场景适配
如果你的Activity配置了singleTop/singleTask等启动模式,点击通知时会复用已存在的Activity实例,触发onNewIntent回调,需要补充参数同步逻辑:
override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) intent ?: return val navController = findNavController(R.id.nav_host_fragment) // 方式1:重新设置导航图传入新参数(适合需要重置导航栈的场景) navController.setGraph(navController.graph, intent.extras) // 方式2:仅更新当前栈顶目的地的参数,不重置导航栈(适合保留用户操作路径的场景) // navController.currentBackStackEntry?.arguments?.putAll(intent.extras) }
注意事项
- 需保证导航图中
startingId参数的类型和FCM传过来的类型匹配,如果怕类型自动解析出错,可以先手动从Intent中取出startingId转成对应类型后,构造新的Bundle传给setGraph方法 - 应用在前台时收到带
notification的FCM消息,还是会触发FirebaseMessagingService的onMessageReceived回调,按照原有逻辑构造PendingIntent传入参数即可,两端参数获取逻辑完全统一
内容的提问来源于stack exchange,提问作者Cruces
相关产品推荐
相关产品推荐

