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