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

   <application
    android:name="com.example.Application.AppApplication"
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application

最后测试一下

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,对于不断的更新稳定版本很重要

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值