1、出现 ANR 的情况
满足下面的一种情况系统就会弹出 ANR 提示
- 输入事件(按键和触摸事件) 5s 内没被处理;
- BroadcastReceiver 的事件 (
onRecieve()
方法) 在规定时间内没处理完 (前台广播为 10s,后台广播为 60s); - Service 前台 20s 后台 200s 未完成启动;
- ContentProvider 的
publish()
在 10s 内没进行完。
通常情况下就是主线程被阻塞造成的。
2、ANR 的实现原理
以输入无响应的过程为例(基于 9.0 代码):
最终弹出 ANR 对话框的位置是与 AMS 同目录的类 AppErrors
的 handleShowAnrUi()
方法。这个类用来处理程序中出现的各种错误,不只 ANR,强行 Crash 也在这个类中处理。
// base/core/java/com/android/server/am/AppErrors.java
void handleShowAnrUi(Message msg) {
Dialog dialogToShow = null;
synchronized (mService) {
AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj;
// ...
Intent intent = new Intent("android.intent.action.ANR");
if (!mService.mProcessesReady) {
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
| Intent.FLAG_RECEIVER_FOREGROUND);
}
mService.broadcastIntentLocked(null, null, intent,
null, null, 0, null, null, null, AppOpsManager.OP_NONE,
null, false, false, MY_PID, Process.SYSTEM_UID, 0 /* TODO: Verify */);
boolean showBackground = Settings.Secure.getInt(mContext.getContentResolver(