Android CrashHandler全局异常

news2024/11/26 10:41:22

CrashHandler 介绍

Android 应用不可避免的会发生crash 即崩溃,无论程序写的多好,都会不可避免的发生崩溃,可能是由底层引起的,也有可能是写的代码引起的。当crash发生时,系统会kill掉正在执行的程序,现象是程序闪退或提升用户已停止运行。出现这种情况,开发者却无法得到程序为何crash。Android 提供了处理这类问题的方法。
java的Thread中有一个UncaughtExceptionHandler接口,该接口的作用主要是为 了 当 Thread 因未捕获的异常而突然终止时,调用处理程序。


    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        // Android-removed: SecurityManager stubbed out on Android.
        /*
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            sm.checkPermission(
                new RuntimePermission("setDefaultUncaughtExceptionHandler")
                    );
        }
        */

         defaultUncaughtExceptionHandler = eh;
     }

    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);
    }

使用


public class CrashHandler implements Thread.UncaughtExceptionHandler {

    public static final String TAG = "CrashHandler";

    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/Crash/log";
    private static final String FILE_NAME = "crash";
    private static final String FILE_NAME_SUFFIX = ".trace";

    private static CrashHandler mInstance;
    private Context mContext;
    private Thread.UncaughtExceptionHandler mDefaultCrashHandler;

    public CrashHandler() {

    }

    public static synchronized CrashHandler getInstance() {
        if (mInstance == null) {
            synchronized (CrashHandler.class) {
                if (mInstance == null) {
                    mInstance = new CrashHandler();
                }
            }
        }
        return mInstance;
    }

    public void init(Context context) {
        mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        mContext = context.getApplicationContext();
    }


    /**
     * 当程序中有未被捕获的异常,系统将会自动调用uncaughtException方法
     *
     * @param thread 为出现未捕获异常的线程
     * @param ex     为未捕获的异常
     */
    @Override
    public void uncaughtException(@NonNull Thread thread, @NonNull Throwable ex) {
        try {
            //导出异常信息到SDCard中
            dumpExceptionToSDCard(ex);
            uploadExceptionToServer();
        } catch (IOException e) {
            e.printStackTrace();
        }

        ex.printStackTrace();
        //如果系统提供了默认异常处理器,则交给系统去结束程序,否则就由自己结束自己
        if (mDefaultCrashHandler != null) {
            mDefaultCrashHandler.uncaughtException(thread, ex);
        } else {
            Process.killProcess(Process.myPid());
        }
    }


    private void dumpExceptionToSDCard(Throwable ex) throws IOException {
        //判断SD是否存在
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            //判断是否是Debug
            Log.w(TAG, "sdcard unmounted dump exception");
            return;
        }
        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        long currentTimeMillis = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(currentTimeMillis);

        File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);
        Log.i(TAG, "fileName:" + file.getName() + " , path:" + file.getPath());


        try {
            PrintWriter printWriter = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            printWriter.println(time);
            dumpPhoneInfo(printWriter);
            printWriter.println();
            ex.printStackTrace(printWriter);
            printWriter.close();
        } catch (Exception e) {
            Log.e(TAG, "dump crash info failed");
            e.printStackTrace();
        }
    }

    private void dumpPhoneInfo(PrintWriter printWriter) throws PackageManager.NameNotFoundException {

        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
        printWriter.print("App Version: ");
        printWriter.print(pi.versionName);
        printWriter.print("_");
        printWriter.println(pi.versionCode);

        //Android 版本号
        printWriter.print("OS Version: ");
        printWriter.print(Build.VERSION.RELEASE);
        printWriter.print("_");
        printWriter.println(Build.VERSION.SDK_INT);

        //手机制造商
        printWriter.print("Vendor: ");
        printWriter.println(Build.MANUFACTURER);

        //手机型号
        printWriter.print("Model: ");
        printWriter.println(Build.MODEL);

        //CPU架构
        printWriter.print("CPU ABI: ");
        printWriter.println(Build.CPU_ABI);
    }

    private void uploadExceptionToServer() {
        // TODO upload Exception Message To Your Server
    }
}

