升级到 Firebase Crashlytics SDK

现在,您可以使用全新官方 Firebase Crashlytics SDK 在应用中设置 Crashlytics,该 SDK 提供了与其他 Firebase 产品更为一致、更加直观易用的改进版 API。

本指南介绍了如何从旧版 Fabric SDK 升级为新 SDK。其中说明了新 API 中的更改、更改的原因,以及如何更新代码(如果需要)。

准备工作

第 1 步:添加 Firebase 配置文件

  1. 打开您的项目设置。在您的应用卡片中,选择您需要为其添加配置文件的应用的软件包 ID。

  2. 点击下载 GoogleService-Info.plist,获取 Firebase Apple 平台配置文件 (GoogleService-Info.plist)。

  3. 将配置文件移至 Xcode 项目的根目录中。如果出现提示,请选择将配置文件添加到所有目标。

如果您的项目中有多个软件包 ID,则必须将每个软件包 ID 与 Firebase 控制台中的注册应用相关联,使每个应用都有自己的 GoogleService-Info.plist 文件。

第 2 步:添加 Firebase Crashlytics SDK

  1. 在 CocoaPods 内的所有目标中,将 FabricCrashlytics Pod 替换为 Firebase/Crashlytics Pod。

    # Add the pod for Firebase Crashlytics
    pod 'Firebase/Crashlytics'
    # Recommended: Add the Firebase pod for Google Analytics pod 'Firebase/Analytics'
  2. 直接从 Fabric 中卸载或移除第三方依赖项,例如 Fabric Answers 和第三方套件的依赖项。

  3. 安装并更新 Pod,然后打开 .xcworkspace 文件以便在 Xcode 中查看项目:

    pod install
    open YOUR_PROJECT.xcworkspace

第 3 步:更新您的代码

  1. 在 Xcode 中,重建您的应用,然后再次打开 .xcworkspace 文件。

  2. 查看以下 SDK 更改,并对您的代码进行适当的更新:


Crashlytics 现在会根据 Firebase 安装 ID 轮替 ID。

Crashlytics 使用 Crashlytics 安装 UUID 来标识应用的实例,并将用户数据与其设备相关联。 以前,Crashlytics 会在设备的广告 ID 发生更改时轮替用户的安装 UUID。现在,Crashlytics 会根据用户的 Firebase 安装 ID (FID) 来轮替安装 UUID。如需了解详情,请访问管理 Firebase 安装 ID

更改的原因

使用 FID,以便与其他 Firebase SDK 保持一致。


run 脚本和 upload-symbols 脚本现位于 FirebaseCrashlytics 中。

您现在可以从新的 FirebaseCrashlytics 库访问 runupload-symbols 脚本。请注意,您仍然可以在构建流程中随时调用 upload-symbols,以便手动上传 dSYM。

此外,新 SDK 中已不再包含 Fabric 的 API_KEYBUILD_SECRET。Crashlytics 现在会使用您的应用的 GoogleService-info.plist,以将应用与您的 Firebase 项目相关联,并保留历史崩溃数据。

Fabric SDK

${PODS_ROOT}/Fabric/run API_KEY BUILD_SECRET
/path/to/pods/directory/Fabric/upload-symbols

Firebase Crashlytics SDK

${PODS_ROOT}/FirebaseCrashlytics/run
/path/to/pods/directory/FirebaseCrashlytics/upload-symbols

更改的原因

Crashlytics 已不再将 Fabric SDK 用作依赖项,因此我们将 CLI 工具移到了新的库中。


Crashlytics 库现在名为 FirebaseCrashlytics。

在应用中,更新导入路径如下:

Fabric SDK

Swift

import Crashlytics

Objective-C

@import Crashlytics

Firebase Crashlytics SDK

Swift

import FirebaseCrashlytics

Objective-C

@import FirebaseCrashlytics

更改的原因

更新 Crashlytics 库的名称,以使其与其他 Firebase 库保持一致(例如,FirebaseFirestoreFirebaseAuth)。


FirebaseCrashlytics 不再支持 Fabric SDK。

