天天看點

未捕獲的全局異常UncaughtExceptionHandler

程式中的未捕獲的全局異常的捕獲(單例)
/ *
 * 1.當出現未捕獲的異常時,能夠給使用者一個相對友好的提示
 * 2.在出現異常時,能夠将異常資訊發送給背景,便于在後續的版本中解決bug
 */
public class CrashHandler implements Thread.UncaughtExceptionHandler {

    //系統預設的處理未捕獲異常的處理器
    private Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    //單例模式:(懶漢式)
    //本身執行個體化未捕獲異常的處理器的操作就是系統在一個單獨的線程中完成的,所有不涉及到
    //多線程的問題,是以使用懶漢式更好!
    private CrashHandler(){

    }

    private static CrashHandler crashHandler = null;
    public static CrashHandler getInstance(){
        if(crashHandler == null){
            crashHandler = new CrashHandler();
        }
        return crashHandler;
    }


    public void init(){
        defaultUncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
        //将目前類設定為出現未捕獲異常的處理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    //一旦系統出現未捕獲的異常,就會調用如下的回調方法
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {

//        Log.e("TAG", "出現了未捕獲的異常了!" + ex.getMessage());
        new Thread(){
            public void run(){
                //prepare()和loop()之間的操作就是在主線程中執行的!
                //在android系統中,預設情況下,一個線程中是不可以調用Looper進行消息的處理的。除非是主線程
                Looper.prepare();
                Toast.makeText(UIUtils.getContext(), "親,出現了未捕獲的異常了!", Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();
        //收集異常資訊
        collectionException(ex);

        try {
            Thread.sleep(2000);

            //移除目前activity
            ActivityManager.getInstance().removeCurrent();
            //結束目前的程序
            android.os.Process.killProcess(android.os.Process.myPid());
            //結束虛拟機
            System.exit(0);

        } catch (InterruptedException e) {
            e.printStackTrace();
        }


    }

    private void collectionException(Throwable ex){
        final String exMessage = ex.getMessage();
        //收集具體的客戶的手機、系統的資訊
        final String message = Build.DEVICE + ":" + Build.MODEL + ":" + Build.PRODUCT + ":" + Build.VERSION.SDK_INT;

        //發送給背景此異常資訊
        new Thread(){
            public void run(){
                //需要按照指定的url,通路背景的sevlet,将異常資訊發送過去
                Log.e("TAG", "exception = " + exMessage);
                Log.e("TAG", "message = " + message);
            }
        }.start();

    }
}