在Applicaption 类中初始化

public class TestApplication extends Application {
 @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        CrashHandler instance = CrashHandler.getInstance();
        instance.init(this);
    }
}

自己手动抛出一个异常

        addDisposable(RxView.clicks(mainBinding.settingIv)
                .throttleFirst(PDAConstant.CLICK, TimeUnit.SECONDS).subscribe(o -> {
                    throw new RuntimeException(" 自定义 exception");
                }));

在这里插入图片描述

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/718609.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CMake静态库动态库的构建和链接

cmake的基础知识&#xff1a;CMakeLists常用命令&#xff0c;在这里不再赘述。 Windows平台下可用cmake-gui生成vs的.sln工程&#xff0c;Linux平台下可以运行cmake命令。 动态库和静态库的构建 现有C工程目录结构如下&#xff1a; 静态库的构建 add.h #include <iost…

【kingbase数据库】kingbase查看所有表名

进入kingbase数据库&#xff0c;在数据库活动页面中选择要查询的数据库。 在SQL命令行工具中输入以下命令&#xff1a; SELECT relname FROM sys_class WHERE relkind r AND relnamespace (SELECT oid FROM sys_namespace WHERE nspname public);执行命令后&#xff0c;…

deeplabv3+源码之慢慢解析main.py(1)--get_argparser函数

deeplab v3源码 慢慢解析系列 本带着一些孩子们做&#xff0c;但本硕能独立看下来的学生不多。和孩子们一起再学一遍吧。希望孩子们和我自己都能坚持写下去吧。网上资料太多了&#xff0c;但不够慢&#xff0c;都是速成&#xff0c;没有足够的解释和补充&#xff0c;希望这次够…

EC200u-cn-4G模块连接OneNet上传GPS定位数据(MQTT协议)

一、前言 这篇文章介绍EC200U-CN 4G模块通过MQTT协议上传GPS数据到OneNet平台,完成地图数据显示的过程。 当前的主控芯片采用MC9S12XS128MAA,通过串口连接EC200U-CN实现联网功能,通过内置的MQTT协议指令,将采集的GPS数据上传到OneNet平台,联合百度地图实现位置显示。 下…

C#(四十七)之关于流的异常

一&#xff1a;Try-catch-finally 声明文件对象要在 Try-catch-finally 结构体外边声明 声明在try中的对象有作用域问题&#xff0c;其并不能影响finally中的程序 在catch中显示程序错误代码。 在finally中释放程序&#xff0c;关闭文件流。 二&#xff1a;using语句 1&a…

启动失败之JDK版本配置不一致

一、java: 警告: 源发行版 17 需要目标发行版 17 1.1.原因 :JDK 版本不对。 这里可以看到&#xff0c;项目需要的是JDK17&#xff0c;而我这里用的是JDK1.8。 1.2.修改 这里有两种操作&#xff0c;一种是修改项目版本&#xff0c;一种是修改JDK版本。无论是哪一种&#xff0…

NSS [SWPUCTF 2022 新生赛]xff

NSS [SWPUCTF 2022 新生赛]xff postman一把梭。

Mysql高级教程第二章

SQL Alias&#xff08;别名&#xff09; 通过使用 SQL&#xff0c;可以为列名称和表名称指定别名&#xff08;Alias&#xff09;。 SQL Alias 表的 SQL Alias 语法 SELECT column_name(s) FROM table_name AS alias_name 列的 SQL Alias 语法 SELECT column_name AS alia…

