现在的位置: 首页 > 综合 > 正文

[Android]将应用崩溃信息汇报给开发者并重新启动应用

2013年10月29日 ⁄ 综合 ⁄ 共 4371字 ⁄ 字号 评论关闭

在开发过程中,虽然经过测试,但在发布后,在广大用户各种各样的运行环境和操作下,可能会发生一些异想不到的错误导致程序崩溃。将这些错误信息收集起来并反馈给开发者,对于开发者改进优化程序是相当重要的。好了,下面就来实现这种功能吧。

(更正:2012年2月9日18时42分07秒)
由于为历史帖原因,以下做法比较浪费,但抓取异常的效果是一样的。
1.对于UI线程(即Android中的主线程)抛出的未捕获异常,将这些异常信息存储起来然后关闭到整个应用程序。并再次启动程序,则进入崩溃信息反馈界面让用户将出错信息以Email的形式发送给开发者。
2.对于非UI线程抛出的异常,则立即唤醒崩溃信息反馈界面提示用户将出错信息发送Email。

效果图如下[CSDN]:

error report
过程了解了,则需要了解的几个知识点如下:
1.拦截UncaughtException
Application.onCreate()是整个Android应用的入口方法。在该方法中执行如下代码即可拦截UncaughtException:

[java] view
plain
copy

  1. ueHandler = new UEHandler(this);  
  2. // 设置异常处理实例  
  3. Thread.setDefaultUncaughtExceptionHandler(ueHandler);  

 

2.抓取导致程序崩溃的异常信息
UEHandler是Thread.UncaughtExceptionHandler的实现类,在其public void uncaughtException(Thread thread, Throwable ex)的实现中可以获取崩溃信息,代码如下:

[java] view
plain
copy

  1. // fetch Excpetion Info  
  2. String info = null;  
  3. ByteArrayOutputStream baos = null;  
  4. PrintStream printStream = null;  
  5. try {  
  6.     baos = new ByteArrayOutputStream();  
  7.     printStream = new PrintStream(baos);  
  8.     ex.printStackTrace(printStream);  
  9.     byte[] data = baos.toByteArray();  
  10.     info = new String(data);  
  11.     data = null;  
  12. catch (Exception e) {  
  13.     e.printStackTrace();  
  14. finally {  
  15.     try {  
  16.         if (printStream != null) {  
  17.             printStream.close();  
  18.         }  
  19.         if (baos != null) {  
  20.             baos.close();  
  21.         }  
  22.     } catch (Exception e) {  
  23.         e.printStackTrace();  
  24.     }  
  25. }  

 


3.程序抛异常后,要关闭整个应用
悲催的程序员,唉,以下三种方式都无效了,咋办啊!!!
    3.1android.os.Process.killProcess(android.os.Process.myPid());
    3.2ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
        am.restartPackage("lab.sodino.errorreport");
    3.3System.exit(0)
    
    好吧,毛主席告诉我们:自己动手丰衣足食。
    SoftApplication中声明一个变量need2Exit,其值为true标识当前的程序需要完整退出;为false时该干嘛干嘛去。该变量在应用的启动Activity.onCreate()处赋值为false。
    在捕获了崩溃信息后,调用SoftApplication.setNeed2Exit(true)标识程序需要退出,并finish()掉ActErrorReport,这时ActErrorReport退栈,抛错的ActOccurError占据手机屏幕,根据Activity的生命周期其要调用onStart(),则我们在onStart()处读取need2Exit的状态,若为true,则也关闭到当前的Activity,则退出了整个应用了。此方法可以解决一次性退出已开启了多个Activity的Application。详细代码请阅读下面的示例源码。

 

好了,代码如下:

lab.sodino.errorreport.SoftApplication.java

[java] view
plain
copy

  1. package lab.sodino.errorreport;  
  2. import java.io.File;  
  3. import android.app.Application;  
  4. /** 
  5.  * @author Sodino E-mail:sodinoopen@hotmail.com 
  6.  * @version Time:2011-6-9 下午11:49:56 
  7.  */  
  8. public class SoftApplication extends Application {  
  9.     /** "/data/data/<app_package>/files/error.log" */  
  10.     public static final String PATH_ERROR_LOG = File.separator + "data" + File.separator + "data"  
  11.             + File.separator + "lab.sodino.errorreport" + File.separator + "files" + File.separator  
  12.             + "error.log";  
  13.     /** 标识是否需要退出。为true时表示当前的Activity要执行finish()。 */  
  14.     private boolean need2Exit;  
  15.     /** 异常处理类。 */  
  16.     private UEHandler ueHandler;  
  17.     public void onCreate() {  
  18.         need2Exit = false;  
  19.         ueHandler = new UEHandler(this);  
  20.         // 设置异常处理实例  
  21.         Thread.setDefaultUncaughtExceptionHandler(ueHandler);  
  22.     }  
  23.     public void setNeed2Exit(boolean bool) {  
  24.         need2Exit = bool;  
  25.     }  
  26.     public boolean need2Exit() {  
  27.         return need2Exit;  
  28.     }  
  29. }  

lab.sodino.errorreport.ActOccurError.java

[java] view
plain
copy

  1. package lab.sodino.errorreport;  
  2. import java.io.File;  
  3. import java.io.FileInputStream;  
  4. import android.app.Activity;  
  5. import android.content.Intent;  
  6. import android.os.Bundle;  
  7. import android.util.Log;  
  8. import android.view.View;  
  9. import android.widget.Button;  
  10. public class ActOccurError extends Activity {  
  11.     private SoftApplication softApplication;  
  12.     /** Called when the activity is first created. */  
  13.     @Override  
  14.     public void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.main);  
  17.         softApplication = (SoftApplication) getApplication();  
  18.         // 一开始进入程序恢复为"need2Exit=false"。  
  19.         softApplication.setNeed2Exit(false);  
  20.         Log.d("ANDROID_LAB""ActOccurError.onCreate()");  
  21.         Button btnMain = (Button) findViewById(R.id.btnThrowMain);  
  22.         btnMain.setOnClickListener(new Button.OnClickListener() {  
  23.             public void onClick(View v) {  
  24.                 Log.d("ANDROID_LAB""Thread.main.run()");  
  25.                 int i = 0;  
  26.                 i = 100 / i;  
  27.             }  
  28.         });  
  29.         Button btnChild = (Button) findViewById(R.id.btnThrowChild);  
  30.         btnChild.setOnClickListener(new Button.OnClickListener() {  
  31.             

抱歉!评论已关闭.