现在,FirebaseCrashlytics 只能通过 Firebase Crashlytics SDK 进行初始化。您可以通过在 Swift 中调用 FirebaseApp.configure 或在 Objective-C 中调用 [FIRApp configure] 来启动 FirebaseCrashlytics 实例。

application:didFinishLaunchingWithOptions 中,将对 Fabric.withstartWithAPIKey 的调用替换为对 FirebaseApp 的调用:

Fabric SDK

Swift

Fabric.with([Crashlytics.self])

Objective-C

[Fabric with:@[[Crashlytics class]]];
+ startWithAPIKey:
+ startWithAPIKey:delegate:

Firebase Crashlytics SDK

Swift

FirebaseApp.configure()

Objective-C

[FIRApp configure];

更改的原因

使用新方法初始化 Crashlytics 与其他 Firebase 服务的初始化方式更加一致。


crash 和 throwException 方法已移除。

新 SDK 不再包含 crashthrowException 方法,而是改为使用 fatalError(在 Swift 中)或空数组(在 Objective-C 中)强制造成崩溃。

Firebase Crashlytics SDK

Swift

// Force a test crash
fatalError()

Objective-C

// Force a test crash
@[][1];

更改的原因

多种不同的原因可能造成多种不同类型的崩溃,这些方法并未明确指出最终崩溃是在运行时还是应用的原生 SDK 中发生。


sharedInstance 方法现已更名为 crashlytics。

新 SDK 不再包含 sharedInstance 方法。 如需初始化 Crashlytics,请改为使用 crashlytics(如需了解详情,请参阅 SwiftObjective-C 参考文档)。在您的应用委托中,以如下方式更新初始化脚本:

Fabric SDK

Swift

Crashlytics.sharedInstance()

Objective-C

[Crashlytics sharedInstance];

Firebase Crashlytics SDK

Swift

Crashlytics.crashlytics()

Objective-C

[FIRCrashlytics crashlytics];

更改的原因

我们已对实例 getter 方法进行了重命名,以便与其他 Firebase SDK 保持一致。


setUserIdentifier 现已更改为 setUserID。setUserName 和 setUserEmail 已移除。

以前,您可以使用 setUserNamesetUserEmail 设置与崩溃相关联的名称或电子邮件地址,但现在已经不再定义这些方法。如需为用户设置 ID,新的首选方法是使用 setUserID

Fabric SDK

Swift

Crashlytics.sharedInstance().setUserIdentifier("user_id")

Crashlytics.sharedInstance().setUserEmail("user_email")

Crashlytics.sharedInstance().setUserName("user_name")

Objective-C

[[Crashlytics sharedInstance] setUserIdentifier:@"user_id"];

[[Crashlytics sharedInstance] setUserEmail:@"user_email"];

[[Crashlytics sharedInstance] setUserName:@"user_name"];

Firebase Crashlytics SDK

Swift

Crashlytics.crashlytics().setUserID("user_id")

Objective-C

[[FIRCrashlytics crashlytics] setUserID:@"user_id"];

更改的原因

我们采用了方法名称 setUserID 以便与其他 Firebase API 保持一致,此外由于不建议通过 Crashlytics 记录个人身份信息 (PII),我们移除了 setUserNamesetUserEmail


CLSLogv 和 CLSNSLogv 已被日志记录函数所取代。

新 SDK 不再包含 CLSLogvCLSNSLogv 函数。如需添加自定义日志消息,请使用 Crashlytics 库中的新日志记录方法。 请注意,新方法不再输出到 stdoutNSLog(如果您希望保留此行为,建议您编写封装容器)。

Fabric SDK

Swift

CLSLogv("%@, %@", getVaList([first_arg, second_arg]))

CLSNSLogv("%@, %@", getVaList([first_arg, second_arg]))

Objective-C

CLSLog(@"%@, %@", first_arg, second_arg);
CLSNSLog(@"%@, %@", first_arg, second_arg);

CLSLogv(@"%@, %@", args_va_list);
CLSNSLogv(@"%@, %@", args_va_list);

