安卓全局異常捕獲,異常崩潰處理


開發安卓的小伙伴都遇到過APP突然崩潰,無響應的情況.如果發生在自己手中,那么還可以通過IDE查看錯誤日志,但是實際都是發生在用戶手中,那么這個時候產生崩潰,無響應ANR異常就很麻煩.無從下手.因此,需要全局異常捕獲.也就是對未知異常,程序員沒有處理的異常進行處理,記錄等便於分析查找原因.

首先,新建一個類 MyCatchException.Java

package com.linfeng.activity;

import android.content.Context;
import android.os.Looper;
import android.util.Log;
import android.widget.Toast;

import com.linfeng.util.Util;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;

/**
 * Created by Linfeng on 2019/05/14.
 */
//全部錯誤捕捉器
public class MyCatchException implements Thread.UncaughtExceptionHandler {
    //本類實例
    private static MyCatchException mInstance;
    //系統默認的uncatchException
    private Thread.UncaughtExceptionHandler mDefaultException;

    private Context mContext;

    //保證只有一個實例
    public MyCatchException() {
    }

    //單例模式
    public static MyCatchException getInstance() {
        if (mInstance == null) {
            mInstance = new MyCatchException();
        }
        return mInstance;
    }

    //獲取系統默認的異常處理器,並且設置本類為系統默認處理器
    public void init(Context ctx) {
        this.mContext = ctx;
        mDefaultException = Thread.getDefaultUncaughtExceptionHandler();
        Thread.setDefaultUncaughtExceptionHandler(this);
    }

    //自定義錯誤處理器
    private boolean handlerException(Throwable ex) {
        if (ex == null) {  //如果已經處理過這個Exception,則讓系統處理器進行后續關閉處理
            return false;
        }

        //獲取錯誤原因
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause!=null){
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        final String msg= result ;

        new Thread() {
            public void run() {
                // Toast 顯示需要出現在一個線程的消息隊列中
                Looper.prepare();
                Toast.makeText(mContext, "程序出錯:" + msg.toString(), Toast.LENGTH_LONG).show();
               //將異常記錄到本地的數據庫或者文件中.或者直接提交到后台服務器
                Util.writeLog("全局異常",msg);
                Looper.loop();
            }

            ;
        }.start();
        return true;
    }

    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        if (!handlerException(ex) && mDefaultException != null) {
            // 如果用戶沒有處理則讓系統默認的異常處理器來處理
            mDefaultException.uncaughtException(thread, ex);
        } else { //否則自己進行處理
            try {  //Sleep 來讓線程停止一會是為了顯示Toast信息給用戶,然后Kill程序
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Util.writeLog("全局異常",e.getMessage());
                Log.d("2635", "uncaughtException: "+e.getMessage());
            }catch (Exception e){
                Util.writeLog("全局異常",e.getMessage());
                Log.d("2635", "Exception: "+e.getMessage());
            }
            //如果不關閉程序,會導致程序無法啟動,需要完全結束進程才能重新啟動
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(10);
        }

    }
}

然后在APP的application中注冊,但是由於一般application都可能用了,或者不方便修改.一般采用在APP的第一個Activity中進行注冊,那么我這里在我第一個Activity,也就是SplashActivity頁面的onCreate方法中添加這兩句代碼

        MyCatchException mException=MyCatchException.getInstance();
        mException.init(getApplicationContext());  //注冊

這樣就完成了,當我們app有沒有處理的異常時,就會自動幫我們捕獲異常.可以做一個測試.

比如,在MainActivity中隨便拋出一個異常,比如數組越界,空指針異常等去測試是否能捕獲這個異常.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM