Unity迁移Asset包后Firebase Cloud Messaging安卓首次启动崩溃求助
问题背景
2021年7月谷歌要求Unity开发者从UPM包迁移至Asset包。我将Unity游戏项目从UPM包切换为Asset包后,安卓设备上出现约10%的启动崩溃问题。
- 崩溃触发条件:仅在旧版本应用覆盖安装新版本时出现,首次启动崩溃后关闭应用重新打开即可恢复,后续不再复现
- 无法回退UPM原因:谷歌已停止通过UPM渠道提供Firebase SDK更新,旧版本SDK无法正常运行
项目环境
- Unity版本:2019.4.30f1(2019.4系列最新版)
- 脚本后端:IL2CPP
- .NET版本:4.x
- 安卓最低API等级:21(Android 5.0)
- NDK/SDK:使用Unity Android模块自带版本
问题排查进展
该问题仅出现在Firebase v8.x.x及以上版本,将Firebase回退到v8之前的7.2.0版本后,崩溃问题完全消失。
崩溃日志
Fatal Exception: java.lang.Error FATAL EXCEPTION [UnityMain] Unity
version : 2019.4.30f1 Device model : ZTE ZTE BLADE V8 MINI Device
fingerprint:
ZTE/P840F01_MX_ATT/ZTE_BLADE_V0850:7.0/NRD90M/20170602.144530:user/release-keys
Caused by java.lang.Error
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Version '2019.4.30f1 (e8c891080a1f)', Build type 'Release', Scripting
Backend 'il2cpp', CPU 'arm64-v8a' Build fingerprint:
'ZTE/P840F01_MX_ATT/ZTE_BLADE_V0850:7.0/NRD90M/20170602.144530:user/release-keys'
Revision: '0' ABI: 'arm64' Timestamp: 2021-10-15 21:23:49-0500 pid:
19756, tid: 20100, name: Thread-93 >>> com.infinitygames.pipes <<<
uid: 10649 signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8
Cause: null pointer dereference x0 0000000000000008 x1
0000007e4f9fe490 x2 0000000000000004 x3 0000007e4f9fe509 x4
0000007e4f9fe448 x5 0000000080000000 x6 0000008000000000 x7
5e6f5e20fffefefe x8 0000000000000000 x9 6472606164716865 x10
7f7f7f7f7f7f7f7f x11 0101010101010101 x12 0000000000000018 x13
00000000ffffffff x14 00000000000cb140 x15 2e8ba2e8ba2e8ba3 x16
0000007e4fff13a8 x17 0000007fa5ee4d98 x18 00000000ffffffff x19
0000000000000000 x20 0000007e4f9fe490 x21 0000007e4f9fe448 x22
0000000000000000 x23 0000007e4f9fe509 x24 0000000000000004 x25
0000000000000008 x26 0000007e4f9fe508 x27 0000000000000001 x28
0000007e4ea92c90 x29 0000007e4f9fe778 sp 0000007e4f9fe3f0 lr
0000007e4fec43ac pc 0000007fa5ee4d98 backtrace: #00 pc
0000000000068d98 /system/lib64/libc.so (pthread_mutex_lock) (BuildId:
359947b8d684fe3e8ea897ca5e978f06) #01 pc 00000000001fe3a8
/data/app/com.infinitygames.pipes-1/lib/arm64/libFirebaseCppApp-8_3_0.so
(firebase::Mutex::Acquire()+4) (BuildId:
8209be713e18b8cc0f0f9cdc20b6d1f4) #02 pc 0000000000203c8c
/data/app/com.infinitygames.pipes-1/lib/arm64/libFirebaseCppApp-8_3_0.so
(void
firebase::ReferenceCountedFutureImpl::CompleteInternal<std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator >, void
firebase::ReferenceCountedFutureImpl::CompleteWithResultInternal<std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator > >
(firebase::FutureHandle const&, int, char const*, std<truncated: 1671 chars>
libc.pthread_mutex_lock (pthread_mutex_lock)
libFirebaseCppApp-8_3_0.firebase::Mutex::Acquire() (Acquire:4)
libFirebaseCppApp-8_3_0.void
firebase::ReferenceCountedFutureImpl::CompleteInternal<std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator >, void
firebase::ReferenceCountedFutureImpl::CompleteWithResultInternal<std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator >
(firebase::FutureHandle const&, int, char const*, std::__ndk1::basic_string<char, std::__ndk1::char_traits,
std::__ndk1::allocator >
const&)::'lambda'(std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator
- )>(firebase::FutureHandle const&, int, char const*, void firebase::ReferenceCountedFutureImpl::CompleteWithResultInternal<std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator >
(firebase::FutureHandle const&, int, char const*, std::__ndk1::basic_string<char, std::__ndk1::char_traits,
std::__ndk1::allocator >
const&)::'lambda'(std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator >)
const&) (allocator > >:44) libFirebaseCppApp-8_3_0.void
firebase::ReferenceCountedFutureImpl::CompleteWithResultInternal<std::__ndk1::basic_string<char,
std::__ndk1::char_traits, std::__ndk1::allocator >
(firebase::FutureHandle const&, int, char const, std::__ndk1::basic_string<char, std::__ndk1::char_traits,
std::__ndk1::allocator > const&) (allocator > >:64)
libFirebaseCppApp-8_3_0.firebase::messaging::CompleteStringCallback(_JNIEnv*,
_jobject*, firebase::util::FutureResult, char const*, void*) (CompleteStringCallback:136)
libFirebaseCppApp-8_3_0.firebase::util::JniResultCallback_nativeOnResult(_JNIEnv*,
_jobject*, _jobject*, unsigned char, unsigned char, _jstring*, long, long) (JniResultCallback_nativeOnResult:172) app_resources_lib.0x6098
可行解决方案
- 版本回退:若业务功能可兼容Firebase 7.x版本,直接回退到7.2.0版本即可完全解决崩溃问题,该版本不存在覆盖安装的空指针异常问题
- 版本升级:若必须使用Firebase 8.x及以上版本,可升级到Firebase 8.6.0以上版本,官方已在该版本修复了Mutex锁空指针的底层问题
- 延迟初始化:如果暂时无法升级版本,可修改Firebase初始化逻辑,不要在Unity启动的第一帧就初始化Firebase Messaging,等待首帧渲染完成后延迟1~2秒再进行初始化,规避旧版本残留数据读取时的线程安全问题
- 本地数据清理:在应用首次启动时,先清理Firebase相关的本地缓存数据后再执行初始化,避免新旧版本数据格式不兼容导致的底层崩溃
内容的提问来源于stack exchange,提问作者Amir Khavari

