Appearance
崩溃统计
字数统计:约 8000 字
难度等级:⭐⭐⭐
面试重要度:⭐⭐⭐⭐
目录
1. 崩溃统计简介
1.1 为什么需要崩溃统计
崩溃统计帮助:
- 发现生产环境问题
- 优先修复影响大的崩溃
- 追踪修复效果
- 了解崩溃趋势1.2 常见指标
- 崩溃率 (Crash-free users)
- 崩溃次数
- 受影响用户数
- 崩溃设备分布
- 崩溃版本分布2. Firebase Crashlytics
2.1 集成
gradle
// 项目级 build.gradle.kts
buildscript {
dependencies {
classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9")
}
}
// 模块级 build.gradle.kts
plugins {
id("com.google.firebase.crashlytics")
}
dependencies {
implementation("com.google.firebase:firebase-crashlytics-ktx:18.4.3")
implementation("com.google.firebase:firebase-analytics-ktx:21.4.0")
}2.2 配置
kotlin
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
// 配置 Crashlytics
FirebaseCrashlytics.getInstance().setCrashlyticsCollectionEnabled(true)
// 设置用户 ID
FirebaseCrashlytics.getInstance().setUserId(getUserId())
// 记录自定义键
FirebaseCrashlytics.getInstance().setCustomKey("app_version", getVersionName())
}
}2.3 记录日志
kotlin
class CrashReporting {
fun log(message: String) {
FirebaseCrashlytics.getInstance().log(message)
}
fun recordException(throwable: Throwable) {
FirebaseCrashlytics.getInstance().recordException(throwable)
}
fun setUserId(userId: String) {
FirebaseCrashlytics.getInstance().setUserId(userId)
}
fun setCustomKey(key: String, value: String) {
FirebaseCrashlytics.getInstance().setCustomKey(key, value)
}
}
// 使用
try {
// 代码
} catch (e: Exception) {
CrashReporting.recordException(e)
throw e
}2.4 测试崩溃
kotlin
// 测试 Crashlytics
FirebaseCrashlytics.getInstance().crash()
// 或
throw RuntimeException("Test Crash")3. Bugly
3.1 集成
gradle
dependencies {
implementation("com.tencent.bugly:crashreport:4.1.9")
implementation("com.tencent.bugly:nativecrashreport:3.9.2")
}3.2 初始化
kotlin
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Bugly.init(
applicationContext,
"your-app-id",
BuildConfig.DEBUG
)
// 设置用户 ID
Bugly.setUserId(applicationContext, getUserId())
// 设置版本
Bugly.setAppVersion(applicationContext, getVersionName())
}
}3.3 上报
kotlin
// 上报 Java 异常
Bugly.postCatchedException(exception)
// 上报自定义错误
Bugly.reportException(exception)
// 设置用户属性
Bugly.putUserData(context, "user_id", userId)
Bugly.putUserData(context, "channel", channel)4. 自定义崩溃收集
4.1 全局异常处理
kotlin
class CrashHandler private constructor() : Thread.UncaughtExceptionHandler {
companion object {
val instance = CrashHandler()
}
private var defaultHandler: Thread.UncaughtExceptionHandler? = null
fun init(context: Context) {
defaultHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler(this)
}
override fun uncaughtException(thread: Thread, throwable: Throwable) {
// 保存崩溃信息
saveCrashInfo(thread, throwable)
// 上传到服务器
uploadCrashInfo()
// 调用默认处理
defaultHandler?.uncaughtException(thread, throwable)
}
private fun saveCrashInfo(thread: Thread, throwable: Throwable) {
val sb = StringBuilder()
sb.append("Time: ${System.currentTimeMillis()}\n")
sb.append("Thread: ${thread.name}\n")
sb.append("Device: ${Build.MODEL}\n")
sb.append("OS: ${Build.VERSION.RELEASE}\n")
sb.append("App Version: ${getVersionName()}\n")
sb.append("\nStack Trace:\n")
sb.append(Log.getStackTraceString(throwable))
// 保存到文件
val file = File(context.cacheDir, "crash_${System.currentTimeMillis()}.log")
file.writeText(sb.toString())
}
private fun uploadCrashInfo() {
// 上传到服务器
}
}
// 初始化
CrashHandler.instance.init(context)4.2 ANR 监控
kotlin
class AnrMonitor {
fun start() {
Thread {
while (true) {
Thread.sleep(5000)
// 检查主线程是否阻塞
val mainLooper = Looper.getMainLooper()
val stackTraces = Looper.getMainLooper().thread.stackTrace
if (stackTraces.size > 10) {
// 可能 ANR
reportAnr(stackTraces)
}
}
}.start()
}
private fun reportAnr(stackTraces: Array<StackTraceElement>) {
// 上报 ANR 信息
}
}5. 崩溃分析
5.1 崩溃分类
崩溃类型:
- NullPointerException
- IndexOutOfBoundsException
- ClassCastException
- OutOfMemoryError
- NetworkOnMainThreadException
- ANR (Application Not Responding)5.2 优先级排序
优先级:
P0 - 影响 > 10% 用户的崩溃
P1 - 影响 1-10% 用户的崩溃
P2 - 影响 < 1% 用户的崩溃
P3 - 偶发崩溃5.3 修复流程
1. 查看崩溃报告
2. 分析堆栈信息
3. 复现问题
4. 定位原因
5. 修复代码
6. 测试验证
7. 发布更新
8. 追踪效果6. 面试考点
6.1 基础概念
Q1: 常用的崩溃统计工具?
答案要点:
- Firebase Crashlytics (Google)
- Bugly (腾讯)
- Sentry
- 自建崩溃收集Q2: 如何收集崩溃信息?
kotlin
// 实现 UncaughtExceptionHandler
class CrashHandler : Thread.UncaughtExceptionHandler {
override fun uncaughtException(t: Thread, e: Throwable) {
// 保存崩溃信息
// 上传到服务器
}
}6.2 实战问题
Q3: 如何集成 Crashlytics?
gradle
// 1. 添加插件
classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9")
// 2. 应用插件
id("com.google.firebase.crashlytics")
// 3. 添加依赖
implementation("com.google.firebase:firebase-crashlytics-ktx:18.4.3")Q4: 如何分析崩溃?
答案要点:
1. 查看崩溃率
2. 分析堆栈信息
3. 确定影响范围
4. 复现问题
5. 定位原因
6. 修复验证参考资料
本文完,感谢阅读!