CLS_LOG(@"%@, %@", first_arg, second_arg);

Firebase Crashlytics SDK

Swift

Crashlytics.crashlytics().log("\(first_arg), \(second_arg)")

Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList([first_arg, second_arg]))

Objective-C

[[FIRCrashlytics crashlytics] log:@"first_arg, second_arg"];

[[FIRCrashlytics crashlytics] logWithFormat:@"%@, %@", first_arg, second_arg];

如果您使用了 CLS_LOG,请将以下内容添加到头文件中,以继续在日志语句中获取文件名和行号:

#define CLS_LOG(__FORMAT__, ...) [[FIRCrashlytics crashlytics] logWithFormat:@"%s line %d $ " __FORMAT__, __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__]

更改的原因

新方法需要实例,这让您可以更轻松地测试代码。


setCustomValue 将取代 setObjectValue、setIntValue、setFloatValue 和 setBoolValue。

新 SDK 中已不再包含自定义 setter 方法。 以前,您可以使用这些方法来设置键值对,以便随崩溃报告一起发送。现在,您可以使用 setCustomValue:forKey 为所有数据类型设置键值对。

Fabric SDK

Swift

Crashlytics.sharedInstance().setObjectValue("value", forKey: "object_key")

Crashlytics.sharedInstance().setIntValue(100, forKey: "int_key")

Crashlytics.sharedInstance().setFloatValue(99.9, forKey: "float_key")

Crashlytics.sharedInstance().setBoolValue(true, forKey: "bool_key")

Objective-C

[[Crashlytics sharedInstance] setObjectValue:@"key" forKey:@"object_key"];

[[Crashlytics sharedInstance] setIntValue:100 forKey:@"int_key"];

[[Crashlytics sharedInstance] setFloatValue:99.9 forKey:@"float_key"];

[[Crashlytics sharedInstance] setBoolValue:YES forKey:@"bool_key"];

Firebase Crashlytics SDK

Swift

Crashlytics.crashlytics().setCustomValue("value", forKey: "object_key")

Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")

Crashlytics.crashlytics().setCustomValue(99.9, forKey: "float_key")

Crashlytics.crashlytics().setCustomValue(true, forKey: "bool_key")

Objective-C

[[FIRCrashlytics crashlytics] setCustomValue:@"value" forKey:@"object_key"];

[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];

[[FIRCrashlytics crashlytics] setCustomValue:@(99.9) forKey:@"float_key"];

[[FIRCrashlytics crashlytics] setCustomValue:@YES forKey:@"bool_key"];

更改的原因

新方法名称是 Crashlytics 所独有的,明示了 Crashlytics 不符合键值对格式。


recordCustomExceptionName:reason:frameArray: 已被 Exception Model API 所取代。

如果您的应用在非原生环境(例如,JavaScript 或 Unity)中运行,则可以使用 Exception Model API 以应用的原生异常格式报告崩溃元数据。

Fabric SDK

Swift

let topFrame = CLSStackFrame() topFrame.symbol = "doSomethingBad" topFrame.fileName = "bad.cc" topFrame.lineNumber = 23

let middleFrame = CLSStackFrame()
middleFrame.symbol = "doOtherStuff"
middleFrame.fileName = "stuff.cc"
middleFrame.lineNumber = 23;

let bottomFrame = CLSStackFrame()
bottomFrame.symbol = "main"
bottomFrame.fileName = "main.cc"
bottomFrame.lineNumber = 123

Crashlytics.sharedInstance().recordCustomExceptionName("FooException",
                                                       reason: "There was a foo.",
                                                       frameArray: [topFrame, middleFrame, bottomFrame])

Objective-C

CLSStackFrame *topFrame = [[CLSStackFrame alloc] init];
topFrame.symbol = @"doSomethingBad";
topFrame.fileName = @"bad.cc";
topFrame.lineNumber = 23;

CLSStackFrame *middleFrame = [[CLSStackFrame alloc] init];
middleFrame.symbol = @"doOtherStuff";
middleFrame.fileName = @"stuff.cc";
middleFrame.lineNumber = 23;

