为什么会写这篇文章?
那得从那个寒夜森森的夜晚说起了,正当俺们愉快玩耍的时候,测试同事在群里发了一条大家都不愿在这个节骨眼看到的消息~"XXX应用无响应。要将她关闭吗?";
心中无数个T的坑,怎么会这样?就在数小时之前才发完版上线,还没稳定一整晚,就开始唱反调了。这能忍?当然不能!扯远了....当晚心想着既然已经发生了,等天亮暖和了再去解决掉她吧,于是第二天信誓旦旦的打开电脑,拷贝traces.txt文件(方法:adb pull /data/anr/traces.txt /Users/atom/Downloads/),打开一看,吓得小弟弟都快掉了,竟然没有昨晚的日志信息,这是怎么回事?原来是Androd自己干的好事。当发生ANR时,系统会将相应的堆栈信息记录在/data/anr/traces.txt文件中,且只会保留最后一次发生ANR时的traces信息...当场就吓尿了,这可如何是好?没法安心过年玩火炮了,不对,是鞭炮!正当俺几经"绝望"时,出现了转机,无意间看到了之前阅过的干货。看到了DropBox,顿时眼前一亮,由此产生了这篇文章。不过由于笔者技术及文笔有限,文章中大量引用了参考资料的文字描述,待有所提高之后,再回来修改修改吧。好了,下面进入正题,希望对大家有所帮助。
网络上关于ANR的种种神秘已经被大家解析得差不多了,这里我就来说说容易被大家忽略的地方,那就是Android traces.txt文件只保留最后一次发生ANR时的traces信息,那么以前的traces信息就丢失了么?答案当然是否定了,不然接下来怎么收场~
这位常常被大家遗忘的主角就是:DropBox
1.DropBox
1.1 历史渊源
为了增强Android的异常信息收集管理能力,从2.2开始增加了DropBox功能。
DropBox(简称DB)是系统进程中的一个服务,在system_server进程启动时创建,并且它没有运行在单独的线程中,而是运行在system_server的ServerThread线程中。我们可以将ServerThread称作system_server的主线程,ServerThread线程除了启动并维护各个服务外,还负责检测一些重要的服务是否死锁。DB被创建的代码如下。
SystemServer.java → ServerThread.run()
Slog.i(TAG, "DropBox Service");
ServiceManager.addService(Context.DROPBOX_SERVICE, //服务名称为“dropbox”
new DropBoxManagerService(context, new File("/data/system/dropbox")));
2. DropBoxManagerService
DropBoxManagerService(简称DBMS)就是DB服务的本尊,它的主要功能接口包括以下几个函数:public void add(DropBoxManager.Entryentry)
DBMS将所有要添加的日志都用DropBoxManager.Entry类型的对象表示,通过add函数添加,并且直到目前为止一个Entry对象对应着一个日志文件。public boolean isTagEnabled(String tag)
通过给每一个Entry设置一个tag可以标识不同类型的日志,并且可以灵活的启用/禁用某种类型的日志,isTagEnabled用来判断指定类型的日志是否被启用/禁用了,一旦禁用就不会再记录这种类型的日志。默认是不禁用任何类型的日志的。稍后说明如何启用/禁用日志。public synchronized DropBoxManager.Entry getNextEntry(String tag, long millis)
我们可以通过getNextEntry函数获取指定类型和指定时间点之后的第一条日志,要使用这个功能应用程序需要有“android.permission.READ_LOGS”的权限,并且在使用完毕返回的Entry对象后要调用其close函数确保关闭日志文件的文件描述符(如果不关闭的话可能造成进程打开的文件描述符超过1024而崩溃,Android中限制每个进程的文件描述符上限为1024)。
DBMS提供了很多的配置项用来限制对磁盘的使用,通过SettingsProvider应用程序维护,数据存放在其settings.db数据库中。这些配置项也都有默认值,罗列如下:
- Settings.Secure.DROPBOX_AGE_SECONDS = "dropbox_age_seconds"
- Settings.Secure.DROPBOX_MAX_FILES = "dropbox_max_files"
- Settings.Secure.DROPBOX_QUOTA_KB = "dropbox_quota_kb"
- Settings.Secure.DROPBOX_QUOTA_PERCENT = "dropbox_quota_percent"
- Settings.Secure.DROPBOX_RESERVE_PERCENT = "dropbox_reserve_percent"
- Settings.Secure.DROPBOX_TAG_PREFIX = "dropbox:"
功效:应用程序可以利用DropBox来做事情,收集日志等