()ANR也算是比较常见的情况,虽然我们大多数可以把锅甩给用户的手机,但是有时候也有甩不动锅的时候
这篇博客的主题是教大家如何看ANR日志,然后就是分析ANR日志
一.预备工作
1.配置环境
配置环境,如果已经配置过的就跳过,在PC的在系统变量中path变量后面添加adb.exe的路径,我的路径是D:\Android\sdk\platform-tools
添加完之后用PC的cmd命令行窗口输入adb,会出现adb的版本号
但是AS还是不行,还需要将adb.exe 、AdbWinApi.dll、 AdbWinUsbApi.dll 三个文件拷贝至windows系的 C:\Windows\System 和 C:\Windows\System32文件夹中。
参考:android studio 'adb' 不是内部或外部命令,也不是可运行的程序_刘_sir的博客-CSDN博客
2.获取ANR日志
当手机出现ANR,就会在data/anr/traces.txt里添加相关记录。
在AS的 terminal 下通过adb命令拿到该文件:adb bugreport
,然后我们在项目的 FS\data\anr 目录下就可以看到了
二.分析日志
1.触摸事件ANR
首先我运行一个会产生ANR的代码,一看就知道这个属于触摸事件ANR
btn_one.setOnTouchListener { v, event ->
Thread.sleep(1000000)
false
}
因为一个日志文件包含了所有应用的ANR信息,所以我们要去找哪一个是我们想看的,因为最新的ANR会在最上面,所以也好找
注意这一句,它有我们的包名,所以可以断定这是我们想看的ANR信息
Cmd line: appupdate.bitpai.com.test
继续往下看,堆内存信息 22%空闲,这个应用堆内存总共分配了12MB
Heap: 22% free, 10MB/12MB; 40193 objects
然后我们往下翻,查看线程的信息,直到我们看见了下面这个,main指的是主线程,prio线程优先级,tid线程锁ID,sleeping指的是线程在休眠,因为我执行了sleep方法, ”
"main" prio=5 tid=1 Sleeping
不过还没完,下面的信息有一句提到了我写的代码,这个24指的是我那句sleep命令的位置
at appupdate.bitpai.com.test.MainActivity$onCreate$1.onTouch(MainActivity.kt:24)
虽然有点长,但是还是放出来一段,因为他说了我堵塞了那些代码的执行,因为onTouch是在dispatchTouchEvent里执行的,所以,有这一段是应该的
at java.lang.Thread.sleep(Thread.java:327)
at appupdate.bitpai.com.test.MainActivity$onCreate$1.onTouch(MainActivity.kt:24)
at android.view.View.dispatchTouchEvent(View.java:11784)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2974)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2604)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2974)
关于触摸事件ANR主要判断在于是否有相关 分发函数 在其中被卡住
2.Service onStartCommand执行超时
我启动一个service,因为无线循环的原因,会产生ANR
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int i=0;
boolean tag=true;
for(;tag;){
i=i+1;
}
return super.onStartCommand(intent, flags, startId);
}
看一下日志,主线程运行中,但是因为在onstart里执行半天都没结束,所以报ANR了
"main" prio=5 tid=1 Runnable
| group="main" sCount=0 dsCount=0 flags=0 obj=0x7302fa20 self=0x7f17ea3a00
| sysTid=10854 nice=-10 cgrp=default sched=0/0 handle=0x7f1cd649b0
| state=R schedstat=( 10991954159 32071357 850 ) utm=1088 stm=11 core=6 HZ=100
| stack=0x7fc2b17000-0x7fc2b19000 stackSize=8MB
| held mutexes= "mutator lock"(shared held)
at appupdate.bitpai.com.test.MyService.onStartCommand(MyService.java:20)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4151)
3.小结
虽然上面的两个例子通过 日志很快就可以知道 问题所在,但是具体到我们平常的ANR发生情况里,还是算比较简单的了。需要仔细盘查和大胆猜测
参考文章