CLSStackFrame *bottomFrame = [[CLSStackFrame alloc] init];
bottomFrame.symbol = @"main";
bottomFrame.fileName = @"main.cc";
bottomFrame.lineNumber = 123;

[[Crashlytics sharedInstance] recordCustomExceptionName:@"FooException"
                                                 reason:@"There was a foo."
                                             frameArray:@[topFrame, middleFrame, bottomFrame]];

Firebase Crashlytics SDK

Swift

var  ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.")
ex.stackTrace = [
  StackFrame.init(symbol:"makeError" fileName:"handler.js" lineNumber:495),
  StackFrame.init(symbol:"then" fileName:"routes.js" lineNumber:102),
  StackFrame.init(symbol:"main" fileName:"app.js" lineNumber:12),
]

crashlytics.record(exceptionModel:ex)

Objective-C

model.stackTrace = @[
  [FIRStackFrame stackFrameWithSymbol:@"makeError" fileName:@"handler.js" lineNumber:495],
  [FIRStackFrame stackFrameWithSymbol:@"then" fileName:@"routes.js" lineNumber:102],
  [FIRStackFrame stackFrameWithSymbol:@"main" fileName:@"app.js" lineNumber:12],
];

更改的原因

这是用户很久以来一直都希望我们提供的一项功能,让您可以将 Crashlytics 扩展到其他平台(如 Unity、Flutter 或 React Native)。



CrashlyticsDelegate 已被多个处理崩溃报告的方法所取代。

您现在可以使用一组新的方法来处理崩溃报告:

  • didFinishLaunchingWithOptions 现已被新的处理程序 checkForUnsentReportsWithCompletion 所取代。

  • crashlyticsDidDetectReportForLastExecution 现已被 didCrashDuringPreviousExecution 所取代。 didCrashDuringPreviousExecution 可让您方便地检测在上次运行应用期间发生的崩溃。

  • crashlyticsCanUseBackgroundSessions 现已永久设置为 true。

  • 我们不再支持在委托中检查 CLSReport 对象。

默认情况下,Crashlytics 会在启动时自动上传崩溃报告,而在先前的版本中,您可以调用 didFinishLaunchingWithOptions,让用户自选启用崩溃报告。 现在,当您调用 setCrashlyticsCollectionEnabled=false 关闭自动崩溃报告时,Crashlytics 会调用 checkForUnsentReportsWithCompletion,这样您的用户就可以选择是否在您的应用崩溃时发送崩溃报告。然后,您可以在用户选择启用时调用 sendUnsentReports,或者在用户选择退出时调用 deleteUnsentReports

请注意,您还可以在 checkForUnsentReportsWithCompletion 之外调用 sendUnsentReportsdeleteUnsentReports。例如,如果您的用户已通过一揽子批准或一揽子拒批的方式允许或禁止您发送崩溃报告,那么您可能想要永久设置或停用崩溃报告。请记住,如果您的应用在其生命周期的早期阶段崩溃,您可能永远不会收到崩溃报告。

Fabric SDK

Swift

class YourClassName: CrashlyticsDelegate {

  func application(_ application: UIApplication, didFinishLaunchingWithOptions

    ...
    Crashlytics.sharedInstance().delegate = self
    ...

    return true
  }

  func crashlyticsDidDetectReport(forLastExecution report: CLSReport, completionHandler: @escaping (Bool) -> Void) {
    /* ... handle unsent reports */
  }

  func crashlyticsCanUseBackgroundSessions(_ crashlytics: Crashlytics) -> Bool {
    return true
  }
}

Objective-C

@interface YourClassName <CrashlyticsDelegate> ()
@end

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

  ...
  [[Crashlytics sharedInstance] setDelegate:self];
  ...

  return YES;
}

-(void)crashlyticsDidDetectReportForLastExecution:(CLSReport *)report completionHandler:(void (^)(BOOL submit))completionHandler {
  // ... handle unsent reports
}

-(BOOL)crashlyticsCanUseBackgroundSessions:(Crashlytics *)crashlytics {
  return YES;
}

@end

Firebase Crashlytics SDK

Swift

/* You must set setCrashlyticsCollectionEnabled to false in order to use
checkForUnsentReportsWithCompletion. */

Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false)

Crashlytics.crashlytics().checkForUnsentReports { hasUnsentReport in
  let hasUserConsent = false
  // ...get user consent.

  if hasUserConsent && hasUnsentReport {
    Crashlytics.crashlytics().sendUnsentReports()
  } else {
    Crashlytics.crashlytics().deleteUnsentReports()
  }
}

// Detect when a crash happens during your app's last run.
if Crashlytics.crashlytics().didCrashDuringPreviousExecution() {
  // ...notify the user.
}

Objective-C

/* You must set setCrashlyticsCollectionEnabled to false in order to use
checkForUnsentReportsWithCompletion. */

[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:false];

[[FIRCrashlytics crashlytics] checkForUnsentReportsWithCompletion:^(BOOL hasUnsentReports) {
  BOOL hasConsent = false;
  // ...get consent from user.

  if (hasConsent && hasUnsentReports) {
    [[FIRCrashlytics crashlytics] sendUnsentReports];
  } else {
    [[FIRCrashlytics crashlytics] deleteUnsentReports];
  }
}];

// Detect when a crash happens during your app's last run.
if ([[FIRCrashlytics crashlytics] didCrashDuringPreviousExecution]) {
  // ...notify the user.
}

更改的原因

该组新方法让您可以更好地控制应用的崩溃报告行为。 此外,在初始化 Crashlytics 之前,您不再需要设置 CrashlyticsDelegate。


firebase_crashlytics_collection_enabled 已被 FirebaseCrashlyticsCollectionEnabled 所取代。

当您在 Info.plist 中将 FirebaseCrashlyticsCollectionEnabled 设置为 false 时,Crashlytics 会在启动时停止自动发送崩溃报告。首次运行应用后,您还可以通过在 Crashlytics.h 中将 setCrashlyticsCollectionEnabled 设置为 false 来停用崩溃报告,但请注意,setCrashlyticsCollectionEnabled 会替换此标志。

替换 Info.plist 中的 firebase_crashlytics_collection_enabled 键以关闭自动收集功能:

  • 键:FirebaseCrashlyticsCollectionEnabled

  • 值:false

首次运行应用后,您还可以将以下代码添加到 Crashlytics.h 来关闭自动收集功能:

Firebase Crashlytics SDK

Swift

// setCrashlyticsCollectionEnabled is set to true by default.
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(false)

Objective-C

// setCrashlyticsCollectionEnabled is set to true by default.
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:false];

更改的原因

现在,在停用自动崩溃报告时,您可以更好地控制 Crashlytics 如何处理尚未发送的崩溃报告。将 FirebaseCrashlyticsCollectionEnabled 设置为 false 后,您可以从应用的任何位置调用 checkForUnsentReportsWithCompletion,并根据用户的选择发送或删除尚未发送的报告。


现在,Crashlytics 始终使用后台会话。

以前,如果您不想在应用中支持后台会话,可以将 crashlyticsCanUseBackgroundSessions 设置为 false。 现在,crashlyticsCanUseBackgroundSessions 始终设置为 true。

更改的原因

我们不再支持低于 7.0 的 iOS 版本和低于 OS X 10.9 的 macOS 版本,这些版本均不支持后台会话。


Crashlytics 只能使用 Google Analytics(分析)收集的数据。

升级到 Firebase Crashlytics SDK 后,您将无法再通过 Fabric Answers 收集数据。如需获取“未受崩溃事件影响的用户数”指标和面包屑导航,请改为使用 Google Analytics(分析)。请注意,您的 Answers 历史解答数据无法迁移到 Firebase。

访问开始使用 Google Analytics(分析),以了解如何将 Google Analytics(分析)添加到您的应用中。

更改的原因

我们现在提供 Google Analytics(分析),以帮助您更深入地了解崩溃数据。借助 Analytics(分析),您可以继续在 Firebase 控制台中收集应用的统计信息。

后续步骤