亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 系統 > Android > 正文

基于Android 錯誤信息捕獲發送至服務器的詳解

2020-04-11 12:08:03
字體:
來源:轉載
供稿:網友
程序員最頭疼的事情就是bug和debug。這次debug長達20天,搞的我心力交瘁。累,因為Android兼容性,不同手機會有不同的bug出來,而且很難復現,所以就上網找了下類似保存錯誤log到文件再上傳到服務器,現把源碼也共享出來。上傳至服務器的代碼我沒加。相信大家都有現成的代碼了。

先講下原理,跟JavaEE的自定義異常捕獲一樣,將錯誤一直向上拋,然后在最上層統一處理。這里就可以獲得Exception Message,進行保存操作
異常捕獲類如下:
復制代碼 代碼如下:

/**
 * @author Stay
 *      在Application中統一捕獲異常,保存到文件中下次再打開時上傳
 */
public class CrashHandler implements UncaughtExceptionHandler {  
    /** 是否開啟日志輸出,在Debug狀態下開啟, 
     * 在Release狀態下關閉以提示程序性能 
     * */ 
    public static final boolean DEBUG = true;  
    /** 系統默認的UncaughtException處理類 */ 
    private Thread.UncaughtExceptionHandler mDefaultHandler;  
    /** CrashHandler實例 */ 
    private static CrashHandler INSTANCE;  
    /** 程序的Context對象 */ 
//    private Context mContext;  
    /** 保證只有一個CrashHandler實例 */ 
    private CrashHandler() {}  
    /** 獲取CrashHandler實例 ,單例模式*/ 
    public static CrashHandler getInstance() {  
        if (INSTANCE == null) {  
            INSTANCE = new CrashHandler();  
        }  
        return INSTANCE;  
    }  

    /** 
     * 初始化,注冊Context對象, 
     * 獲取系統默認的UncaughtException處理器, 
     * 設置該CrashHandler為程序的默認處理器 
     *  
     * @param ctx 
     */ 
    public void init(Context ctx) {  
//        mContext = ctx;  
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();  
        Thread.setDefaultUncaughtExceptionHandler(this);  
    }  

    /** 
     * 當UncaughtException發生時會轉入該函數來處理 
     */ 
    @Override 
    public void uncaughtException(Thread thread, Throwable ex) {  
        if (!handleException(ex) && mDefaultHandler != null) {  
            //如果用戶沒有處理則讓系統默認的異常處理器來處理  
            mDefaultHandler.uncaughtException(thread, ex);  
        } else {  //如果自己處理了異常,則不會彈出錯誤對話框,則需要手動退出app
            try {  
                Thread.sleep(3000);  
            } catch (InterruptedException e) {  
            }  
            android.os.Process.killProcess(android.os.Process.myPid());  
            System.exit(10);  
        }  
    }  

    /** 
     * 自定義錯誤處理,收集錯誤信息 
     * 發送錯誤報告等操作均在此完成. 
     * 開發者可以根據自己的情況來自定義異常處理邏輯 
     * @return 
     * true代表處理該異常,不再向上拋異常,
     * false代表不處理該異常(可以將該log信息存儲起來)然后交給上層(這里就到了系統的異常處理)去處理,
     * 簡單來說就是true不會彈出那個錯誤提示框,false就會彈出
     */ 
    private boolean handleException(final Throwable ex) {  
        if (ex == null) {  
            return false;  
        }  
//        final String msg = ex.getLocalizedMessage();  
        final StackTraceElement[] stack = ex.getStackTrace();
        final String message = ex.getMessage();
        //使用Toast來顯示異常信息  
        new Thread() {  
            @Override 
            public void run() {  
                Looper.prepare();  
//                Toast.makeText(mContext, "程序出錯啦:" + message, Toast.LENGTH_LONG).show();  
//                可以只創建一個文件,以后全部往里面append然后發送,這樣就會有重復的信息,個人不推薦
                String fileName = "crash-" + System.currentTimeMillis()  + ".log";  
                File file = new File(Environment.getExternalStorageDirectory(), fileName);
                try {
                    FileOutputStream fos = new FileOutputStream(file,true);
                    fos.write(message.getBytes());
                    for (int i = 0; i < stack.length; i++) {
                        fos.write(stack[i].toString().getBytes());
                    }
                    fos.flush();
                    fos.close();
                } catch (Exception e) {
                }
                Looper.loop();  
            }  

        }.start();  
        return false;  
    }  

    // TODO 使用HTTP Post 發送錯誤報告到服務器  這里不再贅述
//    private void postReport(File file) {  
//      在上傳的時候還可以將該app的version,該手機的機型等信息一并發送的服務器,
//      Android的兼容性眾所周知,所以可能錯誤不是每個手機都會報錯,還是有針對性的去debug比較好
//    }  
}

在Application onCreate時就注冊ExceptionHandler,此后只要程序在拋異常后就能捕獲到。
復制代碼 代碼如下:

public class App extends Application{
        @Override 
        public void onCreate() {  
            super.onCreate();  
            CrashHandler crashHandler = CrashHandler.getInstance();  
            //注冊crashHandler  
            crashHandler.init(getApplicationContext());  
        }  
}
?public class LogActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        try {//制造bug
            File file = new File(Environment.getExternalStorageState() ,"crash.bin");
            FileInputStream fis = new FileInputStream(file);
            byte[] buffer = new byte[1024];
            fis.read(buffer);
        } catch (Exception e) {
            //這里不能再向上拋異常,如果想要將log信息保存起來,則拋出runtime異常,
//          讓自定義的handler來捕獲,統一將文件保存起來上傳
            throw new RuntimeException(e);
        }
    }
}

注意,如果catch后不throw就默認是自己處理了,ExceptionHandler不會捕獲異常了。
再分享一個Log的封裝類,只要在這里設置DEBUG的值就能讓控制臺是否打印出log
復制代碼 代碼如下:

public class DebugUtil {
    public static final String TAG = "ICON";
    public static final boolean DEBUG = true;

    public static void toast(Context context,String content){
        Toast.makeText(context, content, Toast.LENGTH_SHORT).show();
    }

    public static void debug(String tag,String msg){
        if (DEBUG) {
            Log.d(tag, msg);
        }
    }

    public static void debug(String msg){
        if (DEBUG) {
            Log.d(TAG, msg);
        }
    }

    public static void error(String tag,String error){
        Log.e(tag, error);
    }

