FileObserver捕獲ANR異常

Android中捕獲運行時異常,可以通過繼承UncaughtExceptionHandler來重寫uncaughtException方法。
可以捕獲ANR異常的開源庫目前比較好的是
ANR-WatchDog
其他的開源庫例如:
BlockCanary,SafeLooper
ANR-WatchDog是參考Android WatchDog機制(com.android.server.WatchDog.java)起個單獨線程向主線程發送一個變量+1操作,自我休眠自定義ANR的閾值,休眠過后判斷變量是否+1完成,如果未完成則告警。
但是無法保證能捕捉所有ANR,對閾值的設置直接影響捕獲概率。
后來項目中使用Bugly到監控ANR異常,通過反編譯jar包,發現ANR異常捕獲是通過FileObserver實現的。
當ANR發生的時候,通過監聽文件文件夾“data/anr/”的寫入情況,來判斷是否發生了ANR,如果監聽到data/anr/traces.txt文件寫入。說明有此時有ANR異常發生。

FileObserver

通過ActivityManager.getProcessesInErrorState();獲取當前進程的所有異常信息List.遍歷此列表,從中找到ActivityManager.ProcessErrorStateInfo對象的condition == 2 的Error。過濾掉其他非ANR異常。

過濾掉其他非ANR異常

然后過濾掉非本應用下的異常。


過濾掉非本應用下的異常

ProcessErrorStateInfo源碼:

/**
 * Information you can retrieve about any processes that are in an error condition.
 */
public static class ProcessErrorStateInfo implements Parcelable {
    /**
     * Condition codes
     */
    public static final int NO_ERROR = 0;
    public static final int CRASHED = 1;
    public static final int NOT_RESPONDING = 2;

    /**
     * The condition that the process is in.
     */
    public int condition;

    /**
     * The process name in which the crash or error occurred.
     */
    public String processName;

    /**
     * The pid of this process; 0 if none
     */
    public int pid;

    /**
     * The kernel user-ID that has been assigned to this process;
     * currently this is not a unique ID (multiple applications can have
     * the same uid).
     */
    public int uid;

    /**
     * The activity name associated with the error, if known.  May be null.
     */
    public String tag;

    /**
     * A short message describing the error condition.
     */
    public String shortMsg;

    /**
     * A long message describing the error condition.
     */
    public String longMsg;

    /**
     * The stack trace where the error originated.  May be null.
     */
    public String stackTrace;

    /**
     * to be deprecated: This value will always be null.
     */
    public byte[] crashData = null;

    public ProcessErrorStateInfo() {
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(condition);
        dest.writeString(processName);
        dest.writeInt(pid);
        dest.writeInt(uid);
        dest.writeString(tag);
        dest.writeString(shortMsg);
        dest.writeString(longMsg);
        dest.writeString(stackTrace);
    }

    public void readFromParcel(Parcel source) {
        condition = source.readInt();
        processName = source.readString();
        pid = source.readInt();
        uid = source.readInt();
        tag = source.readString();
        shortMsg = source.readString();
        longMsg = source.readString();
        stackTrace = source.readString();
    }

    public static final Creator<ProcessErrorStateInfo> CREATOR =
            new Creator<ProcessErrorStateInfo>() {
        public ProcessErrorStateInfo createFromParcel(Parcel source) {
            return new ProcessErrorStateInfo(source);
        }
        public ProcessErrorStateInfo[] newArray(int size) {
            return new ProcessErrorStateInfo[size];
        }
    };

    private ProcessErrorStateInfo(Parcel source) {
        readFromParcel(source);
    }
}

FileObserver捕獲ANR異常,缺點是Android5.0低權限應用不能監聽變化“、data/anr/traces.txt”,只能在root之后才可以。
詳細實現源碼:CrashHandler

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容