Android:Firebase推送通知深度链接冷启动失效(仅应用运行时正常)
Android:Firebase推送通知深度链接冷启动失效(仅应用运行时正常)
我之前也碰到过几乎一模一样的问题!结合你用的FCM+Jetpack Compose Navigation技术栈,给你梳理几个关键的排查点和解决方法,亲测有效:
1. 先把AndroidManifest的配置拉满,别漏关键项
冷启动时系统是直接通过启动Activity处理深度链接的,这里最容易踩坑。首先确保你的启动Activity(比如MainActivity)配置正确:
- 必须设置
android:exported="true"(API31+强制要求,否则系统无法启动它处理外部Intent) - 深度链接的
<intent-filter>里要包含DEFAULT和BROWSABLE类别,data标签要对应你的scheme和host
示例配置:
<activity android:name=".MainActivity" android:exported="true" android:launchMode="singleTop"> <!-- 推荐用singleTop避免多实例 --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <!-- 深度链接专属Intent Filter --> <intent-filter android:autoVerify="true"> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="appName" android:host="chat" /> </intent-filter> </activity>
2. 冷启动时要手动把Intent传递给Compose NavHost
Compose Navigation初始化需要时间,冷启动时如果直接在NavHost初始化时获取Intent,可能拿不到最新的链接。可以在Activity里用State保存深度链接,等NavHost ready后再触发导航:
class MainActivity : ComponentActivity() { // 用State保存深度链接,确保Compose能感知变化 private val pendingDeepLink = mutableStateOf<Uri?>(null) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 冷启动时从Intent里捞深度链接 intent?.data?.let { pendingDeepLink.value = it } setContent { YourAppTheme { val navController = rememberNavController() // 当pendingDeepLink有值时,触发导航 LaunchedEffect(pendingDeepLink.value) { pendingDeepLink.value?.let { uri -> navController.navigate(uri) { launchSingleTop = true // 避免重复打开页面 restoreState = true // 恢复之前的页面状态(可选) } // 导航后清空,防止Activity重建时重复触发 pendingDeepLink.value = null } } NavHost(navController = navController, startDestination = "home") { // 一定要给Chat页面配置对应的深度链接规则 composable( route = "chat/{chatId}/{userId}", deepLinks = listOf( navDeepLink { uriPattern = "appName://chat/{chatId}/{userId}" } ) ) { backStackEntry -> val chatId = backStackEntry.arguments?.getString("chatId") val userId = backStackEntry.arguments?.getString("userId") ChatScreen(chatId, userId) } // 其他页面的导航配置... } } } } // 热启动时(App在后台),新的Intent会走onNewIntent,这里也要处理 override fun onNewIntent(intent: Intent?) { super.onNewIntent(intent) intent?.data?.let { pendingDeepLink.value = it } } }
3. 检查FCM消息的Payload格式,别用错字段
如果你的推送是用Notification Payload,系统可能会在App后台时直接处理通知,导致深度链接没正确传递。更推荐用Data Payload,这样所有字段都会直接传给你的App:
示例FCM Data Payload:
{ "to": "你的设备Token", "data": { "link": "appName://chat/123/456", "title": "新消息提醒", "body": "有人给你发了一条消息" } }
然后在你的FirebaseMessagingService里,要正确构建PendingIntent,把深度链接传进去:
class MyFirebaseMessagingService : FirebaseMessagingService() { override fun onMessageReceived(remoteMessage: RemoteMessage) { super.onMessageReceived(remoteMessage) val deepLink = remoteMessage.data["link"] ?: return // 构建打开深度链接的Intent val deepLinkIntent = Intent(Intent.ACTION_VIEW, Uri.parse(deepLink)) deepLinkIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP) // 注意:API30+必须加FLAG_IMMUTABLE或FLAG_MUTABLE val pendingIntent = PendingIntent.getActivity( this, 0, deepLinkIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE ) // 构建通知并显示 val notification = NotificationCompat.Builder(this, "你的通知渠道ID") .setContentTitle(remoteMessage.data["title"]) .setContentText(remoteMessage.data["body"]) .setSmallIcon(R.drawable.ic_notification) .setContentIntent(pendingIntent) .setAutoCancel(true) .build() NotificationManagerCompat.from(this).notify(1, notification) } }
4. 测试冷启动的正确姿势
别以为划掉最近应用就是冷启动了!有些设备会保留App进程,正确的测试方法是:
- 划掉最近应用里的App
- 等待3-5秒(确保系统杀死进程)
- 再点击推送通知
额外坑:如果有启动页(SplashScreen)
如果你用了SplashActivity,一定要把它的Intent完整传递给MainActivity,不然深度链接会丢:
class SplashActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 把Splash的Intent所有数据传递给MainActivity val mainIntent = Intent(this, MainActivity::class.java) mainIntent.putExtras(intent) mainIntent.data = intent.data startActivity(mainIntent) finish() } }
备注:内容来源于stack exchange,提问作者RJnr
相关产品推荐
相关产品推荐

