React Native Firebase Messaging导致大量ANR问题寻求解决方案
React Native 应用 Firebase 推送触发ANR修复方案
问题定位
该ANR由io.invertase.firebase.messaging.ReactNativeFirebaseMessagingReceiver广播接收器触发:系统下发FCM推送(对应意图com.google.android.c2dm.intent.RECEIVE)时,接收器默认在主线程同步等待JS线程回调,一旦JS线程处于卡顿、后台冻结、未启动状态,就会阻塞广播处理流程,超过系统广播超时阈值(前台广播10s、后台广播60s)就会触发ANR。网上通用方案未生效基本是没命中版本bug、接收器逻辑阻塞、配置错误这几个核心问题。
可落地修复步骤
- 先锁定无bug的依赖版本
已知@react-native-firebase/messaging在12.1.0~14.2.0版本区间存在主线程同步等待JS回调的已知bug,不要使用这个区间的版本。生产环境验证稳定的版本为11.5.0(旧版稳定线)、15.7.0及以上(新版稳定线),升级/降级依赖后重新打包即可解决80%左右的同类型ANR。 - 替换默认广播接收器,彻底避免主线程阻塞
覆盖SDK默认的消息接收器,将所有推送处理逻辑切到IO线程执行,不占用主线程资源,也不强制等待JS线程响应。
首先在AndroidManifest.xml中替换默认接收器声明:
然后在android工程对应包路径下实现自定义接收器:<receiver android:name=".CustomFirebaseMessagingReceiver" 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" /> </intent-filter> </receiver>import android.content.Context import android.content.Intent import io.invertase.firebase.messaging.ReactNativeFirebaseMessagingReceiver import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch class CustomFirebaseMessagingReceiver : ReactNativeFirebaseMessagingReceiver() { override fun onReceive(context: Context, intent: Intent) { val pendingResult = goAsync() CoroutineScope(Dispatchers.IO).launch { try { super.onReceive(context, intent) } finally { pendingResult.finish() } } } } - 关闭非必要的后台JS拉起配置
如果不需要静默推送触发后台无头JS任务,在android/app/src/main/res/values/strings.xml中添加以下配置,避免推送到达时强制拉起处于冻结/未启动状态的JS线程造成锁等待:
注意:如果业务依赖静默推送做后台数据同步,不要关闭headless js配置,直接用上面自定义接收器的方案即可。<string name="firebase_messaging_auto_init_enabled">true</string> <bool name="rnfirebase_messaging_headless_js_enabled">false</bool> - 排查主线程初始化阻塞问题
部分场景下ANR的根因不是Firebase SDK本身,而是Application.onCreate中做了过多同步耗时操作:比如三方SDK同步初始化、大文件SharedPreferences读写、数据库全量加载等,导致主线程资源被占满,Firebase接收器拿不到执行权超时。将所有非首屏必须的初始化逻辑切到子线程延迟1~2s执行即可。
验证方式
修复后可以通过adb命令模拟多场景推送:反复在应用杀进程、前台切后台、后台长时间驻留状态下执行adb shell am broadcast -a com.google.android.c2dm.intent.RECEIVE -n com.app/.CustomFirebaseMessagingReceiver,观察logcat无ANR报错后,再提交到Google Play预发布测试渠道跑24小时稳定性测试,确认ANR率降到0.1%阈值以下再全量发版。
内容的提问来源于stack exchange,提问作者Waleed Iqbal
相关产品推荐
相关产品推荐

