本页面提供了问题排查帮助,并解答了有关使用 Crashlytics 的常见问题。如果您找不到想要的内容或需要其他帮助,请与 Firebase 支持团队联系。
常规问题排查/常见问题解答
在“问题”表格中看到某些问题的不同格式(有时会看到“变体”)
您可能会注意到,Firebase 控制台的“问题”表格中列出的问题有两种不同的格式。您还有可能注意到,某些问题中具有一个称为“变体”的功能。原因如下:
2023 年初,我们发布了经过改进的事件分组分析引擎,还更新了设计,并推出了一些针对新问题的高级功能(例如变体)。如需了解详情,请参阅我们近期发布的博文;如需了解亮点,您可以阅读下文。
Crashlytics 会分析应用的所有事件(如崩溃、非严重错误和 ANR),并创建一种称为问题的事件组,以此将具有共同故障点的所有事件纳入一个问题。
为了将事件划分到这些问题中,经过改进的分析引擎现在会考虑事件的许多方面,包括堆栈轨迹中的帧、异常消息、错误代码以及其他平台或错误类型特征。
但在这种事件组中,导致各事件失败的堆栈轨迹可能有所不同。不同的堆栈轨迹可能代表着不同的根本原因。 为了体现一个问题内部可能存在的此类差异,我们现在会在问题内创建变体,变体是一个问题中的事件子组,该子组内的事件具有共同的故障点以及相似的堆栈轨迹。借助变体,您可以调试一个问题内最普遍的堆栈轨迹,并确定是否有不同的根本原因会导致这一故障。
改进后的体验如下:
改进了问题行中显示的元数据
现在,您可以更轻松地了解应用中的问题并进行分类。减少重复问题
更改行号不会导致新问题。更轻松地调试存在多种不同根本原因的复杂问题
使用变体调试一个问题中最普遍的堆栈轨迹。更有意义的提醒和信号
新问题表示真的出现了新的 bug。更强大的搜索功能
每个问题都包含更易于搜索的元数据,例如异常类型和软件包名称。
具体改进措施如下:
从您的应用获取新事件时,我们会检查这些事件是否与现有问题匹配。
如果没有匹配项,我们会自动为事件应用更智能的事件分组算法,并使用改进后的元数据设计创建新的问题。
这是我们对事件分组进行的第一次重大更新。如果您有任何反馈或遇到任何问题,请通过
没有看到“未遇到崩溃问题”指标和/或“疾速崩溃提醒”
如果您没有看到“未遇到崩溃问题”指标(例如未遇到崩溃问题的用户数和未发生崩溃问题的活跃日)和/或疾速崩溃提醒,请确保您使用的是 Crashlytics SDK v18.6.0+(或 Firebase BoM v32.6.0+)。
没有看到面包屑导航日志
如果您没有看到路径日志,我们建议您检查应用的 Google Analytics 配置。请确保您符合以下要求:
您已在 Firebase 项目中启用 Google Analytics。
您已为 Google Analytics 启用数据共享。如需详细了解此设置,请参阅管理您的 Google Analytics 数据共享设置
您已向应用 添加了 Firebase SDK for Google Analytics 。除了 Crashlytics SDK 之外,您还必须添加此 SDK。
您对应用中所用的所有产品都使用的是 最新的 Firebase SDK 版本 。
特别要确认您使用的 Firebase SDK for Google Analytics 是否至少为以下版本:
Android — v17.2.3+ (BoM v24.7.1+) 。
为什么仅对 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 插件 v2.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 控制台中生成不一致的堆栈轨迹。如需缓解此问题,请在构建流程中添加以下链接器标志:
如果您使用的是 LLVM 工具链中的
lld
链接器,请添加:-Wl,--no-rosegment
如果您使用的是 GNU 工具链中的
ld.gold
链接器,请添加:-Wl,--rosegment
如果堆栈轨迹仍不一致(或者两个标志都不适用于您的工具链),请试试将以下内容添加到构建流程:
-fno-omit-frame-pointer
如何将我自己的 Breakpad 符号文件生成器二进制程序用于 NDK?
Crashlytics 插件捆绑了一个定制的 Breakpad 符号文件生成器。如果您希望使用自己的二进制程序来生成 Breakpad 符号文件(例如,如果您希望在自己的 build 链中从源代码构建所有原生可执行文件),请使用可选的 symbolGeneratorBinary
扩展属性来指定可执行文件的路径。
您可以通过以下方法指定 Breakpad 符号文件生成器二进制程序的路径:
方法 1:在
build.gradle
文件中通过firebaseCrashlytics
扩展指定路径将以下内容添加到您的应用级
build.gradle.kts
文件: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 Mobile Ads SDK,但无法收到崩溃信息
如果您的项目同时使用 Crashlytics 和 Google Mobile Ads SDK,这可能是由于在注册异常处理程序时,崩溃报告工具进行了干扰。如需解决此问题,请调用 disableSDKCrashReporting
,在 Mobile Ads 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,那么这些崩溃报告将触发回归问题。
如果您不希望由于回归算法而要重新打开问题,请“忽略”问题,而不是将其关闭。