今天在测试app的时候,发现有一个地方一直在报ANR,没有定位到具体代码。
通过网上资料写了一个方法,去监听代码里面超时的地方,抛出异常进行定位。
具体如下:
public class ANRWatchDog extends Thread {
public static final int MESSAGE_WATCHDOG_TIME_TICK = 0;
/**
* 判定Activity发生了ANR的时间,必须要小于5秒,否则等弹出ANR,可能就被用户立即杀死了。
*/
public static final int ACTIVITY_ANR_TIMEOUT = 2000;
private static int lastTimeTick = -1;
private static int timeTick = 0;
private Handler watchDogHandler = new android.os.Handler() {
@Override
public void handleMessage(Message msg) {
timeTick++;
timeTick = timeTick % Integer.MAX_VALUE;
}
};
@Override
public void run() {
while (true) {
watchDogHandler.sendEmptyMessage(MESSAGE_WATCHDOG_TIME_TICK);
try {
Thread.sleep(ACTIVITY_ANR_TIMEOUT);
} catch (InterruptedException e) {
e.printStackTrace();
}
//如果相等,说明过了ACTIVITY_ANR_TIMEOUT的时间后watchDogHandler仍没有处理消息,已经ANR了
if (timeTick == lastTimeTick) {
throw new ANRException();
} else {
lastTimeTick = timeTick;
}
}
}
public class ANRException extends RuntimeException {
public ANRException() {
super("应用程序无响应,快来改BUG啊!!");
Thread mainThread = Looper.getMainLooper().getThread();
setStackTrace(mainThread.getStackTrace());
}
}
}
然后在的Application中将该类初始化。
系统内存在超时的地方,就会抛出异常,并帮你定位。
我的情况是在使用友盟统计的时候,在Activity中调用onKillProcess这个方法。
onKillProcess是在app内杀死进程的时候(如 Process.kil,System.exit)进行调用的方法,主要是保存一些页面调用的数据。正常的应用是不需要调用此方法的。因为保存的时候耗时太长,所以ANR了。
所以在使用onKillProcess的时候切忌,使用在正确的位置。