Android应用 捕获应用崩溃的数据CrashHandler

Android应用 捕获应用崩溃的数据CrashHandler

当应用发生崩溃,需要讲崩溃信息保存起来,上传服务器或者保存到数据库

网上这块资料很多,简单记录当作学习笔记吧

首先,创建一个类CrashHandler 实现 UncaughtExceptionHandler 接口

接口UncaughtExceptionHandler的定义

public static interface UncaughtExceptionHandler {
    /**
     * The thread is being terminated by an uncaught exception. Further
     * exceptions thrown in this method are prevent the remainder of the
     * method from executing, but are otherwise ignored.
     *
     * @param thread the thread that has an uncaught exception
     * @param ex the exception that was thrown
     */
    void uncaughtException(Thread thread, Throwable ex);
}

需要实现的方法为uncaughtException,其中的ex就是被抛出的异常
对应的CrashHandler设置为单例。

/**
 * 单例模式
 */
private CrashHandler() {
}

private static CrashHandler instance = null;

public static CrashHandler getInstance() {
    if (null == instance) {
        instance = new CrashHandler();
    }
    return instance;
}

CrashHandler中的init方法,设置系统的异常处理器为CrashHandler

// 系统默认的处理器,需要在自己处理完之后交还给系统处理
private Thread.UncaughtExceptionHandler mDefaultHandler;

public void init(Context context) {
    this.context = context;
    // 系统默认的处理器
    mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    // 设置该CrashHandler为程序的默认处理器
    Thread.setDefaultUncaughtExceptionHandler(this);
}

其次,需要手机异常信息,对应的当前手机系统版本,应用的版本

CrashHandler中的getCrashInfo 方法

private StringBuffer getCrashInfo(Throwable ex) {
    StringBuffer sb = new StringBuffer();
    String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
    // 当前时间
    sb.append("TIME=" + time + "\n");
    // 当前手机信息
    sb.append("DEVICE=" + Build.DEVICE + "\n");
    sb.append("VERSION=" + Build.VERSION.RELEASE + "\n");
    // 获取app的信息
    PackageManager pm = context.getPackageManager();
    PackageInfo pi;
    try {
        pi = pm.getPackageInfo(context.getPackageName(), PackageManager.GET_ACTIVITIES);
        if (pi != null) {
            String versionName = pi.versionName == null ? "null" : pi.versionName;
            String versionCode = pi.versionCode + "";
            // app的版本号和版本名
            sb.append("versionName=" + versionName + "\n");
            sb.append("versionCode=" + versionCode + "\n");
        }
    } catch (NameNotFoundException e) {
        e.printStackTrace();
    }
    // 崩溃错误日志
    Writer writer = new StringWriter();
    PrintWriter printWriter = new PrintWriter(writer);
    ex.printStackTrace(printWriter);
    Throwable cause = ex.getCause();
    while (cause != null) {
        cause.printStackTrace(printWriter);
        cause = cause.getCause();
    }
    printWriter.close();
    String result = writer.toString();
    sb.append(result + "\n");
    return sb;
}

具体实现的uncaughtException 方法,这里一定要交还给系统的处理器

    @Override
public void uncaughtException(Thread thread, Throwable ex) {
    // 获取错误信息 ,写入数据库
    StringBuffer crashInfo = getCrashInfo(ex);
    Log.e(TAG, crashInfo.toString());
    //处理完之后调用默认系统处理器(不调用会一直黑屏)
    mDefaultHandler.uncaughtException(thread, ex);
    //打印错误信息
    ex.printStackTrace();
}

对应的自定的Application类

public class AppApplication extends Application{

@Override
public void onCreate() {
    super.onCreate();
    CrashHandler.getInstance().init(getApplicationContext());
}

}
别忘了在清单文件中修改一下Applicationd配置,为自定义的AppApplication

   
    
        
            

            
        
    

最后测试一下

MainActivity中

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    //崩溃测试
    System.out.println(1/0);
}

}
打印日志(部分)如下

01-29 01:19:40.371: E/leafact-CrashHandler(2029): TIME=2016-01-29 01:19:40

01-29 01:19:40.371: E/leafact-CrashHandler(2029): DEVICE=vbox86p

01-29 01:19:40.371: E/leafact-CrashHandler(2029): VERSION=4.4.4

01-29 01:19:40.371: E/leafact-CrashHandler(2029): versionName=1.0

01-29 01:19:40.371: E/leafact-CrashHandler(2029): versionCode=1

01-29 01:19:40.371: E/leafact-CrashHandler(2029): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.crashapp/com.example.crashapp.MainActivity}: java.lang.ArithmeticException: divide by zero

总结

对于获取的crashInfo,我们可以上传数据到服务器,可以在本地新建Crash_table表进行存储。
有了CrashHandler,对于不断的更新稳定版本很重要

你可能感兴趣的:(Android)