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捕获ANR异常》 FileObserver

通过ActivityManager.getProcessesInErrorState();获取当前进程的所有异常信息List.遍历此列表,从中找到ActivityManager.ProcessErrorStateInfo对象的condition == 2 的Error。过滤掉其他非ANR异常。

《FileObserver捕获ANR异常》 过滤掉其他非ANR异常

然后过滤掉非本应用下的异常。

《FileObserver捕获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

    原文作者:Calllanna
    原文地址: https://www.jianshu.com/p/a1a27619b0ef
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