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

应用关闭时接收FCM触发ANR问题求助

解决FCM消息触发应用关闭状态下的ANR问题

问题背景

应用处于关闭状态时接收FCM消息,触发大量ANR,ANR日志指向FirebaseInstanceIdReceiver处理com.google.android.c2dm.intent.RECEIVE意图。已尝试升降级Firebase SDK、配置指定Manifest组件,但问题仍未解决。

排查与解决步骤

1. 替换废弃的FirebaseInstanceIdReceiver

从Firebase SDK 21.0.0版本开始,FirebaseInstanceIdReceiver已被废弃,官方推荐使用FirebaseMessagingReceiver替代。修改Manifest中的接收器配置:

<receiver
    android:name="com.google.firebase.messaging.FirebaseMessagingReceiver"
    android:exported="true"
    android:permission="com.google.android.c2dm.permission.SEND">
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <action android:name="com.google.android.c2dm.intent.REGISTRATION" />
        <category android:name="${applicationId}" />
    </intent-filter>
</receiver>

旧接收器在新版本SDK中存在后台场景下的兼容性问题,是触发ANR的常见诱因。

2. 优化FirebaseMessagingService的消息处理逻辑

广播接收器的主线程执行超时限制为10秒,一旦onMessageReceived中存在耗时操作就会触发ANR:

  • 避免在主线程执行网络请求、数据库读写等阻塞任务,改用协程、AsyncTask或WorkManager移至后台处理
  • 显示通知的操作直接调用NotificationManagerCompat完成,不要附加复杂逻辑
  • 数据消息的解析、业务处理全部放在后台线程执行

示例优化后的代码:

override fun onMessageReceived(remoteMessage: RemoteMessage) {
    // 通知消息直接快速处理
    remoteMessage.notification?.let {
        val notification = NotificationCompat.Builder(this, getString(R.string.notification_channel_id))
            .setContentTitle(it.title)
            .setContentText(it.body)
            .setSmallIcon(R.drawable.ic_notification)
            .build()
        NotificationManagerCompat.from(this).notify(System.currentTimeMillis().toInt(), notification)
    }
    
    // 数据消息移至后台处理
    CoroutineScope(Dispatchers.IO).launch {
        processDataPayload(remoteMessage.data)
    }
}

3. 排查应用启动阶段的阻塞操作

应用关闭时接收FCM消息会触发进程重启,若Application或启动页的onCreate中存在耗时初始化(如SDK预加载、大量IO操作),会直接导致ANR:

  • 将非必要的初始化逻辑延迟到首屏启动后执行
  • 对必须提前初始化的SDK,采用异步初始化方式

4. 检查FCM消息类型与payload大小

  • 若发送的是通知消息(含notification字段),系统会直接处理显示,不会触发onMessageReceived;若仍出现ANR,可尝试改为纯数据消息(仅含data字段),由应用自行控制处理流程
  • 确保消息payload不超过FCM限制的4KB,过大的数据会增加解析耗时

5. 用StrictMode定位主线程阻塞

在Debug版本中启用StrictMode,检测主线程的违规操作:

override fun onCreate() {
    if (BuildConfig.DEBUG) {
        StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
            .detectAll()
            .penaltyLog()
            .build())
        StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder()
            .detectAll()
            .penaltyLog()
            .build())
    }
    super.onCreate()
}

通过Logcat中的StrictMode警告,精准定位主线程中耗时的代码块。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 05:20:29