当前位置: 首页 > news >正文

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生,系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler它是Thread的子类(就是package java.lang;线程的Thread)。本文将利用它将设备信息、报错信息以及错误的发生时间都记录到文件存到本地用来分析问题。当然也可以在客户授权同意的情况下将这些错误信息或者缓存的文件发送到服务端进行分析。

本文只实现获取错误信息并存文件,如需上传请自己增加网络请求。

核心代码就是自己实现Thread.UncaughtExceptionHandler并重写uncaughtException方法,然后调用Thread的静态方法setDefaultUncaughtExceptionHandler将自己实现类对象设置进去,等程序发生crash闪退的时候系统会调用uncaughtException方法并传递错误信息。

第一步实现Thread.UncaughtExceptionHandler并完成信息保存

public class CrashHandler implements Thread.UncaughtExceptionHandler {private static final String CRASH_DIR = "crash";private static final String FILE_NAME = "crash_log.txt";private static final SimpleDateFormat DATE_FORMAT =new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());private static final String TAG = "CrashHandler";private Context mContext;private Thread.UncaughtExceptionHandler mDefaultHandler;public static void init(Context context) {int i1 = ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE);int i2 = ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE);if (i1 == PackageManager.PERMISSION_GRANTED && i2 == PackageManager.PERMISSION_GRANTED) {//已有权限CrashHandler handler = new CrashHandler(context);Thread.setDefaultUncaughtExceptionHandler(handler);} else {Log.e(TAG, "onClick: 无权限需申请");if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
//                context.requestPermissions(permissions, 1000);}else {// 低版本设备}}}private CrashHandler(Context context) {mContext = context.getApplicationContext();mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();}@Overridepublic void uncaughtException(Thread thread, Throwable ex) {Log.e(TAG, "uncaughtException:  抛异常");saveCrashInfo(ex);mDefaultHandler.uncaughtException(thread, ex);}private void saveCrashInfo(Throwable ex) {String time = DATE_FORMAT.format(new Date());String deviceInfo = getDeviceInfo();String crashInfo = getCrashInfo(ex);File externalDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS+"/"+CRASH_DIR);
//        File dir = new File(Environment.getExternalStorageDirectory(), CRASH_DIR);if (!externalDir.exists()) {externalDir.mkdirs();}
//        File dir = new File(Environment.getExternalStorageDirectory(), CRASH_DIR);
//        if (!dir.exists()) {
//            dir.mkdirs();
//        }File file = new File(externalDir, FILE_NAME);try (PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file, true)))) {pw.println("========== Crash Log ==========");pw.println("Time: " + time);pw.println(deviceInfo);pw.println(crashInfo);pw.println();pw.println(); // 空行分隔每次崩溃记录} catch (IOException e) {e.printStackTrace();}}private String getDeviceInfo() {return "Model: " + Build.MODEL + "\n" +"Brand: " + Build.BRAND + "\n" +"Android SDK: " + Build.VERSION.SDK_INT + "\n" +"Version: " + Build.VERSION.RELEASE;}private String getCrashInfo(Throwable ex) {StringBuilder sb = new StringBuilder();sb.append("Exception: ").append(ex.getClass().getName()).append("\n");sb.append("Message: ").append(ex.getMessage()).append("\n");StackTraceElement[] stackTrace = ex.getStackTrace();for (StackTraceElement element : stackTrace) {sb.append("\tat ").append(element.toString()).append("\n");}return sb.toString();}
注意想创建文件夹要使用路径不能再是Environment.getExternalStorageDirectory()。否则可能无法成功指定到文件。

第二、实现类调用最好在Application的onCreate中实现,因为是全局的越早开始检测越好。

@Override
public void onCreate() {super.onCreate();context = this;Log.e(TAG, "onCreate: ");CrashHandler.init(this);
}
  • 第三、主动创建一个异常

  • Log.e(TAG, "error: "+ 1/0 );

    第四、实现效果:

http://www.xdnf.cn/news/930979.html

相关文章:

  • 【hive】函数集锦:窗口函数、列转行、日期函数
  • stm32-c8t6实现语音识别(LD3320)
  • 【Mac 从 0 到 1 保姆级配置教程 16】- Docker 快速安装配置、常用命令以及实际项目演示
  • 【SpringBoot+SpringCloud】Linux配置nacos踩坑大全
  • AI时代:学习永不嫌晚,语言多元共存
  • 思澈sdk-新建lcd
  • LeetCode--25.k个一组翻转链表
  • 从0开始学习R语言--Day20-ARIMA与格兰杰因果检验
  • 【第八篇】 SpringBoot高级配置(配置篇)
  • CZGL.SystemInfo:跨平台的系统信息获取库
  • AUTOSAR实战教程--DoIP_01_配置项解释
  • 0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
  • Linux下GCC和C++实现统计Clickhouse数据仓库指定表中各字段的空值、空字符串或零值比例
  • Go基本语法——go语言中的四种变量定义方法
  • 【Java学习笔记】BigInteger 和 BigDecimal 类
  • 【Go语言基础【19】】接口:灵活实现多态的核心机制
  • 基于RT-DETR算法的夜间交通车辆与行人目标检测
  • FPGA静态功耗
  • 2025年与2030年AI及AI智能体 (Agent) 市场份额分析报告
  • 网络之交换机
  • 【题解-洛谷】B3626 跳跃机器人
  • JavaWeb——登录(14/16):登录校验-Interceptor-详解(使用细节、拦截路径的配置、匹配规则、执行流程、拦截器与过滤器的区别)
  • 【华为云Astro 轻应用】组装“待处理工单”页面示例
  • C语言基础面试问答
  • 【人工智能 | 项目开发】Python Flask实现本地AI大模型可视化界面
  • 苍穹外卖-day01
  • 用 DeepSeek 高效完成数据分析与挖掘
  • Bootstrap Table开源的企业级数据表格集成
  • 大数据学习(133)-Hive数据分析2
  • 论文笔记:Large Language Models for Next Point-of-Interest Recommendation