android程序奔溃异常捕捉

来源:互联网 发布:汉字输入法软件 编辑:程序博客网 时间:2024/05/15 00:08

我们的程序虽然在发布之前都会经过严格测试,但是总会有一个bug导致奔溃,这时为了将这个bug记录下来,如果有机会也可以把这些奔溃日志发给我们,做进一步的处理.

一、异常捕捉

  1. 要对程序的异常进行捕获,必须重写UncaughtExceptionHandler,如下:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MyUncaughtException implements UncaughtExceptionHandler {  
  2.   
  3.     private Context mContext;  
  4.     private UncaughtExceptionHandler mDefaultHandler;  
  5.       
  6.     @Override  
  7.     public void uncaughtException(Thread thread, Throwable ex) {  
  8.         // TODO Auto-generated method stub  
  9.         if (!handleException(thread, ex) && mDefaultHandler != null) {  
  10.             mDefaultHandler.uncaughtException(thread, ex);  
  11.         } else {  
  12.             try {  
  13.                 Thread.sleep(3000);  
  14.             } catch (InterruptedException e) {  
  15.                 // TODO Auto-generated catch block  
  16.                 e.printStackTrace();  
  17.             }  
  18.         }  
  19.           
  20.         //默认处理  
  21.         mDefaultHandler.uncaughtException(thread, ex);  
[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1.  <span style="white-space:pre">  </span>android.os.Process.killProcess(android.os.Process.myPid());    
  2.         System.exit(1);    
  3.       
  4.     // 重新启动程序,注释上面的退出程序  
  5.        Intent intent = new Intent();  
  6.        intent.setClass(mContext,MainActivity.class);  
  7.        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);  
  8.        mContext.startActivity(intent);  
  9.        android.os.Process.killProcess(android.os.Process.myPid());  
  10.   
  11.     }  
  12.   
  13.     //单例模式保证  
  14.     private MyUncaughtException() {  
  15.     }  
  16.       
  17.     private static MyUncaughtException instance = null;  
  18.       
  19.     public static MyUncaughtException getInstance() {  
  20.         if(instance == null) {  
  21.             instance = new MyUncaughtException();  
  22.         }  
  23.         return instance;  
  24.     }  
  25.       
  26.     //初始化  
  27.     public void init(Context context) {  
  28.         mContext = context;  
  29.         mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();  
  30.         Thread.setDefaultUncaughtExceptionHandler(this);  
  31.     }  
  32.       
  33.     //异常处理,保存错误信息,发送等操作  
  34.     private boolean handleException(Thread thread, Throwable e) {  
  35.         if(e == null) {  
  36.             return false;  
  37.         }  
  38.           
  39.         final String error = e.getLocalizedMessage();  
  40.         //显示异常信息  
  41.         new Thread() {  
  42.   
  43.             @Override  
  44.             public void run() {  
  45.                 // TODO Auto-generated method stub  
  46.                 Looper.prepare();  
  47.                 String description = "程序出错了";  
  48.                 if(error != null) {  
  49.                     description += error;  
  50.                 }  
  51.                 Toast.makeText(mContext, description, Toast.LENGTH_SHORT).show();  
  52.                 Looper.loop();  
  53.                 super.run();  
  54.             }  
  55.               
  56.         }.start();  
  57.           
  58.         //保存错误信息  
  59.         saveCrashLog();  
  60.         return true;  
  61.     }  
  62.       
  63.     //这里暂不写实现了  
  64.     private void saveCrashLog() {  
  65.           
  66.   
  67. }  


 

  1. 需要在Application中注册,用来监控整个程序

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. public class MyApp extends Application {  
  2.   
  3.     @Override  
  4.     public void onCreate() {  
  5.         // TODO Auto-generated method stub  
  6.         super.onCreate();  
  7.         MyUncaughtException exceptionHandler = MyUncaughtException.getInstance();  
  8.         exceptionHandler.init(getApplicationContext());  
  9.     }  
  10.   
  11. }  


 

  1. 修改androidManifest.xmlapplicationname

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <application  
  2.         android:allowBackup="true"  
  3.         android:icon="@drawable/ic_launcher"  
  4.         android:label="@string/app_name"  
  5.         android:name="MyApp"  


4. 始终不理解的是为什么要使用线程处理,为什么将线程升级为looper线程?

如果主线程发生uncaughtException 通常会导致main thread 的looper 退出,这时不会再响应任何UI消息,所以要在其他线程中调用显示的方法。

一直没有找到这地方的源码,猜测,在调用Toast.show()方法的时候,最后会形成一条消息Message,并且如果当前线程没有Handler,会自动构造一个默认的Handler,进行处理,最后这个消息发送Handler对应的Loooper,所以,这个线程一定要是Looper线程,而且在Toast之前,Looper线程已经调用Looper.prapare();

0 0
原创粉丝点击