导致ANR的情况有很多,如
Activity的UI在5秒内没有响应输入事件(例如,按键按下,屏幕触摸)–主要类型
在主线程频繁进行IO操作
BroadcastReceiver在10秒内没有执行完毕
Service在特定时间内(前台进程20秒内,后台进程是200秒,在ActiveServices.java设置)无法处理完成–小概率类型
看打印的话也可以知道大概是什么原因引起,如下
01-05 08:36:53.153 1626 1652 E ActivityManager: ANR in com.toptech.launcherkorea2 (com.toptech.launcherkorea2/.Launcher)
01-05 08:36:53.153 1626 1652 E ActivityManager: PID: 4274
01-05 08:36:53.153 1626 1652 E ActivityManager: Reason: Input dispatching timed out (Waiting because no window has focus but there is a focused application that may eventually add a window when it finishes starting up.)
01-05 08:36:53.153 1626 1652 E ActivityManager: Load: 10.03 / 3.93 / 1.44
01-05 08:36:53.153 1626 1652 E ActivityManager: CPU usage from 67322ms to 0ms ago:
01-05 08:36:53.153 1626 1652 E ActivityManager: 23% 1285/mediaserver: 9.1% user + 14% kernel / faults: 12024 minor 135 major
01-05 08:36:53.153 1626 1652 E ActivityManager: 15% 1626/system_server: 10% user + 5.1% kernel / faults: 36464 minor 762 major
.
.
01-05 08:36:53.153 1626 1652 E ActivityManager: +0% 4304/com.google.process.gapps: 0% user + 0% kernel
01-05 08:36:53.153 1626 1652 E ActivityManager: 80% TOTAL: 56% user + 17% kernel + 6% iowait + 0.4% softirq
01-05 08:36:53.153 1626 1652 E ActivityManager: CPU usage from 2059ms to 2577ms later:
01-05 08:36:53.153 1626 1652 E ActivityManager: 57% 4274/com.toptech.launcherkorea2: 47% user + 10% kernel / faults: 7027 minor 33 major
01-05 08:36:53.153 1626 1652 E ActivityManager: 52% 4274/.launcherkorea2: 45% user + 7.2% kernel
01-05 08:36:53.153 1626 1652 E ActivityManager: +0% 4367/Thread-280: 0% user + 0% kernel
01-05 08:36:53.153 1626 1652 E ActivityManager: +0% 4369/RenderThread: 0% user + 0% kernel
01-05 08:36:53.153 1626 1652 E ActivityManager: +0% 4371/Thread-283: 0% user +
01-05 08:36:53.195 1291 1662 E IPlayerImplClient: Send NOTIFY_CALLBACK
如上可知是com.toptech.launcherkorea2应用的Launcher类导致ANR,而且还能通过Reason描述知道具体的原因,但是要分析什么操作导致的,还需要分析traces.txt日志文件。
traces.txt日志文件分析
文件路径:/data/anr/traces.txt(只保留最后一次发生的ANR事件)
"main" prio=5 tid=1 Native
| group="main" sCount=1 dsCount=0 obj=0x73581518 self=0xab006958
| sysTid=4274 nice=0 cgrp=default sched=0/0 handle=0xf77dfb34
| state=S schedstat=( 0 0 0 ) utm=411 stm=28 core=3 HZ=100
| stack=0xff493000-0xff495000 stackSize=8MB
| held mutexes=
kernel: __switch_to+0x74/0x8c
kernel: futex_wait_queue_me+0xdc/0x16c
kernel: futex_wait+0xe4/0x234
kernel: do_futex+0x198/0x9e0
kernel: compat_SyS_futex+0x78/0x16c
kernel: cpu_switch_to+0x48/0x4c (_ZN17SkPNGImageEncoder8doEncodeEP9SkWStreamRK8SkBitmapRKbii11SkColorTypeR18png_color_8_struct+622)
native: #12 pc 0017dee5 /system/lib/libskia.so (_ZN17SkPNGImageEncoder8onEncodeEP9SkWStreamRK8SkBitmapi+200)
native: #13 pc 0008f2a1 /system/lib/libandroid_runtime.so (???)
native: #14 pc 00bdea6b /data/dalvik-cache/arm/system@framework@boot.oat (Java_android_graphics_Bitmap_nativeCompress__JIILjava_io_OutputStream_2_3B+158)
at android.graphics.Bitmap.nativeCompress(Native method)
at android.graphics.Bitmap.compress(Bitmap.java:1027)
at com.toptech.launcherkorea2.Launcher.creatGalleryInSdcard(Launcher.java:1627)
at com.toptech.launcherkorea2.Launcher.onCreate(Launcher.java:277)
at android.app.Activity.performCreate(Activity.java:6241)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1107)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2369)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2476)
at android.app.ActivityThread.-wrap11(ActivityThread.java:-1)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1344)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke!(Native method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:731)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:621)
线程名字(“main”),线程优先级(“prio=5”),线程id(“tid=1”),线程状态(Native),比较常见的状态还有Sleeping、Waiting;
从以上文件可以定位到
com.toptech.launcherkorea2.Launcher.creatGalleryInSdcard(Launcher.java:1627)
try {
FileOutputStream os = new FileOutputStream(defaultFile);
defaultBitmap.compress(CompressFormat.PNG, 100, os);
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
操作bitmap时出现ANR,在主线程进行耗时的操作,会影响到阻塞主线程,可以把这些操作放在新的线程执行,如下:
new Thread(new Runnable() {
public void run() {
try {
FileOutputStream os = new FileOutputStream(defaultFile);
defaultBitmap.compress(CompressFormat.PNG, 100, os);
os.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
如何避免ANR
1、避免在主线程进行复杂耗时的操作,特别是文件读取或者数据库操作;
2、避免频繁实时更新UI;
3、BroadCastReceiver 要进行复杂操作的的时候,可以在onReceive()方法中启动一个Service来处理;
4、避免在IntentReceiver里启动一个Activity,因为它会创建一个新的画面,并从当前用户正在运行的程序上抢夺焦点。如果你的应用程序在响应Intent广播时需要向用户展示什么,你应该使用Notification Manager来实现。
5、在设计及代码编写阶段避免出现出现同步/死锁或者错误处理不恰当等情况。