崩溃截图有什么用?
- 更快复现问题:不用从日志里猜应用状态,你能直接看到导致崩溃的屏幕画面。
- 理解 UI/UX 情境:崩溃是由对话框、导航错误还是 UI 里的边缘情况触发的?截图能把这弄清楚。
- 节省调试时间:开发者常常要花数小时重现合适的条件,有了视觉快照能快很多。
- 衔接开发与 QA:测试人员和支持团队可以附上截图参考,开发者不用来回沟通就能马上明白情况。
- 捕捉用户特定的边缘情况:有时候崩溃是由特定数据、配置或用户流程导致的,这些从日志里看不出来,截图能揭示这些线索。
总之,把崩溃报告和截图结合起来,就像给警方报告加上监控录像——文字记录告诉你发生了什么,视频则确切展示了是怎么发生的。
- 如何实现呢?我们可以结合 Android 原生 API 来实现这个功能:
UncaughtExceptionHandler:应用崩溃前会调用的监听器。
PixelCopy:用于以编程方式截图的较新 API。
ActivityLifeCycleCallback:在应用类中跟踪 Activity 生命周期的监听器,能让我们对当前 Activity 保持弱引用。
- 设置
UncaughtExceptionHandler和ActivityLifecycleCallback
MyCrashHandler implements UncaughtExceptionHandler
mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();// 获取系统默认的UncaughtException处理器
Thread.setDefaultUncaughtExceptionHandler(this);// 设置该CrashHandler为程序的默认处理器
- 当UncaughtException发生时会转入该重写的方法来处理
@Override
public void uncaughtException(Thread thread, Throwable ex) {
if (!handleException(ex) && mDefaultHandler != null) {
// 如果自定义的没有处理则让系统默认的异常处理器来处理
mDefaultHandler.uncaughtException(thread, ex);
} else {
try {
// 如果处理了,让程序继续运行2秒再退出,保证文件保存并上传到服务器
Thread.sleep(2000);
} catch (InterruptedException e) {
// e.printStackTrace();
}
// 退出程序
// android.os.Process.killProcess(android.os.Process.myPid());
// System.exit(1);
mDefaultHandler.uncaughtException(thread, ex);
}
}
- 收集错误信息 发送错误报告等操作均在此完成.
public boolean handleException(Throwable ex) {
if (ex == null) {
return false;
}
new Thread() {
@Override
public void run() {
Looper.prepare();
Toast.makeText(mContext, "程序出现异常,请稍等再关闭", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}.start();
// 收集手机。平板,车载 设备参数信息 collectDeviceInfo(mContext);
// 自定义保存日志文件 saveCrashInfo2File(ex);
return true;
}