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

如何区分应用从无数据FCM通知与应用图标启动的场景?

区分FCM通知启动与应用图标启动的方案

这个问题我做FCM集成时也碰到过,确实因为通知不带数据,导致常规的extras判断失效,不过有两个比较靠谱的解决思路:

方法一:利用FCM的click_action字段(推荐)

这是最直接的方案,只需要后端在推送通知时添加click_action参数,就能让系统在用户点击通知时,给启动Intent带上自定义的Action,以此区分图标启动的场景。

步骤1:后端修改推送Payload

在FCM的通知Payload里加入click_action,指定一个自定义的Action名称,比如OPEN_NOTIFICATION_SECTION:

{
  "notification": {
    "title": "你的通知标题",
    "click_action": "OPEN_NOTIFICATION_SECTION"
  },
  "to": "目标设备的FCM令牌"
}

步骤2:配置AndroidManifest.xml

给你的主Activity添加对应的<intent-filter>,让它能响应这个自定义Action:

<activity
    android:name=".MainActivity"
    android:exported="true">
    <!-- 原有图标启动的intent-filter -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    <!-- 新增处理通知点击的intent-filter -->
    <intent-filter>
        <action android:name="OPEN_NOTIFICATION_SECTION" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

步骤3:在Activity中判断启动来源

在MainActivity的onCreate和onNewIntent(如果是singleTop等启动模式)里,通过Intent的Action来区分:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    handleLaunchIntent(intent)
}

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    setIntent(intent)
    handleLaunchIntent(intent)
}

private fun handleLaunchIntent(intent: Intent?) {
    intent?.let {
        when (it.action) {
            "OPEN_NOTIFICATION_SECTION" -> {
                // 来自通知点击,跳转到通知板块
                navigateToNotificationSection()
            }
            "android.intent.action.MAIN" -> {
                // 来自应用图标点击,正常初始化
            }
        }
    }
}

private fun navigateToNotificationSection() {
    // 这里写跳转到通知板块的逻辑,比如Fragment跳转或Activity跳转
    supportFragmentManager.beginTransaction()
        .replace(R.id.container, NotificationFragment())
        .commit()
}

方法二:自定义通知构建(适用于无法修改后端Payload的场景)

如果后端没办法调整推送内容,你可以在客户端拦截FCM通知,自己构建带有标识的PendingIntent,替换系统默认的通知行为。

步骤1:实现FirebaseMessagingService

创建自定义的FirebaseMessagingService,在onMessageReceived中自己构建通知,并给PendingIntent添加自定义标识:

class MyFirebaseMessagingService : FirebaseMessagingService() {
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
        super.onMessageReceived(remoteMessage)
        remoteMessage.notification?.let { fcmNotification ->
            // 构建启动Intent,添加自定义标识
            val launchIntent = packageManager.getLaunchIntentForPackage(packageName)?.apply {
                putExtra("FROM_FCM_NOTIFICATION", true)
                flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
            } ?: return

            val pendingIntent = PendingIntent.getActivity(
                this,
                0,
                launchIntent,
                PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

            // 构建自定义通知
            val notificationBuilder = NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL_ID")
                .setSmallIcon(R.drawable.ic_notification)
                .setContentTitle(fcmNotification.title ?: "")
                .setPriority(NotificationCompat.PRIORITY_DEFAULT)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)

            // 确保通知渠道存在(Android 8.0+要求)
            val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channel = NotificationChannel(
                    "NOTIFICATION_CHANNEL_ID",
                    "通知频道",
                    NotificationManager.IMPORTANCE_DEFAULT
                )
                notificationManager.createNotificationChannel(channel)
            }

            // 显示自定义通知
            notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build())
        }
    }
}

步骤2:在Activity中判断标识

和方法一类似,在MainActivity中读取Intent的自定义参数:

private fun handleLaunchIntent(intent: Intent?) {
    intent?.let {
        val fromNotification = it.getBooleanExtra("FROM_FCM_NOTIFICATION", false)
        if (fromNotification) {
            navigateToNotificationSection()
        }
    }
}

注意:这个方法的前提是,应用在后台时FCM会将通知消息传递到onMessageReceived。但根据FCM规则,当应用完全未运行时,纯通知消息会由系统直接展示,不会进入onMessageReceived,所以这种情况下方法一的兼容性更好。

内容的提问来源于stack exchange,提问作者Lucas P.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 19:52:37