用户反馈:扫描到客户端后点击「开始推流」立刻闪退。
根因:PoseDetector.initialize() 只 catch (Exception),而 MediaPipe 初始化
失败会抛 UnsatisfiedLinkError / NoClassDefFoundError / ExceptionInInitializerError
—— 这些都是 Error,不是 Exception,会直接冒泡成进程崩溃。
证据(对照实验):新增 Robolectric 组合测试后
改回 catch (Exception):5 项测试 2 项失败
- java.lang.UnsatisfiedLinkError: no mediapipe_tasks_jni in java.library.path
- java.lang.NoClassDefFoundError: Could not initialize class ...PoseLandmarker
改为 catch (Throwable):5 项全部通过
修复与加固:
- PoseDetector / CameraController 全部改为捕获 Throwable,失败只提示不崩溃
- 移除 accompanist-permissions 0.34.0(2024-02 发布,会传递引入
compose animation-core 1.6.0,与 Compose BOM 存在版本偏斜风险),
改用平台 Activity Result API
- MediaPipe 回调在相机线程:所有 Compose 状态写入统一 post 回主线程
- WebSocket 连接、相机启动、单帧分析全部包上失败保护
- 新增 CrashLogger:未捕获异常落盘到 filesDir/crashes/,
并在连接页直接展示堆栈(免去连 adb 抓 logcat)
- 新增 ScreenCompositionTest(Robolectric):真实组合三个页面,
覆盖「进入页面即崩溃」这一类缺陷,共 30 项单元测试
26 lines
686 B
Kotlin
26 lines
686 B
Kotlin
package com.opendance.studio
|
|
|
|
import android.app.Application
|
|
import com.opendance.studio.util.CrashLogger
|
|
|
|
/**
|
|
* 应用级单例容器(T-AND-001 骨架)。
|
|
*
|
|
* 只持有跨页面共享、生命周期长于 Activity 的对象;相机与推理器由运行页持有,
|
|
* 离开运行页即释放,避免相机被后台占用。
|
|
*/
|
|
class OpenDanceApp : Application() {
|
|
|
|
override fun onCreate() {
|
|
super.onCreate()
|
|
instance = this
|
|
// 最先安装崩溃记录,保证后续任何初始化失败都能落盘堆栈
|
|
CrashLogger.install(this)
|
|
}
|
|
|
|
companion object {
|
|
lateinit var instance: OpenDanceApp
|
|
private set
|
|
}
|
|
}
|