UG NX二次开发(C#)-建模-根据特征获取体(或者关联体)

文章目录 1、前言2、创建块特征与UIStyler2.1 创建两个长方体2.2 创建一个UIStyler3、添加获取体的代码1、前言 UG NX的建模是基于特征建模的,比如块、圆柱体、合并操作等等都是特征,都有特征对象,对于具有体的特征,其可以通过NXOpen二次开发技术实现二者的转换,也可以通…

error: exportArchive: No signing certificate \“Mac Development\“ found

error: exportArchive: No signing certificate “Mac Development” found UNIAPP打包又遇到这个问题了, 证书过期续期的时候又遇到这个问题了(之前遇到过解决了,时间长忘了),记录一下,报错信息 error: exportArchive: No signing certificate \"Mac Development\"…

url, uri, urn的区别

URI URI是统一资源标识符&#xff08;Uniform Resource Identifier&#xff09;的缩写。它用于标识网络上的逻辑或物理资源。URL和URN是URI的子类型。URL用于定位资源&#xff0c;而URN用于命名资源。 一个URI由以下部分组成 scheme:[//authority]path[?query][#fragment] …

UDP客户端和服务器

UDP客户端&#xff0c;也就是首先主动发送数据的一方&#xff0c;也就是发起服务请求的一方。 UDP服务器&#xff0c;也就是首先等待接收数据&#xff0c;并对接收的数据进行处理&#xff0c;返回计算结果的一方&#xff0c;也就是提供服务的一方。 涉及的函数 ssize_t recvfr…

实现Linux 视频聊天、远程桌面(源码,支持信创环境,可与Windows版、安卓版互通)

有朋友在下载并了解了《C# 实现 Linux 视频会议&#xff08;源码&#xff0c;支持信创环境&#xff0c;银河麒麟&#xff0c;统信UOS&#xff09;》中提供的源码后&#xff0c;留言给我说&#xff0c;这个视频会议有点复杂了&#xff0c;代码比较多&#xff0c;看得有些费劲。问…

嵌入式系统标志的策略和技巧

当在嵌入式系统中使用标志时&#xff0c;可以考虑以下优化措施&#xff1a; 图像压缩&#xff1a;由于嵌入式系统通常具有有限的存储空间&#xff0c;可以使用图像压缩算法来减小标志的文件大小。常见的压缩算法包括JPEG、PNG等&#xff0c;可以根据系统的要求选择合适的压缩算…

Gradle多模块项目搭建完整教程,模块互相依赖,基于springboot开发

1.父项目创建&#xff0c;【com.fdw.hibernate】 2.子项目创建&#xff0c;【com.fdw.study】【com.fdw.parent】 3.最终结构目录 4. 父工程build.gradle plugins {id java }allprojects {// 指定需要的插件// 指定语言apply plugin: java//指定编辑器apply plugin: idea// 配…

漏洞复现Tomcat系列弱口令、CVE-2017-12615、CVE-2020-1938

文章目录 提提神tomcat8 弱口令介绍&#xff1a;复现&#xff1a; Tomcat PUT方法任意写文件漏洞&#xff08;CVE-2017-12615&#xff09;介绍&#xff1a;复现&#xff1a; Tomcat AJP 文件包含漏洞&#xff08;CVE-2020-1938&#xff09;介绍&#xff1a;复现&#xff1a; 提…

c#/c++ 通过系统api监视文件变化的问题

再分享个比较经典的案例&#xff0c;在很多场景下&#xff0c;我们都要去监视某个文件夹下的文件变化&#xff0c;在创建、修改或删除的时候触发一些行为。众所周知&#xff0c;c#有个实现类叫FileSystemWatcher&#xff0c;可以用来监视目录包括子目录下文件的变化&#xff0c…

亚马逊云科技,定义了生成式AI的生产力

众所周知&#xff0c;要把大模型转化为生产力&#xff0c;AI模型、算力和数据会是难以逾越的门槛。新的目标已经出现&#xff0c;我们是否有了足够强大的AI基础设施&#xff1f;在6月28日上海举行的峰会上&#xff0c;亚马逊云科技展示了这样的能力。 从掀起AI画图热潮的Stabil…

【深度学习笔记】深层神经网络

本专栏是网易云课堂人工智能课程《神经网络与深度学习》的学习笔记&#xff0c;视频由网易云课堂与 deeplearning.ai 联合出品&#xff0c;主讲人是吴恩达 Andrew Ng 教授。感兴趣的网友可以观看网易云课堂的视频进行深入学习&#xff0c;视频的链接如下&#xff1a; 神经网络和…

select 框添加树结构(todu)

1. 案例: 2. 代码 下班了&#xff0c;明天写