    public static void error(String error){
        Log.e(TAG, error);
    }
}

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本免费一区二区三区视频观看| 97精品国产97久久久久久春色| 中文字幕亚洲字幕| 欧美日本高清一区| 久久九九全国免费精品观看| 激情亚洲一区二区三区四区| 亚洲国产福利在线| 久久天天躁狠狠躁夜夜躁| 日韩中文字幕在线| 日韩av综合网| 久久精品色欧美aⅴ一区二区| 国产精品揄拍一区二区| 97久久精品人人澡人人爽缅北| 亚洲性夜色噜噜噜7777| 国产手机视频精品| 国产日产亚洲精品| 国产精品丝袜白浆摸在线| 欧美性猛交xxxx富婆弯腰| 欧美一区视频在线| 美女999久久久精品视频| 亚洲午夜精品视频| 伊人久久综合97精品| 日韩成人在线视频观看| 国产精品久久久久久久7电影| www日韩中文字幕在线看| 欧美日韩国产成人高清视频| 中文字幕在线视频日韩| 俺去啦;欧美日韩| 日韩成人在线电影网| 亚洲一区二区免费在线| 久久久av免费| 国产精品小说在线| 欧美性猛交xxx| 久久久久久高潮国产精品视| 国产精品一二三在线| 国产精品电影观看| 欧美精品福利视频| 国语自产精品视频在线看抢先版图片| 欧美精品videossex性护士| 亚洲欧美国产日韩天堂区| 国产精品入口夜色视频大尺度| 亚洲综合一区二区不卡| 黄色成人av在线| 91在线中文字幕| 一本一本久久a久久精品牛牛影视| 亚洲天堂日韩电影| 色伦专区97中文字幕| 欧美激情xxxx性bbbb| 亚洲影视九九影院在线观看| 国产成人一区二区三区| 亚洲精品视频在线观看视频| 国产精品扒开腿做爽爽爽视频| 亚洲男人的天堂在线| 中文字幕成人精品久久不卡| 久久人人爽国产| 欧美成年人视频网站欧美| 久久国产精彩视频| 国产精品一区专区欧美日韩| 亚洲国产成人精品一区二区| 最新91在线视频| 日韩欧美在线观看| 欧美一级电影免费在线观看| 亚洲a成v人在线观看| 亚洲美女www午夜| 亚洲在线免费视频| 精品欧美国产一区二区三区| 97视频人免费观看| 日韩高清av一区二区三区| 欧美黑人国产人伦爽爽爽| 九九久久精品一区| 91精品国产自产在线| 欧美激情精品久久久久久黑人| 亚洲男女性事视频| 欧美黑人狂野猛交老妇| 中文字幕欧美亚洲| 亚洲黄页视频免费观看| 久久久久久久国产精品视频| 亚洲成人av资源网| 国产精品一区二区久久久久| 亚洲va欧美va国产综合久久| 国产欧美日韩综合精品| 国产在线视频一区| 国产精品免费看久久久香蕉| 狠狠躁18三区二区一区| 清纯唯美日韩制服另类| 浅井舞香一区二区| 亚洲国产精品va在线观看黑人| 57pao成人永久免费视频| 欧美日韩成人黄色| 国产精品海角社区在线观看| 久久亚洲电影天堂| 日韩中文综合网| 成人久久精品视频| 欧美理论电影网| 欧美一级片一区| 国产精品自产拍在线观看中文| 在线观看91久久久久久| 日韩禁在线播放| 热门国产精品亚洲第一区在线| 91久久久久久久久久久久久| 日本免费一区二区三区视频观看| 色吧影院999| 国产精品久久婷婷六月丁香| 成人精品视频久久久久| 久久久久久av| 久久精品91久久香蕉加勒比| 亚洲a中文字幕| 欧美日韩亚洲国产一区| 精品久久久久久久久中文字幕| 久久久国产在线视频| 2019国产精品自在线拍国产不卡| 国产成人av网址| 伊是香蕉大人久久| 国产不卡av在线免费观看| 成人精品久久av网站| 91sao在线观看国产| 日本一区二区三区四区视频| 国产精品久久久久久久久久久久久久| 亚洲xxx视频| 欧美人与物videos| 亚洲自拍偷拍色片视频| 欧美夫妻性生活xx| 一本大道久久加勒比香蕉| 久久精品视频亚洲| 亚洲一区二区三区视频播放| 在线播放日韩欧美| 亚洲国产美女久久久久| 久久综合国产精品台湾中文娱乐网| 青青精品视频播放| 中文字幕无线精品亚洲乱码一区| 成人免费视频网址| 亚洲国产欧美一区| 欧美另类第一页| 日韩精品在线观看一区二区| 性亚洲最疯狂xxxx高清| 成人高清视频观看www| 欧美激情啊啊啊| 日韩资源在线观看| 久久亚洲精品视频| www国产精品视频| 中文字幕日韩综合av| 成人网在线观看| 欧美性猛交xxxx| 色综合视频网站| 成人免费自拍视频| 欧美精品在线第一页| 亚洲人成电影网站色www| 国产精品扒开腿爽爽爽视频| 麻豆国产va免费精品高清在线| 亚洲午夜国产成人av电影男同| 88国产精品欧美一区二区三区| 成人免费看片视频| 国产一区二区三区丝袜| 亚洲成人在线视频播放| 91精品国产乱码久久久久久蜜臀| 97香蕉超级碰碰久久免费软件| 日韩欧美国产一区二区| 亚洲网址你懂得| 欧美另类精品xxxx孕妇| 在线观看日韩www视频免费| 成人免费午夜电影| 日本一区二区三区在线播放| 狠狠干狠狠久久| 成人黄色网免费|