本页面提供了问题排查帮助,并解答了有关使用 Crashlytics 的常见问题。如果您找不到想要的内容或需要其他帮助,请与 Firebase 支持团队联系。
常规问题排查/常见问题解答
没有看到“未遇到崩溃问题”指标和/或“疾速崩溃提醒”
如果您没有看到“未遇到崩溃问题”指标(例如未遇到崩溃问题的用户数和未发生崩溃问题的活跃日)和/或疾速崩溃提醒,请确保您使用的是
Crashlytics SDK v18.6.0+(或 Firebase BoM v32.6.0+)。
没有看到面包屑导航日志
如果您没有看到面包屑导航日志,我们建议您检查应用的 Google Analytics 配置。请确保您符合以下要求:
为什么仅对 Android 11 及更高版本报告 ANR?
Crashlytics 支持对搭载 Android 11 及更高版本的设备中的 Android 应用报告 ANR。我们用于收集 ANR 的底层 API (getHistoricalProcessExitReasons) 比基于 SIGQUIT 或基于监控定时器的方法更加可靠。此 API 仅适用于 Android 11 及更高版本的设备。
为什么有些 ANR 缺少 BuildId
?
如果您的某些 ANR 缺少 BuildId
,请按如下方式进行问题排查:
确保您使用的是最新版 Crashlytics Android SDK 和 Crashlytics Gradle 插件。
如果是在 Android 11 和某些 Android 12 ANR 中缺少 BuildId
,则可能是因为您使用的 SDK 和/或 Gradle 插件已过时。如要正确收集这些 ANR 的 BuildId
,您需要使用以下版本:
- Crashlytics Android SDK 18.3.5 版及更高版本 (Firebase BoM v31.2.2+)
- Crashlytics Gradle 插件 2.9.4 版及更高版本
检查您的共享库是否使用了非标准位置。
如果只有应用的共享库缺少 BuildId
,则可能是因为您的共享库没有使用标准的默认位置。在这种情况下,Crashlytics 可能无法找到关联的 BuildId
。建议考虑让共享库使用标准位置。
确保您没有在构建流程中删除 BuildId
。
请注意,以下问题排查提示对 ANR 和原生代码崩溃都适用。
通过对二进制文件运行 readelf -n
来检查 BuildId
是否存在。如果 BuildId
不存在,请将 -Wl,--build-id
添加到构建系统的标志中。
确保您没有因缩减 APK 大小而无意中删除 BuildId
。
如果您同时保留了缩减版和完整版的库,请务必在代码中指向正确的版本。
Crashlytics 信息中心和 Google Play 管理中心的 ANR 报告之间的区别
Google Play 和 Crashlytics 中的 ANR 计数可能不一致。这在意料之中,因为两者的 ANR 数据收集和报告机制有所不同。Crashlytics 会在应用下次启动时报告 ANR,而 Android Vitals 会在发生 ANR 后即刻发送 ANR 数据。
此外,Crashlytics 仅显示搭载 Android 11 及更高版本的设备上发生的 ANR,而 Google Play 则显示使用 Google Play 服务且同意进行数据收集的设备上的 ANR。
Crashlytics 信息中心和 Logcat 中的 NDK 堆栈轨迹之间的差异
LLVM 和 GNU 工具链针对您应用中的二进制文件只读段提供不同的默认值和处理方式,这可能会在 Firebase 控制台中生成不一致的堆栈轨迹。如需缓解此问题,请在构建流程中添加以下链接器标志:
如果堆栈轨迹仍不一致(或者两个标志都不适用于您的工具链),请试试将以下内容添加到构建流程:
-fno-omit-frame-pointer
如何将我自己的 Breakpad 符号文件生成器二进制程序用于 NDK?
Crashlytics 插件捆绑了一个定制的 Breakpad 符号文件生成器。
如果您希望使用自己的二进制程序来生成 Breakpad 符号文件(例如,如果您希望在自己的 build 链中从源代码构建所有原生可执行文件),请使用可选的 symbolGeneratorBinary
扩展属性来指定可执行文件的路径。
您可以通过以下方法指定 Breakpad 符号文件生成器二进制程序的路径:
方法 1:在 build.gradle
文件中通过 firebaseCrashlytics
扩展指定路径
将以下内容添加到您的应用级 build.gradle.kts
文件:
Gradle 插件 v3.0.0+
android {
buildTypes {
release {
configure<CrashlyticsExtension> {
nativeSymbolUploadEnabled = true
// Add these optional fields to specify the path to the executable
symbolGeneratorType = "breakpad"
breakpadBinary = file("/PATH/TO/BREAKPAD/DUMP_SYMS")
}
}
}
}
较低的插件版本
android {
// ...
buildTypes {
// ...
release {
// ...
firebaseCrashlytics {
// existing; required for either symbol file generator
nativeSymbolUploadEnabled true
// Add this optional new block to specify the path to the executable
symbolGenerator {
breakpad {
binary file("/PATH/TO/BREAKPAD/DUMP_SYMS")
}
}
}
}
}
方法 2:在 Gradle 属性文件中通过属性行指定路径
您可以使用 com.google.firebase.crashlytics.breakpadBinary
属性指定可执行文件的路径。
您可以手动更新 Gradle 属性文件,也可以通过命令行更新此文件。例如,如需通过命令行指定路径,请使用如下命令:
./gradlew -Pcom.google.firebase.crashlytics.symbolGenerator=breakpad \
-Pcom.google.firebase.crashlytics.breakpadBinary=/PATH/TO/BREAKPAD/DUMP_SYMS \
app:assembleRelease app:uploadCrashlyticsSymbolFileRelease
使用 DexGuard 时无法收到崩溃信息
如果您看到以下异常,可能是因为您使用的 DexGuard 版本与 Firebase Crashlytics SDK 不兼容:
java.lang.IllegalArgumentException: Transport backend 'cct' is not registered
此异常不会导致您的应用崩溃,但会阻止其发送崩溃报告。如需修复此问题,请执行以下操作:
确保您使用的是最新版 DexGuard 8.x。最新版本包含 Firebase Crashlytics SDK 所需的规则。
如果您不希望更改 DexGuard 版本,请尝试(在 DexGuard 配置文件中)向混淆规则添加以下内容:
-keepresourcexmlelements manifest/application/service/meta-data@value=cct
为什么因 .kt
文件造成的崩溃被标为 .java
问题?
如果应用使用的是不显示文件扩展名的 obfuscator(混淆器),Crashlytics 会默认以 .java
文件扩展名生成问题。
为了让 Crashlytics 生成的问题带有正确的文件扩展名,请确保您的应用使用以下设置:
- 使用 Android Gradle 4.2.0 或更高版本
- 使用 R8 且启用混淆功能。如需将应用更新到 R8,请按照此文档进行操作。
请注意,在更新到上述设置后,您可能会看到新的 .kt
问题,它们与现有的 .java
问题重复。请参阅常见问题解答,详细了解这种情况。
为什么 .kt
问题与现有的 .java
问题重复?
从 2021 年 12 月中旬开始,Crashlytics 改进了对使用 Kotlin 的应用的支持。
不久之前,可用的混淆器都不显示文件扩展名,因此 Crashlytics 默认以 .java
文件扩展名生成各个问题。不过,从 Android Gradle 4.2.0 开始,R8 支持文件扩展名。
经过此次更新,Crashlytics 现在可以确定应用中使用的每个类是否是以 Kotlin 编写的,并在问题签名中包含正确的文件名。如果您的应用采用以下设置,则崩溃现在可以正确归因于 .kt
文件(如果适用):
- 您的应用使用 Android Gradle 4.2.0 或更高版本。
- 您的应用使用 R8 且已启用混淆功能。
由于新崩溃的问题签名中现在包含正确的文件扩展名,因此您可能会看到新的 .kt
问题,而这些问题实际上与标记为 .java
的现有问题重复。在 Firebase 控制台中,我们会尝试识别新的 .kt
问题是否与标记为 .java
的现有问题重复,并通知您。
谁可以查看、撰写和删除问题的备注?
借助备注功能,项目成员可以就相关疑问或状态更新等特定问题进行备注。
项目成员发布备注时,系统会标注其 Google 账号的电子邮件地址。此电子邮件地址将与备注一起向有权访问备注的所有项目成员显示。
下文介绍了查看、撰写和删除备注所需的权限:
谁可以查看、撰写和删除问题的备注?
借助备注功能,项目成员可以就相关疑问或状态更新等特定问题进行备注。
项目成员发布备注时,系统会标注其 Google 账号的电子邮件地址。此电子邮件地址将与备注一起向有权访问备注的所有项目成员显示。
下文介绍了查看、撰写和删除备注所需的权限:
集成
应用还使用了 Google 移动广告 SDK,但无法收到崩溃信息
如果您的项目同时使用 Crashlytics 和 Google 移动广告 SDK,这可能是由于在注册异常处理程序时,崩溃报告工具进行了干扰。如需解决此问题,请调用 disableSDKCrashReporting
,在移动广告 SDK 中关闭崩溃报告。
我的 BigQuery 数据集位于何处?
无论您的 Firebase 项目位于何处,将 Crashlytics 关联到 BigQuery 后,您创建的新数据集都会自动采用美国位置。
Crashlytics 是否支持 armeabi?
Firebase Crashlytics NDK 不支持 ARMv5 (armeabi)。从 NDK r17 开始,我们不再支持此 ABI。
回归问题
什么是回归问题?
如果您之前修复并关闭了某个问题,但 Crashlytics 收到了一个该问题再次发生的新报告,则表明该问题已回归。Crashlytics 会自动重新打开这些回归问题,以便您可以根据自己的应用需求采取相应措施。
以下示例场景说明了 Crashlytics 如何将问题归类为回归问题:
- Crashlytics 首次收到有关崩溃“A”的崩溃报告。Crashlytics 会为该崩溃打开相应的问题(问题“A”)。
- 您快速修复此 bug,关闭问题“A”,然后发布应用的新版本。
- 在您关闭问题后,Crashlytics 收到关于问题“A”的另一份报告。
- 如果报告来自 Crashlytics 在您关闭问题时知道的应用版本(这意味着该版本已针对任何崩溃发送了崩溃报告),则 Crashlytics 不会将问题视为回归。此问题将保持关闭状态。
- 如果报告来自 Crashlytics 在您关闭问题时不知道的应用版本(这意味着该版本从未针对任何崩溃发送过崩溃报告),则 Crashlytics 会将该问题视为回归问题,并将其重新打开。
当某个问题回归时,我们会发送回归检测提醒,并向该问题添加回归信号,让您知道 Crashlytics 已经重新打开了问题。如果您不希望由于回归算法而要重新打开问题,请“忽略”问题,而不是将其关闭。
为什么我看到旧版应用的回归问题?
如果报告来自在您关闭问题时从未发送过任何崩溃报告的旧应用版本,则 Crashlytics 会认为问题已回归,并会重新打开问题。
在以下情况下,可能会出现这种情形:您已修复了一个 bug,并发布了应用的新版本,但仍有一些用户使用的是旧版本,而且未进行 bug 修复。如果偶然情况下,当您关闭问题时,其中一个旧版本根本没有发送过任何崩溃报告,并且这些用户开始遇到 bug,那么这些崩溃报告将触发回归问题。
如果您不希望由于回归算法而要重新打开问题,请“忽略”问题,而不是将其关闭。