文章出處

本篇文章包含以下內容:

Crash異常捕獲的簡單使用 Crash異常捕獲并發送到服務器

在項目中,我們常常會遇到Crash的現象,也就是程序崩潰的時候,這個時候最常看到的就是這個界面

\

如果你的項目已經發布到市場上了,這樣的崩潰對于開發人員是看不到的,所以我們得想方法將崩潰信息發送到服務器,交給我們的程序員查看,Google考慮到這一點,也提供了Thread.UncaughtExceptionHandler接口來實現這一問題

一、Crash異常捕獲的簡單使用

創建Crash異常捕獲很簡單,主要的步驟有:

創建BaseApplication繼承Application并實現Thread.UncaughtExceptionHandler 通過Thread.setDefaultUncaughtExceptionHandler(this)設置默認的異常捕獲 最后在manifests中注冊創建的BaseApplication

public class BaseApplication extends Application implements Thread.UncaughtExceptionHandler {    @Override    public void onCreate() {        super.onCreate();        //設置異常捕獲        Thread.setDefaultUncaughtExceptionHandler(this);    }    @Override    public void uncaughtException(final Thread thread, final Throwable ex) {        //當有異常產生時執行該方法    }}

我們可以在uncaughtException()方法中輸出異常信息,并讓它隔兩秒殺死自己進程,這樣就不會彈出崩潰的彈窗,讓它直接退出程序

/** * 當有異常產生時執行該方法 * @param thread 當前線程 * @param ex 異常信息 */@Overridepublic void uncaughtException(final Thread thread, final Throwable ex) {    new Thread(new Runnable() {        @Override        public void run() {            Log.e("TAG","currentThread:"+Thread.currentThread()+"---thread:"+thread.getId()+"---ex:"+ex.toString());        }    }).start();    SystemClock.sleep(2000);    android.os.Process.killProcess(android.os.Process.myPid());}

最后一步,別忘了在manifests中注冊BaseApplication

我們通過運行這個方法,來測試我們的程序

private void testError() {    int a = 10 / 0;}

查看Log信息,驗證我們的錯誤信息

12-18 11:40:02.074 7510-7555/com.handsome.ap E/TAG: currentThread:Thread[Thread-325,5,main]---thread:1---ex:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.handsome.ap/com.handsome.ap.Activity.MainActivity}: java.lang.ArithmeticException: divide by zero

完整代碼

public class BaseApplication extends Application implements Thread.UncaughtExceptionHandler {    @Override    public void onCreate() {        super.onCreate();        //設置異常捕獲        Thread.setDefaultUncaughtExceptionHandler(this);    }    /**     * 當有異常產生時執行該方法     * @param thread 當前線程     * @param ex 異常信息     */    @Override    public void uncaughtException(final Thread thread, final Throwable ex) {        new Thread(new Runnable() {            @Override            public void run() {                Log.e("TAG","currentThread:"+Thread.currentThread()+"---thread:"+thread.getId()+"---ex:"+ex.toString());            }        }).start();        SystemClock.sleep(2000);        android.os.Process.killProcess(android.os.Process.myPid());    }}
二、Crash異常捕獲并發送到服務器

其實這里就是將上面的簡單使用進行封裝,在一個類中處理相關的邏輯,主要步驟和上面是一樣的

public class CrashHandler implements Thread.UncaughtExceptionHandler {    /**     * 捕獲異常回掉     *     * @param thread 當前線程     * @param ex     異常信息     */    @Override    public void uncaughtException(Thread thread, Throwable ex) {        //導出異常信息到SD卡        dumpExceptionToSDCard(ex);        //上傳異常信息到服務器        uploadExceptionToServer(ex);        //延時1秒殺死進程        SystemClock.sleep(2000);        Process.killProcess(Process.myPid());    }}

我們為下面的信息保存先提供一些成員變量

//文件夾目錄private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/crash_log/";//文件名private static final String FILE_NAME = "crash";//文件名后綴private static final String FILE_NAME_SUFFIX = ".trace";//上下文private Context mContext;//單例模式private static CrashHandler sInstance = new CrashHandler();private CrashHandler() {}public static CrashHandler getInstance() {    return sInstance;}

提供一個初始化的方法,記得調用Thread.setDefaultUncaughtExceptionHandler(this)這個方法

/** * 初始化方法 * * @param context */public void init(Context context) {    //將當前實例設為系統默認的異常處理器    Thread.setDefaultUncaughtExceptionHandler(this);    //獲取Context,方便內部使用    mContext = context.getApplicationContext();}

剩下的就是保存異常信息了,這里發送到服務端采用的是Bmob第三方后端云

/** * 導出異常信息到SD卡 * * @param ex */private void dumpExceptionToSDCard(Throwable ex) {    if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {        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));    //以當前時間創建log文件    File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);    try {        //輸出流操作        PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));        //導出手機信息和異常信息        PackageManager pm = mContext.getPackageManager();        PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);        pw.println("發生異常時間:" + time);        pw.println("應用版本:" + pi.versionName);        pw.println("應用版本號:" + pi.versionCode);        pw.println("android版本號:" + Build.VERSION.RELEASE);        pw.println("android版本號API:" + Build.VERSION.SDK_INT);        pw.println("手機制造商:" + Build.MANUFACTURER);        pw.println("手機型號:" + Build.MODEL);        ex.printStackTrace(pw);        //關閉輸出流        pw.close();    } catch (Exception e) {    }}/** * 上傳異常信息到服務器 * * @param ex */private void uploadExceptionToServer(Throwable ex) {    Error error = new Error(ex.getMessage());    error.save(new SaveListener() {        @Override        public void done(String objectId, BmobException e) {        }    });}

在我們的Application中創建該異常捕獲

CrashHandler crashHandler = CrashHandler.getInstance();crashHandler.init(this);

我們同樣按照上面的方法來測試這個異常捕獲,運行程序,在文件夾中找到我們創建的目錄

\

找到對應文件

\

查看對應信息

\

后臺數據庫的信息

\

完整代碼

public class CrashHandler implements Thread.UncaughtExceptionHandler {    //文件夾目錄    private static final String PATH = Environment.getExternalStorageDirectory().getPath() + "/crash_log/";    //文件名    private static final String FILE_NAME = "crash";    //文件名后綴    private static final String FILE_NAME_SUFFIX = ".trace";    //上下文    private Context mContext;    //單例模式    private static CrashHandler sInstance = new CrashHandler();    private CrashHandler() {}    public static CrashHandler getInstance() {        return sInstance;    }    /**     * 初始化方法     *     * @param context     */    public void init(Context context) {        //將當前實例設為系統默認的異常處理器        Thread.setDefaultUncaughtExceptionHandler(this);        //獲取Context,方便內部使用        mContext = context.getApplicationContext();    }    /**     * 捕獲異常回掉     *     * @param thread 當前線程     * @param ex     異常信息     */    @Override    public void uncaughtException(Thread thread, Throwable ex) {        //導出異常信息到SD卡        dumpExceptionToSDCard(ex);        //上傳異常信息到服務器        uploadExceptionToServer(ex);        //延時1秒殺死進程        SystemClock.sleep(2000);        Process.killProcess(Process.myPid());    }    /**     * 導出異常信息到SD卡     *     * @param ex     */    private void dumpExceptionToSDCard(Throwable ex) {        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {            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));        //以當前時間創建log文件        File file = new File(PATH + FILE_NAME + time + FILE_NAME_SUFFIX);        try {            //輸出流操作            PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(file)));            //導出手機信息和異常信息            PackageManager pm = mContext.getPackageManager();            PackageInfo pi = pm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);            pw.println("發生異常時間:" + time);            pw.println("應用版本:" + pi.versionName);            pw.println("應用版本號:" + pi.versionCode);            pw.println("android版本號:" + Build.VERSION.RELEASE);            pw.println("android版本號API:" + Build.VERSION.SDK_INT);            pw.println("手機制造商:" + Build.MANUFACTURER);            pw.println("手機型號:" + Build.MODEL);            ex.printStackTrace(pw);            //關閉輸出流            pw.close();        } catch (Exception e) {        }    }    /**     * 上傳異常信息到服務器     *     * @param ex     */    private void uploadExceptionToServer(Throwable ex) {        Error error = new Error(ex.getMessage());        error.save(new SaveListener() {            @Override            public void done(String objectId, BmobException e) {            }        });    }}

到這里我們的Crash異常捕獲就結束了,很簡單的一段代碼就可以解決你缺少的項目經驗

看文倉www.kanwencang.com網友整理上傳,為您提供最全的知識大全,期待您的分享,轉載請注明出處。
歡迎轉載:http://www.kanwencang.com/bangong/20170114/87911.html

文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()