远程获取应用程序的crash信息

使用CrashHandler来获取应用的crash信息

Android应用难免遇到crash的情况,当程序crash后就会造成“闪退”,这对用户来说是很不友好的,然而当用户crash的时候,开发者并不知道是什么原因导致,尤其是版本上线后很不利于一个产品的持续发展

好在Android提供了处理这类问题的方法,可以通过CrashHandler来监视应用的crash信息,给程序设置一个CrashHandler,这样当程序crash时就会调用CrashHandler的uncaughtException方法。这个方法中我们就可以将获取的crash信息上传到服务器,开发人员就可以对一些错误进行修复了

Thread类中的setDefaultUncaughtExceptionHandler源码:

/**
 * Sets the default uncaught exception handler. This handler is invoked in
 * case any Thread dies due to an unhandled exception.
 *
 * @param handler
 *            The handler to set or null.
 */
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler handler) {
    Thread.defaultUncaughtHandler = handler;
}

当crash发生的时候系统就会回掉UncaughtExceptionHandler的uncaughtException方法,在uncaughtException方法中就可以获取到异常信息,可以先把异常信息存储到SD卡中,然后在合适的时机通过网络将crash信息上传到服务器上

具体实现方式

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private static final String TAG = "CrashHandler";
    private static final boolean DEBUG = true;

    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/CrashTest/log/";
    private static final String FILE_NAME = "crash";
    private static final String FILE_NAME_SUFFIX = ".trace";

    private static CrashHandler sInstance = new CrashHandler();
    private Thread.UncaughtExceptionHandler mDefaultCrashHandler;
    private Context mContext;

    private CrashHandler() {
    }

    public static CrashHandler getInstance() {
        return sInstance;
    }

    public void init(Context context) {
        mDefaultCrashHandler = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
        mContext = context.getApplicationContext();
    }

    /**
     * 当程序中有未被捕获的异常,系统将自动调用#uncaughtException方法
     *
     * @param thread 出现未捕获的线程
     * @param ex     未捕获的异常
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        try {
            //导出异常信息到SD卡中
            saveExceptionToSDCard(ex);
            //上传异常信息到服务器
            uploadExceptionToServer();
        } catch (IOException e) {
            e.printStackTrace();
        }

        ex.printStackTrace();
        //如果系统提供了默认的异常处理器,则交给系统去结束程序,否则由自己结束
        if (mDefaultCrashHandler != null) {
            mDefaultCrashHandler.uncaughtException(thread, ex);
        } else {
            Process.killProcess(Process.myPid());
        }

    }

    private void saveExceptionToSDCard(Throwable ex) throws IOException {
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            if (DEBUG) {
                Log.e("TAG", "sdcard not exists!");
                return;
            }
        }

        File dir = new File(PATH);
        if (!dir.exists()) {
            dir.mkdirs();
        }
        long current = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(current));
        File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);

        try {
            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));
            pw.println(time);
            savePhoneInfo(pw);
            pw.println();
            ex.printStackTrace(pw);
            pw.close();
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }

    }

    private void savePhoneInfo(PrintWriter pw) throws PackageManager.NameNotFoundException {
        PackageManager pm = mContext.getPackageManager();
        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
        pw.print("App Version:");
        pw.print(pi.versionName);
        pw.print("_");
        pw.println(pi.versionCode);

        //Android版本号
        pw.print("OS Version:");
        pw.print(Build.VERSION.SDK_INT);

        //手机制造商
        pw.print("Vendor:");
        pw.print(Build.MANUFACTURER);

        //手机型号
        pw.print("Model:");
        pw.println(Build.MODEL);

        //CPU架构
        pw.print("CPU ABI:");
        pw.println(Build.CPU_ABI);
    }

    private void uploadExceptionToServer() {
        //Upload Exception Message To Your Web Server
    }

}

使用方法

public class CrashApp extends MyApplication {

    private static CrashApp instance;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        //在这里为应用设置异常处理,然后程序才能获取未处理的异常
        CrashHandler crashHandler = CrashHandler.getInstance();
        crashHandler.init(this);
    }

    public static CrashApp getInstance() {
        return instance;
    }

}

别忘了在manifest里面配置:

<application
    android:name=".CrashApp"
    android:allowBackup="true"
    android:icon="@drawable/logo_app"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar">
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值