程序异常的处理的分析---从起步到超越
2013-09-24 16:33
246 查看
相信大家在使用一些软件时,它们崩溃前都会出现一些对话框,例如“程序终止,点击确定发送错误日志以便我们更好解决问题!”这些应用程序是怎么处理的呢?
所谓“智者千虑,必有一失”。在Android中肯定没少遇到过空指针异常、程序异常终止等相关问题。即便是调试成功了,也很难保证用户的操作不会造成新问题的发生。对于此类FC(force close )问题,我们现在就来看看“愚者千虑,必有一得”的逆袭!
【一】起步篇
先上一段代码:
先定义一个新类,由于需要应用程序的相关操作,继承Application类。在继承类后,这个例子中,我们先看最简单的一个错误解决办法:onLowMemory(),顾名思义,就是在低内存状态程序会触动执行的方法。这个方法可以说把一般左右的问题都解决了。
在这个例子中,我们先是注册了一个广播接受者,在filter里指定一个动作(这里是“kill other process”),在低内存时,发送广播,在继承广播的类里,定义收到广播后的方法,例如可以杀死一些后台进程,或指定其它方法。
【二】同步篇
既然会了基本的问题处理,那么剩下的问题呢?比如程序的空指针异常问题,现在我们仍旧没有处理它。现在我们就来看看另一个需要继承的方法:onCreat()。这个方法我们很熟悉了,它确实和预想中的一样,是程序第一次执行时启动的方法。
这样,我们就知道了可以把许多初始化操作放在其中执行。要想彻底解决其他问题,我们还需要再新建一个类,实现UncaughtExceptionHandler 的接口。这个接口位于lang下的线程中(import java.lang.Thread.UncaughtExceptionHandler)。我们仍旧从代码着手。请看代码:
实现接口中的一个方法:public void uncaughtException(Thread arg0, Throwable arg1)
这里我们在控制台中打印log,并利用安卓进程管理机制,杀死当前的进程。同时,为了保证只创建一个类的实例,我们私有化构造方法,并利用java中的synchronized关键字,实现进程锁。这样,就能保证创建类的实例对象时,只能一次性的、且通过getInstance()方法进行。
好了,再回到Myapp类里,写写onCreat()方法
我们调用getInstance()方法,返回得到一个实现了uncaughtException方法的对象。我们使用代码将其绑定到程序所在的当前进程中。
Thread.currentThread().setUncaughtExceptionHandler(myCrashHandler)
【三】超越篇
现在我们已经兼顾了几乎可能出现的任何问题。但是,如果有其他偶然因素出现时,或者程序终止后我们需要得到错误日志,让用户把错误日志上传到程序所在的服务器,又要怎么操作呢?很高兴的是,Android工程师给我们提供了相关的方法来获取用户信息。
仍然是一段代码:
分析以上代码,不难发现,我们先是得到一个包的管理器(PackageManager),然后调用getPackageInfo方法,获取到出错的版本等软信息。
Android里将所有的硬件信息都打包到了Build.class.getDeclaredFields()中,我们调用它,就会返回一个Field的数组,返回了此类的所有信息。接着,我们将所有Field里的字串直接拼接到Stringbuilder中。然后用ex.printStackTrace(printWriter)获取错误的堆栈信息。如果有所需要,还可以把这些信息都一起发送到服务器。这样工程师就能对错误进行进一步的统计分析,对产品进行优化。
OK,现在大功告成,是不是感觉你的应用程序变得健康许多了呢~
所谓“智者千虑,必有一失”。在Android中肯定没少遇到过空指针异常、程序异常终止等相关问题。即便是调试成功了,也很难保证用户的操作不会造成新问题的发生。对于此类FC(force close )问题,我们现在就来看看“愚者千虑,必有一得”的逆袭!
【一】起步篇
先上一段代码:
public class Myapp extends Application { @Override public void onLowMemory() { super.onLowMemory(); Intent intent= new Intent(); intent.setAction("kill other process"); sendBroadcast(intent); } }
先定义一个新类,由于需要应用程序的相关操作,继承Application类。在继承类后,这个例子中,我们先看最简单的一个错误解决办法:onLowMemory(),顾名思义,就是在低内存状态程序会触动执行的方法。这个方法可以说把一般左右的问题都解决了。
在这个例子中,我们先是注册了一个广播接受者,在filter里指定一个动作(这里是“kill other process”),在低内存时,发送广播,在继承广播的类里,定义收到广播后的方法,例如可以杀死一些后台进程,或指定其它方法。
【二】同步篇
既然会了基本的问题处理,那么剩下的问题呢?比如程序的空指针异常问题,现在我们仍旧没有处理它。现在我们就来看看另一个需要继承的方法:onCreat()。这个方法我们很熟悉了,它确实和预想中的一样,是程序第一次执行时启动的方法。
这样,我们就知道了可以把许多初始化操作放在其中执行。要想彻底解决其他问题,我们还需要再新建一个类,实现UncaughtExceptionHandler 的接口。这个接口位于lang下的线程中(import java.lang.Thread.UncaughtExceptionHandler)。我们仍旧从代码着手。请看代码:
public class MyCrashHandler implements UncaughtExceptionHandler { private MyCrashHandler(){ } //该类的实例对应一把锁,syschronized方法必须获得调用该方法的类的实例才能执行,否则线程阻塞 private static MyCrashHandler myCrashHandler; public static synchronized MyCrashHandler getInstance(){ if(myCrashHandler==null){ myCrashHandler=new MyCrashHandler(); } return myCrashHandler; } public void uncaughtException(Thread arg0, Throwable arg1) { System.out.println("程序出错FC"); android.os.Process.killProcess(android.os.Process.myPid()); } }
实现接口中的一个方法:public void uncaughtException(Thread arg0, Throwable arg1)
这里我们在控制台中打印log,并利用安卓进程管理机制,杀死当前的进程。同时,为了保证只创建一个类的实例,我们私有化构造方法,并利用java中的synchronized关键字,实现进程锁。这样,就能保证创建类的实例对象时,只能一次性的、且通过getInstance()方法进行。
好了,再回到Myapp类里,写写onCreat()方法
public class Myapp extends Application { //应用程序第一次调用时实施绑定UncrashExceptionHandler @Override public void onCreate() { super.onCreate(); MyCrashHandler myCrashHandler= MyCrashHandler.getInstance(); Thread.currentThread().setUncaughtExceptionHandler(myCrashHandler); } }
我们调用getInstance()方法,返回得到一个实现了uncaughtException方法的对象。我们使用代码将其绑定到程序所在的当前进程中。
Thread.currentThread().setUncaughtExceptionHandler(myCrashHandler)
【三】超越篇
现在我们已经兼顾了几乎可能出现的任何问题。但是,如果有其他偶然因素出现时,或者程序终止后我们需要得到错误日志,让用户把错误日志上传到程序所在的服务器,又要怎么操作呢?很高兴的是,Android工程师给我们提供了相关的方法来获取用户信息。
仍然是一段代码:
StringBuilder sb = new StringBuilder(); // 1.获取当前应用程序的版本号. PackageManager pm = context.getPackageManager(); try { PackageInfo packinfo = pm.getPackageInfo(context.getPackageName(), 0); sb.append("程序的版本号为" + packinfo.versionName); sb.append("\n"); // 2.获取手机的硬件信息. Field[] fields = Build.class.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { // 暴力反射,获取私有的字段信息 fields[i].setAccessible(true); String name = fields[i].getName(); sb.append(name + " = "); String value = fields[i].get(null).toString(); sb.append(value); sb.append("\n"); } // 3.获取程序错误的堆栈信息 . StringWriter writer = new StringWriter(); PrintWriter printWriter = new PrintWriter(writer); ex.printStackTrace(printWriter); String result = writer.toString(); sb.append(result); System.out.println(sb.toString()); // 4.把错误信息 提交到服务器 uploadtoHttp(sb); } catch (Exception e) { e.printStackTrace(); } // 完成自杀的操作 android.os.Process.killProcess(android.os.Process.myPid()); }
分析以上代码,不难发现,我们先是得到一个包的管理器(PackageManager),然后调用getPackageInfo方法,获取到出错的版本等软信息。
Android里将所有的硬件信息都打包到了Build.class.getDeclaredFields()中,我们调用它,就会返回一个Field的数组,返回了此类的所有信息。接着,我们将所有Field里的字串直接拼接到Stringbuilder中。然后用ex.printStackTrace(printWriter)获取错误的堆栈信息。如果有所需要,还可以把这些信息都一起发送到服务器。这样工程师就能对错误进行进一步的统计分析,对产品进行优化。
OK,现在大功告成,是不是感觉你的应用程序变得健康许多了呢~
相关文章推荐
- Java程序异常处理的特殊情况
- 调试技巧 —— 如何利用windbg + dump + map分析程序异常
- linux内核分析笔记----中断和中断处理程序
- ABP源码分析四十七:ABP中的异常处理
- android 处理程序全局异常和错误
- 彻底接管程序异常处理
- Nodejs异步回调之异常处理实例分析
- Ajax程序:处理异步调用中的异常(使用Asp.Net Ajax内建的异常处理方法)
- 【java 中的connection reset 异常处理分析】
- Release和Debug程序的不同及异常处理
- 一个用Spring AOP实现异常处理和记录程序执行时间的实例--邵京国
- 【DB.PL/SQL】程序流程控制 —— 异常处理
- ----------------以下总结的5-10课是程序的面向对象和异常处理部分--------------
- R语言|数据预处理--5异常值分析及处理
- 向量化异常处理程序 继续处理程序 veh 例子
- Linux内核分析-异常处理
- linux内核分析笔记----中断和中断处理程序
- EJB3之JPA程序结构,完美的异常处理
- python中用try来处理程序异常的集中常用方法
- Python(六)--异常的处理与程序调试