Day9 APP中抓取崩溃日志与邮件通知

来源:互联网 发布:淘宝实名认证步骤 编辑:程序博客网 时间:2024/06/07 09:54

点此进入目录:[干货] 十天 教你从创意到上线APP

一、异常的捕获

1、异常捕获类

首先,我们定义一个CrashHelper ,继承自UncaughtExceptionHandler ,这个类用来捕获系统出现的异常信息。

/** * Created by   : WGH. */public class CrashHelper implements UncaughtExceptionHandler {    private Context mContext;    private static CrashHelper crashHelper;    private UncaughtExceptionHandler mDefaultHandler;    private CrashHelper() {    }    public static CrashHelper getInstance() {        if (crashHelper == null) {            crashHelper = new CrashHelper();        }        return crashHelper;    }    public void init(Context context) {        mContext = context;        // to get the default UncaughtException of system        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();        // to set the CrashHandler as the default program handler        Thread.setDefaultUncaughtExceptionHandler(this);    }    @Override    public void uncaughtException(Thread thread, Throwable exception) {        MessageUtil.postAppCrashMsg(exception, mDefaultHandler, thread);    }}

当系统出现异常的时候,我们就可以在这个uncaughtException()函数中捕获到异常和线程的一些相关信息,这里我们发送了异常的消息,然后就可以在Service中进行处理了。当然,在正常使用之前,还需要进行CrashHelper的初始化,我们将这部分工作放到MyApplication中进行。

2、全局MyApplication中的初始化

代码很简答,如下:

/** * Created by   : WGH. */public class MyApplication extends Application{    private MyApplication mMyApplication;    @Override    public void onCreate() {        super.onCreate();        mMyApplication = this;        CrashHelper handler = CrashHelper.getInstance();        handler.init(getApplicationContext());    }    public static MyApplication context() {        return mMyApplication;    }    public static Gson getGson() {        GsonBuilder builder = new GsonBuilder();        return builder.create();    }    public static DaoMaster getDaoMaster() {        if (daoMaster == null) {            DaoMaster.OpenHelper helper = new DaoMaster.DevOpenHelper(mMyApplication, Define.DBNAME, null);            daoMaster = new DaoMaster(helper.getReadableDatabase());        }        return daoMaster;    }    public static DaoSession getDaoSession() {        if (daoSession == null) {            if (daoMaster == null) {                daoMaster = getDaoMaster();            }            daoSession = daoMaster.newSession();        }        return daoSession;    }}

可以看到,我们在MyApplication 中做了不少事情:getGson、getDaoSession等,这里初始化异常最主要的代码就是这两句:

        CrashHelper handler = CrashHelper.getInstance();        handler.init(getApplicationContext());

二、异常的传递和处理

1、接收异常消息

在我们捕获到异常的时候,我们会在Service中进行消息的接收,然后对之进行处理(邮件上传)。

以下就是消息接收的代码:
    @Subscribe(threadMode = ThreadMode.MAIN)    public void onMessageEvent(CrashMessage message) {        switch (message.what) {            case PreDefine.AppCrash:                mThread = message.thread;                mException = message.throwable;                mExceptionHandler = message.exceptionHandler;                handleException(mException);                break;        }    }

可以看到,我们使用了事件总线的方式来接收消息,然后在拿到各个参数后调用handleException(mException)进行后续的逻辑处理。

2、处理异常消息

    private boolean handleException(Throwable exception) {        if (exception == null) {            return false;        }        final StackTraceElement[] stack = exception.getStackTrace();        final String message = exception.getMessage();        new Thread() {            @Override            public void run() {                Looper.prepare();                String fileName = Define.LogFileName;                if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {                    File file = new File(Environment.getExternalStorageDirectory(), fileName);                    mFilePath = file.getPath();                    try {                        FileOutputStream fileOutputStream = new FileOutputStream(file, true);                        fileOutputStream.write((message + "\n\n").getBytes());                        for (StackTraceElement stackTraceElement : stack) {                            fileOutputStream.write(stackTraceElement.toString().getBytes());                        }                        fileOutputStream.flush();                        fileOutputStream.close();                        if (NetWorkUtil.isNetWork()) {                            String[] toAddress = {PreDefine.getMailNumTo()};                            EmailHelper.sendComplex(toAddress, MainActivity.activityMain.getResources()                                    .getString(R.string.mail_title_crashlog), mEmailSubject, mFilePath);                            deleteFile();                        }                        handleExceptionBySystem();                    } catch (Exception e) {                        DLog.e(e.toString());                    }                }                Looper.loop();            }        }.start();        return true;    }    private void handleExceptionBySystem() {        mExceptionHandler.uncaughtException(mThread, mException);    }

首先,我们通过exception.getStackTrace()获取到异常信息栈,然后通过exception.getMessage()获取异常信息,最后开启子线程将异常信息写入到文件流并发送出去。

关于邮件的逻辑我就不详细介绍了,感兴趣的可以参阅我的项目源码:。。。

联系方式:

简书:WillFlow
CSDN:WillFlow
微信公众号:WillFlow

微信公众号:WillFlow

原创粉丝点击