Android使用CrashHandler编写异常捕获类,分析程序崩溃原因 墨蓝 2023-10-18 15:21 140阅读 0赞 ### 概述 ### 无论你的程序写的多么完美,都不可能避免会发生crash。可能是由于系统底层的bug,也可能是由于不充分的机型适配......等。当发生更crash时,系统会kill掉正在执行的程序,从而立马闪退。更糟糕的是,当用户发生crash时,开发者却无法得知程序为何crash,更不立即得到用户的crash信息,所以往往造成修复不及时。 目前有两种处理方案,一种是利用第三方的sdk进行崩溃日志收集(友盟、腾讯的bugly),另一种则是如下实现UncaughtExceptionHandler。 ### 实现流程 ### 这里我创建CrashLogManager类去实现UncaughtExceptionHandler接口,在uncaughtException方法进行异常信息处理,获取的crash信息,写入到手机的本地文件,然后上传到自己公司服务器。切记得在Application中进行初始化,确保程序已经获得了读写权限。 完整CrashLogManager代码如下: public class CrashLogManager implements Thread.UncaughtExceptionHandler { public static final String TAG = "CrashHandler"; public static final boolean DEBUG=true; //日志保存路径 public static final String PATH=Environment.getExternalStorageDirectory().getPath()+"/TestApp/CrashLog/"; public static final String FILE_NAME="carsh_"; public static final String FILE_NAME_SUFFIX=".txt"; //系统默认的UncaughtException处理类 private Thread.UncaughtExceptionHandler mDefaultHandler; //CrashLogManager实例 private static CrashLogManager INSTANCE = new CrashLogManager(); //程序的Context对象 private Context mContext; /** 保证只有一个CrashLogManager实例 */ private CrashLogManager() { } /** 获取CrashLogManager实例 ,单例模式 */ public static CrashLogManager getInstance() { return INSTANCE; } /** * 初始化 * @param context */ public void init(Context context) { mContext = context; //获取系统默认的UncaughtException处理器 mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler(); //设置该CrashLogManager为程序的默认处理器 Thread.setDefaultUncaughtExceptionHandler(this); } /** * 最关键函数,当程序有未捕获的异常时,系统自动调用次方法 * @param thread 未捕获异常线程 * @param ex 未捕获异常信息 */ @Override public void uncaughtException(Thread thread, Throwable ex) { try { //异常信息写入sd卡 dumpExceptionToSD(ex); //异常信息上传服务器 uploadExcptionToServer(); } catch (IOException e) { e.printStackTrace(); } if (mDefaultHandler != null) { //如果用户没有处理则让系统默认的异常处理器来处理 mDefaultHandler.uncaughtException(thread, ex); } else { android.os.Process.killProcess(android.os.Process.myPid()); System.exit(1); } } /** * 异常信息写入sd卡 * @param ex */ private void dumpExceptionToSD(Throwable ex) throws IOException{ //无sd卡或无法使用 if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){ if(DEBUG){ Log.w(TAG,"No SD card"); } } else { File dir=new File(PATH); if(!dir.exists()){ dir.mkdirs(); } long currentData=System.currentTimeMillis(); String time=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(currentData)); File file =new File(PATH + FILE_NAME + time.replace(" ", "_") + FILE_NAME_SUFFIX ); Log.e(TAG,"crash file path:"+file.getAbsolutePath()); try { PrintWriter printWriter=new PrintWriter(new BufferedWriter(new FileWriter(file))); printWriter.println(time);//写入时间 phoneInformation(printWriter);//写入手机信息 printWriter.println(); ex.printStackTrace(printWriter);//异常信息 printWriter.close(); } catch (IOException e) { e.printStackTrace(); Log.e(TAG,"writer crash log failed"); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } } /** * phone info */ private void phoneInformation(PrintWriter pw) throws PackageManager.NameNotFoundException { PackageManager pm=mContext.getPackageManager(); PackageInfo pi= pm.getPackageInfo(mContext.getPackageName(),PackageManager.GET_ACTIVITIES); pw.println("App Version: "+pi.versionName+"_versionCode:"+pi.versionCode); pw.println("OS Version: "+ Build.VERSION.RELEASE+"_SDK:"+Build.VERSION.SDK_INT); pw.println("Vendor: "+Build.MANUFACTURER); pw.println("Model: "+Build.MODEL); pw.println("CPU ABI: "+Build.CPU_ABI); } /** * 异常信息上传服务器 */ private void uploadExcptionToServer() { //上传you web server } } 在Application进行初始化 CrashLogManager crashLog = CrashLogManager.getInstance(); crashLog.init(getApplicationContext()); 模拟产生crash,伪代码。这里产生空指针 xDialog=null; xDialog.onShowN(true,false); crashLog文件: ![20190308161515685.png][] 分析文件得出崩溃原因为空指针: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbjg1Nw_size_16_color_FFFFFF_t_70][] ### 结尾 ### 异常信息上传的具体逻辑请根据自己网络框架进行实现,这里就不多说了。本文如果对你有帮助请点个赞鼓励一下吧。 [20190308161515685.png]: https://img-blog.csdnimg.cn/20190308161515685.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbjg1Nw_size_16_color_FFFFFF_t_70]: https://img-blog.csdnimg.cn/20190308161551818.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xpbjg1Nw==,size_16,color_FFFFFF,t_70
相关 异常处理不完善:未捕获的异常导致程序崩溃 确实,异常处理是编程中不可或缺的一部分。如果异常处理不完善,可能会出现以下问题: 1. 程序崩溃:当未捕获的异常被抛出时,如果没有相应的代码去处理这个异常,程序就会因无法正常 妖狐艹你老母/ 2024年10月15日 15:54/ 0 赞/ 49 阅读
相关 异常处理失效:未捕获的异常导致程序崩溃 是的,你描述的情况非常常见。在编程中,如果一个异常没有被恰当地捕获并进行处理,它通常会终止当前的函数或者方法执行。 这可能导致程序运行不完整,甚至出现系统崩溃的情况。因此,在 Love The Way You Lie/ 2024年09月22日 12:27/ 0 赞/ 80 阅读
相关 异常处理:忘记捕获导致程序崩溃的案例 在编程中,异常处理是非常重要的一环。它可以帮助我们避免因为意外情况导致程序崩溃或出现不可预期的行为。 下面是一个可能的例子: ```python def divide(a, 怼烎@/ 2024年09月17日 08:24/ 0 赞/ 56 阅读
相关 Java异常处理:未捕获异常导致程序崩溃实例 在Java编程中,异常处理是为了避免程序因为意外或预期外的情况而直接停止运行。当一个未被捕获的异常被抛出时,程序将自动进入异常处理流程。 下面是一个例子,展示了未捕获异常会导 约定不等于承诺〃/ 2024年09月12日 01:51/ 0 赞/ 90 阅读
相关 Android使用CrashHandler编写异常捕获类,分析程序崩溃原因 概述 无论你的程序写的多么完美,都不可能避免会发生crash。可能是由于系统底层的bug,也可能是由于不充分的机型适配......等。当发生更crash时,系统会kill 墨蓝/ 2023年10月18日 15:21/ 0 赞/ 141 阅读
相关 Android 应用崩溃捕获工具 xCrash 源代码:[https://gitee.com/mirrors/xCrash][https_gitee.com_mirrors_xCrash] xCrash xCras 妖狐艹你老母/ 2023年10月11日 13:06/ 0 赞/ 39 阅读
相关 自定义CrashHandler捕获全局未处理异常 在我们实际开发中,很多时候有些程序的异常并没有完全进行捕捉处理,如果程序执行到报错的代码时,程序就会强行停止,force close,并且界面对用户来说是不友 水深无声/ 2022年09月19日 01:57/ 0 赞/ 171 阅读
相关 android捕获全局异常,CrashHandler 1. package com.numob.david.util; 2. 3. import java.io.File; 4. import jav 迈不过友情╰/ 2022年08月07日 08:59/ 0 赞/ 200 阅读
相关 IOS 程序崩溃原因总结 [为什么80%的码农都做不了架构师?>>> ][80_] ![hot3.png][] 1. 访问某个对象不存在的属性。 2. 访问已经被dealloc的对象。 3. 在 怼烎@/ 2022年01月17日 01:49/ 0 赞/ 301 阅读
还没有评论,来说两句吧...