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

从通知冷启动Android应用时如何获取Intent Extras?

应用冷启动时点击通知无法获取Intent Extras的解决方法

问题描述

当应用未运行或不在后台时,点击通知启动应用无法获取Intent中的extras;但应用处于运行或后台状态时,可正常获取这些extras。当前SplashActivity为应用的主活动,需解决冷启动时获取extras的问题。

问题重现

冷启动时SplashActivity的日志显示:

onCreate: intent action android.intent.action.MAIN
onCreate: intent test extra -1 // 预期值为16

相关代码

PushNotificationService代码

val intent = Intent(this, SplashActivity::class.java).apply {
    flags = FLAG_ACTIVITY_NEW_TASK or FLAG_ACTIVITY_CLEAR_TASK
    putExtra("TEST", 16)
}
val pendingIntent = PendingIntent.getActivity(this, Random.nextInt(), intent, FLAG_IMMUTABLE or FLAG_UPDATE_CURRENT)

AndroidManifest配置

<application
    android:name=".HiltApplication"
    android:allowBackup="true"
    android:icon="@mipmap/app_logo"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/app_logo_round"
    android:supportsRtl="true"
    android:theme="@style/Theme.X">
    <activity
        android:name=".SplashActivity"
        android:exported="true"
        android:screenOrientation="portrait"
        android:theme="@style/Theme.X.Splash">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <service
        android:name=".service.PushNotificationService"
        android:exported="false">
        <intent-filter>
            <action android:name="com.google.firebase.MESSAGING_EVENT" />
        </intent-filter>
    </service>
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_channel_id"
        android:value="@string/notification_channel_general" />
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_icon"
        android:resource="@mipmap/app_logo" />
    <meta-data
        android:name="com.google.firebase.messaging.default_notification_color"
        android:resource="@color/blue" />
</application>

SplashActivity代码

@AndroidEntryPoint
class SplashActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        Splash()
    }

    Log.d("SPLASH", "onCreate: intent action ${intent.action}")
    Log.d("SPLASH", "onCreate: intent test extra ${intent.getIntExtra("TEST", -1)}")
}

}

FCM通知Payload

const message = {
    token: "TOKEN",
    notification: {
        title: d.title,
        body: d.content
    },
    android: {
        notification: {
            channel_id: "fcm_channel",
        },
    },
    data: {
        title: d.title,
        content: d.content,
    },
};

问题原因

当FCM消息包含notification字段时,若应用处于后台或未运行状态,系统会自动接管通知展示,此时点击通知会直接启动应用的Launcher Activity(SplashActivity),并不会使用你在PushNotificationService中创建的自定义PendingIntent,导致手动添加的TEST extra无法被传递。

解决方案

方案一:手动构建并展示通知(推荐)

在onMessageReceived中手动创建并展示通知,完全控制通知的点击行为,确保自定义extras能被传递:

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    super.onMessageReceived(remoteMessage)
    
    // 构建跳转Intent,携带自定义参数和FCM data数据
    val intent = Intent(this, SplashActivity::class.java).apply {
        flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
        putExtra("TEST", 16)
        // 遍历FCM data字段,添加到Intent中
        remoteMessage.data.forEach { (key, value) ->
            putExtra(key, value)
        }
    }
    
    // 创建唯一的PendingIntent,避免被覆盖
    val pendingIntent = PendingIntent.getActivity(
        this,
        System.currentTimeMillis().toInt(),
        intent,
        PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
    )
    
    // 构建通知
    val notificationBuilder = NotificationCompat.Builder(this, getString(R.string.notification_channel_general))
        .setSmallIcon(R.mipmap.app_logo)
        .setColor(ContextCompat.getColor(this, R.color.blue))
        .setContentTitle(remoteMessage.notification?.title ?: "")
        .setContentText(remoteMessage.notification?.body ?: "")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .setAutoCancel(true)
    
    // 展示通知
    val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
    notificationManager.notify(System.currentTimeMillis().toInt(), notificationBuilder.build())
}

方案二:调整Intent Flags并完善Activity逻辑

  1. 修改PendingIntent的Flags,避免使用FLAG_ACTIVITY_CLEAR_TASK,改用可保留extras的组合:
val intent = Intent(this, SplashActivity::class.java).apply {
    flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
    putExtra("TEST", 16)
}
  1. 在SplashActivity中重写onNewIntent,统一处理Intent extras:
@AndroidEntryPoint
class SplashActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            Splash()
        }
        handleIntentExtras(intent)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        setIntent(intent) // 更新当前Intent为最新的跳转Intent
        handleIntentExtras(intent)
    }

    private fun handleIntentExtras(intent: Intent?) {
        intent?.let {
            Log.d("SPLASH", "intent action ${it.action}")
            val testExtra = it.getIntExtra("TEST", -1)
            Log.d("SPLASH", "intent test extra $testExtra")
            // 处理FCM data中的内容
            val title = it.getStringExtra("title")
            val content = it.getStringExtra("content")
            Log.d("SPLASH", "FCM data title: $title, content: $content")
        }
    }
}

方案三:仅发送Data类型消息

在FCM消息Payload中移除notification字段,只保留data字段,这样所有消息都会被传递到onMessageReceived方法,无论应用状态如何,你可以完全自定义通知行为:

const message = {
    token: "TOKEN",
    data: {
        title: d.title,
        content: d.content,
        "TEST": "16" // Data字段的值必须为字符串类型
    },
    android: {
        notification: {
            channel_id: "fcm_channel",
        },
    },
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 23:19:55