Android全局异常捕获

ops/2024/11/19 22:33:36/

在开发过程中我们会使用try{}catch捕获一些异常,不过我们毕竟不能面面俱到,所以总会有一些异常在我们想不到的位置发生,然后程序就崩溃了,于是赶紧连上电脑复现bug,有的可以复现有的一时还复现不了,然后就各种手忙脚乱。

这时候我们就需要有一个全局异常捕获器,当有异常发生时,全局异常捕获器会输出异常信息,然后我们可以设置将异常信息保存到本地或者是上传服务器,方便我们快速的定位问题,不用为重新复现问题而搞的焦头烂额。

一、了解UncaughtExceptionHanlder

这里我们介绍使用UncaughtExceptionHandler来设置全局异常捕获器。首先我们来看看这个类。

源码:

@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
* <p>Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
UncaughtExceptionHandler是java.Thread类中定义的一个接口。

作用:
用来处理在程序中未被捕获的异常。(如果程序中已经自己设置了try{}catch,则不会执行这个方法)。

二、实现方法

1.定义异常捕获类
新建MyCrashHandler 实现UncaughtExptionHandler接口:

public class MyCrashHandler implements Thread.UncaughtExceptionHandler {@Overridepublic void uncaughtException(Thread t, Throwable e) {//在这里处理异常信息}
}

2.将得到的异常数据保存到本地(也可以上传服务器,这里根据需求自行解决)

/**
* 保存错误信息到文件中
* @param ex
*/
private void saveCrashInfoToFile(Throwable ex) {Writer writer = new StringWriter();PrintWriter printWriter = new PrintWriter(writer);ex.printStackTrace(printWriter);Throwable exCause = ex.getCause();while (exCause != null) {exCause.printStackTrace(printWriter);exCause =exCause.getCause();}printWriter.close();long timeMillis = System.currentTimeMillis();//错误日志文件名称String fileName = "crash-" + timeMillis + ".log";//判断sd卡可正常使用if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {//文件存储位置String path = Environment.getExternalStorageDirectory().getPath() + "/crash_logInfo/";File fl = new File(path);//创建文件夹if(!fl.exists()) {fl.mkdirs();}try {FileOutputStream fileOutputStream = new FileOutputStream(path + fileName);fileOutputStream.write(writer.toString().getBytes());fileOutputStream.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}
}

不要忘记配置读写权限:

<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 从SDCard读入数据权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

3.将该异常类设置为系统默认异常处理类,然后出现异常时,则该类会处理异常。

//设置该类为系统默认处理类
Thread.setDefaultUncaughtExceptionHandler(this);

4.在Application中使用:

MyCrashHandler mycrashHandler = new MyCrashHandler();
Thread.setDefaultUncaughtExceptionHandler(mycrashHandler);

第3步可以放到Application中,也可以在自身类里初始化好。这里只讲述思路。

到这里为止,就已经完成了全局捕获器的创建和调用,如果出现未捕获的异常,异常信息就会保存到sd卡内。这样就方便我们的查找。

当然上面的代码只是讲解思路,所以使用的时候,我们需要补充和完善,比如bug信息文件里添加手机信息,在保存到本地后将文件上传服务器等等操作,这些都可以根据需求自行完善。这里贴出我自己使用的一部分代码。

public class MyCrashHandler implements Thread.UncaughtExceptionHandler {private Thread.UncaughtExceptionHandler mDefaultHandler;private Context mcontext;private static MyCrashHandler myCrashHandler;private MyCrashHandler(){}public static synchronized MyCrashHandler newInstance() {if(myCrashHandler == null)myCrashHandler = new MyCrashHandler();return myCrashHandler;}/*** 初始化* @param context*/public void init(Context context){mcontext = context;//系统默认处理类mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();//设置该类为系统默认处理类Thread.setDefaultUncaughtExceptionHandler(this);}@Overridepublic void uncaughtException(Thread t, Throwable e) {if(!handleExample(e) && mDefaultHandler != null) { //判断异常是否已经被处理mDefaultHandler.uncaughtException(t, e);}else {try {Thread.sleep(3000);} catch (InterruptedException e1) {e1.printStackTrace();}//退出程序android.os.Process.killProcess(android.os.Process.myPid());System.exit(1);}}/*** 提示用户出现异常* 将异常信息保存* @param ex* @return*/private boolean handleExample(Throwable ex) {if(ex == null)return false;new Thread(() -> {Looper.prepare();Toast.makeText(mcontext, "很抱歉,程序出现异常,即将退出", Toast.LENGTH_SHORT).show();Looper.loop();}).start();//手机设备参数信息collectDeviceInfo(mcontext);saveCrashInfoToFile(ex);return true;}/*** 设备信息* @param mcontext*/private void collectDeviceInfo(Context mcontext) {}/*** 保存错误信息到文件中* @param ex*/private void saveCrashInfoToFile(Throwable ex) {Writer writer = new StringWriter();PrintWriter printWriter = new PrintWriter(writer);ex.printStackTrace(printWriter);Throwable exCause = ex.getCause();while (exCause != null) {exCause.printStackTrace(printWriter);exCause = exCause.getCause();}printWriter.close();long timeMillis = System.currentTimeMillis();//错误日志文件名称String fileName = "crash-" + timeMillis + ".log";//判断sd卡可正常使用if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {//文件存储位置String path = Environment.getExternalStorageDirectory().getPath() + "/crash_logInfo/";File fl = new File(path);//创建文件夹if(!fl.exists()) {fl.mkdirs();}try {FileOutputStream fileOutputStream = new FileOutputStream(path + fileName);fileOutputStream.write(writer.toString().getBytes());fileOutputStream.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}
}


链接:https://www.jianshu.com/p/bafaea706eec


http://www.ppmy.cn/ops/135082.html

相关文章

hive 统计各项目下排名前5的问题种类

实现指定某项目下的数据效果图如下所示&#xff1a; 其中 ABCDE 为前5名的问题种类&#xff0c;其中A问题有124个&#xff08;出现了124次&#xff09; 数据说明&#xff1a; 整个数据集 包含很多项目一个项目 包含很多问题一个问题 选项 可认为是 类别值&#xff0c;所有出…

RK3568硬解码并与Qt界面融合显示深入探究

1. 最近实在头疼&#xff0c;因为项目换了平台。折腾来折腾去&#xff0c;到今天算是把很多坑踩完了。 RK上实现硬解码方案一共有一下几种方式 1&#xff09;opencvgstreamer插件&#xff0c;采用硬解码&#xff0c;只能解码出图像&#xff0c;无法解出声音 2&#xff09;ff…

Windows C++ TCP/IP 两台电脑上互相传输字符串数据

在 Windows 上使用 C 实现两个进程通过 TCP/IP 协议传输字符串数据是一个非常常见的任务。我们可以利用 Windows Sockets API (winsock2) 来进行套接字编程。在下面的例子中&#xff0c;我们将演示如何通过 TCP/IP 协议传输字符串数据。这里将包括两个程序&#xff1a;一个是服…

Spring Boot教程之Spring Boot简介

Spring Boot 简介 接下来一段时间&#xff0c;我会持续发布并完成Spring Boot教程 Spring 被广泛用于创建可扩展的应用程序。对于 Web 应用程序&#xff0c;Spring 提供了 Spring MVC&#xff0c;它是 Spring 的一个广泛使用的模块&#xff0c;用于创建可扩展的 Web 应用程序。…

笔记02----重新思考轻量化视觉Transformer中的局部感知CloFormer(即插即用)

1. 基本信息 论文标题: 《Rethinking Local Perception in Lightweight Vision Transformer》中文标题: 《重新思考轻量化视觉Transformer中的局部感知》作者单位: 清华大学发表时间: 2023论文地址: https://arxiv.org/abs/2303.17803代码地址: https://github.com/qhfan/CloF…

【设计模式】入门 23 种设计模式(代码讲解)

入门 23 种设计模式&#xff08;代码讲解&#xff09; 1.创建型模式2.适配器模式3.行为型模式 设计模式是在软件设计中反复出现的问题的 通用解决方案。它们是经过多次验证和应用的指导原则&#xff0c;旨在帮助软件开发人员解决特定类型的问题&#xff0c;提高代码的可维护性、…

网络安全检测技术

一&#xff0c;网络安全漏洞 安全威胁是指所有能够对计算机网络信息系统的网络服务和网络信息的机密性&#xff0c;可用性和完整性产生阻碍&#xff0c;破坏或中断的各种因素。安全威胁可分为人为安全威胁和非人为安全威胁两大类。 1&#xff0c;网络安全漏洞威胁 漏洞分析的…

动手学深度学习70 BERT微调

1. BERT微调 2. 自然语言推理数据集 3. BERT微调代码 4. QA 9 10, 一般不固定&#xff0c;固定参数可以使训练速度加快&#xff0c;可以尝试 11 应该能 12 本身很快技术细节–>精度高 13 bert一般可以用工具转成c 开销大。考虑怎么提升bert性能。 14 设备性能不高&#xf…