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

Android Intent Extras值不随FCM新数据更新问题咨询

问题

我使用FCM向Android应用发送通知,通知由FirebaseMessagingService接收并处理,此部分功能正常。我从FCM通知中提取信息,传入FirebaseMessagingService内的函数生成Intent,在发送至MainActivity前,Intent及其Extras包含最新的FCM数据(此阶段一切正常),代码如下:

const val channelId = "notification_channel"
const val channelName = "com.prod.myApp"

fun generateNotification(goToFragment: String, contact_id: String, source_origin: String){

        val intent = Intent(this, MainActivity::class.java)

        intent.putExtra("fragmentToLoad", goToFragment)
        intent.putExtra("contact_id", contact_id)
        intent.putExtra("source_origin", source_origin)

        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)

        val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)

        var builder: NotificationCompat.Builder = NotificationCompat.Builder(applicationContext, channelId)
            .setSmallIcon(R.drawable.ic_baseline_back_hand_24)
            .setAutoCancel(true)
            .setVibrate(longArrayOf(1000, 1000, 1000, 1000))
            .setOnlyAlertOnce(true)
            .setContentIntent(pendingIntent)

        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val notificationChannel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
            notificationManager.createNotificationChannel(notificationChannel)
            }

        notificationManager.notify(0, builder.build())
}

MainActivity接收Intent并按如下逻辑处理:

onNewIntent(intent) //NOTE: See below

if (intent.extras != null) {

            if(intent.hasExtra("fragmentToLoad")){


                when(intent.getStringExtra("fragmentToLoad").toString()){

                    "GetPic" -> {

                        myViewModel.setContactsOrigin(intent.getStringExtra("source_origin").toString())
                        myViewModel.setPostcardContactID(intent!!.getStringExtra("contact_id").toString())
                        supportFragmentManager.findFragmentById(R.id.myNavHostFragment) as NavHostFragment
                        val navController = navHostFragment.navController
                        navController.navigate(R.id.GetPic)
                    }

                    else -> {
                        Log.d("mainActivity","Intent option " + intent.hasExtra("fragmentToLoad").toString() + " is not an anticipated option")
                    }
                }

            }

MainActivity中还单独实现了onNewIntent方法:

override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent) // Update the intent with new data
    }

问题在于MainActivity中getStringExtra("source_origin")的值始终不更新,一直是首次运行时的数值(尽管FirebaseMessagingService中该值已多次修改)。例如首次运行时source_origin为"banana",后续即使改为"orange",MainActivity中仍显示"banana"。打开指定Fragment的功能正常,所有操作在模拟器中进行,多次清理缓存及重启Android Studio均无效。请问该错误持续出现的原因是什么?


原因分析与解决方案

核心原因

问题出在PendingIntent的复用机制:

  • 创建PendingIntent时使用了固定的requestCode=0,且仅设置PendingIntent.FLAG_MUTABLE标记。
  • 系统会缓存相同requestCode、相同组件的PendingIntent,当后续尝试创建新的PendingIntent时,会直接返回缓存的旧实例,不会更新Intent的Extras数据。
  • 这就导致即使你生成了带新数据的Intent,MainActivity收到的仍是第一次缓存的Extras值。

直接修复方案

修改PendingIntent的创建逻辑,添加PendingIntent.FLAG_UPDATE_CURRENT标记,确保Intent内容变化时,系统更新已有的PendingIntent:

val pendingIntent = PendingIntent.getActivity(
    this, 
    0, 
    intent, 
    PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
)

额外优化点

  1. 修复MainActivity的Intent处理逻辑:
    手动调用onNewIntent(intent)是错误的,onNewIntent是系统回调方法,无需手动触发。应将Intent处理逻辑抽成独立方法,在onCreate和onNewIntent中统一调用:
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // 其他初始化代码
        handleIntent(intent)
    }
    
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)
        handleIntent(intent)
    }
    
    private fun handleIntent(intent: Intent) {
        if (intent.extras != null && intent.hasExtra("fragmentToLoad")) {
            when(intent.getStringExtra("fragmentToLoad")) {
                "GetPic" -> {
                    intent.getStringExtra("source_origin")?.let {
                        myViewModel.setContactsOrigin(it)
                    }
                    intent.getStringExtra("contact_id")?.let {
                        myViewModel.setPostcardContactID(it)
                    }
                    val navHostFragment = supportFragmentManager.findFragmentById(R.id.myNavHostFragment) as NavHostFragment
                    val navController = navHostFragment.navController
                    navController.navigate(R.id.GetPic)
                }
                else -> {
                    Log.d("mainActivity","Intent option is not an anticipated option")
                }
            }
        }
    }
    
  2. 避免通知覆盖:
    当前使用notificationManager.notify(0, builder.build())的固定ID0,新通知会直接覆盖旧通知。如果需要保留多条通知,建议使用唯一ID(比如FCM消息的messageId或时间戳)。

内容的提问来源于stack exchange,提问作者stroopwafel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 10:46:22