Android關於全局異常捕獲及發送到服務器

在做項目的過程中,出現異常是在所難免的,Android開發也難逃一劫。
搞過Android開發的朋友都知道,只要程序中出現有異常情況,如果沒有對異常進行處理,那麼整個應用程序都會出現崩潰的現象。如果是在調試的階段出現崩潰現象到是沒有什麼大問題,因爲你可以通過控制檯打印出異常信息,進而修改代碼,避免異常。可是,如果產品已經上線了,用戶在使用過程中出現崩潰,這時候你應該怎麼辦呢?直接找客戶看異常信息?不可能,因爲你沒有對異常信息進行捕獲,一崩潰就什麼都“消失”了。還有,假設你對捕獲了異常信息,把異常信息想寫到了sd卡里面,但是出現問題的手機是在用戶手上,出現異常你就找客戶,讓他去他手機上的SD卡查看異常信息,然後再告訴你哪裏出現了問題。我說兄弟,你不要指望每個用戶都是程序員!
好了,面對以上出現的問題,我們應該如何解決呢?
一、進行全局異常捕獲
二、將異常信息寫入SD卡
三、程序崩潰了就無法訪問網絡了,故當再次啓動應用程序時,將寫到SD卡里面的異常信息讀取出來,然後發送到服務器。這樣開發人員就可以看到用戶手機上出現的異常情況了

可是擺在面前的一個問題,如何全局捕獲異常信息?
步驟:
1.定義一個類,該類繼承Application類
2.在配置文件清單中配置該Application類
3.實現oncreate方法,捕獲異常信息

關鍵代碼:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import android.app.Application;
import android.os.Environment;
/**
 * 注意:一定要記得在清單文件中配置
 * @author Administrator
 *
 */
public class BaseApplication extends Application {
    //Called when the application is starting當應用程序被開啓的時候調用
    //before any other application objects have been created
    @Override
    public void onCreate() {
        //老母子的方法。 基地
        //重新系統的異常處理器
        Thread.currentThread().setUncaughtExceptionHandler(new MyExceptionHander());
        super.onCreate();
    }
    //要全局捕獲異常,需要自定義一個類,該類須要繼承UncaughtExceptionHandler
    private class MyExceptionHander implements UncaughtExceptionHandler{
        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            //留下了 留下遺囑的時間
            System.out.println("發生了異常,但是被我們給捕獲了。。");

            //專注自殺的方法,就是殺死自己的進程, 早死早超生
                             android.os.Process.killProcess(android.os.Process.myPid());
        }
    }
}

通過以上代碼,我們已經可以全局捕獲到異常信息了,也就是不管你的app在哪裏出現了異常,基本上都可以捕獲得到。捕獲到的異常,通過參數ex傳入到方法uncaughtException()中,下一步,我們在方法uncaughtException()將異常信息寫到SD卡里
關鍵代碼如下:

try {
                StringWriter wr = new StringWriter();
                PrintWriter pw = new PrintWriter(wr);
                ex.printStackTrace(pw);
                File file = new File(Environment.getExternalStorageDirectory(),"error.log");
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(wr.toString().getBytes());
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

整體代碼如下:

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import android.app.Application;
import android.os.Environment;
/**
 * 注意:一定要記得在清單文件中配置
 * @author Administrator
 *
 */
public class MobileSafeApplication extends Application {
    //Called when the application is starting當應用程序被開啓的時候調用
    //before any other application objects have been created
    @Override
    public void onCreate() {
        //老母子的方法。 基地
        //重新系統的異常處理器
        Thread.currentThread().setUncaughtExceptionHandler(new MyExceptionHander());
        super.onCreate();
    }

    private class MyExceptionHander implements UncaughtExceptionHandler{
        @Override
        public void uncaughtException(Thread thread, Throwable ex) {
            //留下了 留下遺囑的時間
            System.out.println("發生了異常,但是被我們給捕獲了。。");
            try {
                StringWriter wr = new StringWriter();
                PrintWriter pw = new PrintWriter(wr);
                ex.printStackTrace(pw);
                File file = new File(Environment.getExternalStorageDirectory(),"error.log");
                FileOutputStream fos = new FileOutputStream(file);
                fos.write(wr.toString().getBytes());
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            //專注自殺的方法,就是殺死自己的進程, 早死早超生
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }
}

好了,我們已經把異常信息寫到SD卡里面了,但只要出現異常崩潰,程序就掛了,雖然可以通過SD卡里面保存的異常日誌查看異常信息,可是出現問題的手機可能是客戶的,所以爲了能讓我們開發人員更好的維護,就要在application調用oncreate方法時,將異常信息發送到服務器。有一個免費的比較好的異常管理工具,叫做bugly,它是騰訊bugly提供的,網址> http://bugly.qq.com,不收錢,只要大家使用QQ登錄進去就可以了,並且界面管理得挺好,它其實已經幫我們把以上關於全局異常捕獲的類封裝好了,還提供了一個異常回調的函數。我們只需要將其jar包導入到自己的工程,在application中調用,就可以了。
關鍵代碼如下:

CrashReport.UserStrategy strategy = new CrashReport.UserStrategy(context); //App的策略Bean
        strategy.setAppVersion(CommonUtil.getVersionName(context));      //App的版本
        strategy.setAppReportDelay(5000);  //設置SDK處理延時,毫秒
        //回調類CrashHandleCallback的方法裏面已經封裝了全局捕獲異常,並且當出現異常時,自動上傳到騰訊bugly,無需手動上傳
        strategy.setCrashHandleCallback(new CrashReport.CrashHandleCallback() {
            /**
             *
             * @param crashType 錯誤類型   CRASHTYPE_JAVA=0,CRASHTYPE_NATIVE=2;CRASHTYPE_U3D=3;CRASHTYPE_ANR=4
             * @param errorType 錯誤類型名
             * @param errorMessage 錯誤信息
             * @param errorStack 錯誤堆棧
             * @param //Map<String key, String value>  額外的自定義上傳信息
             * @return
             */
            @Override
            public synchronized Map<String, String> onCrashHandleStart(int crashType, String errorType, String errorMessage, String errorStack) {
                FileOutputStream fos=null;
                try {
                    File file = new File(Environment.getExternalStorageDirectory(),"/error.log");
//              File file = new File("E://error.log");
                    fos = new FileOutputStream(file);
                    String time= CommonUtil.getDateFormat(System.currentTimeMillis());
                    String error="crashType----->"+crashType+"--errorType--"+errorType+"--errorMessage-->"+errorMessage+"--errorStack-->"+errorStack+"_發生異常時間:"+time;
                    LogUtils.d(this.getClass().getSimpleName(),error);
                    fos.write(error.getBytes());
                } catch (Exception e) {
                    e.printStackTrace();
                }finally{
                    if(fos!=null){
                        try {
                            fos.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                        fos=null;
                    }
                }
                //專注自殺的方法,就是殺死自己的進程, 早死早超生,但殺死進程後,將無法上傳異常到騰訊bugly
                Process.killProcess(Process.myPid());
                return null;
            }
        });
        CrashReport.initCrashReport(context, "900004802", true, strategy); //自定義策略生效,必須在初始化SDK前調用
        CrashReport.setUserId("aixiu_org");
也就是說,我們在處理異常的時候,前面的步驟也都可以忽略掉了,直接參考騰訊bugly提供文檔,然後把它集成到自己的項目中,就OK了。這樣,當出現異常信息的時候,不僅可以寫到SD卡,再次進入app時,還可以將異常信息上報到bugly服務器,只要登錄到

http://bugly.qq.com就可以管理了

如果這文章對你有用,請點贊,謝謝!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章