场景:
一般在使用Toast和Dialog时候,展示的时候发生异步,展示之前,主线程消息耗时过多导致服务端(SystemService)判断超时或Dialog依赖的Activity被销毁后,发生异常。
App中遇到另一类BadTokenException问题,在App比较大的工程发生较多。
腾讯bugly抓到
Token场景
Token,全局唯一,整个系统去识别和管理。token并不是客户端进程生成的。那就是服务端产生的。
启动Activity之前系统端AMS创建ActivityRecord,构造函数内部实例化了一个Token,保证了唯一性,Activity在AMS端唯一标识,基于这个唯一标识进行信息同步和区分。服务端AMS通知客户端实例化Activity的过程。
image.png
image.png
问题分析:从进程崩溃可知,主线程创建Activity(LaunchActivity),此时主线程消息队列所有消息被Block,没有机会执行onDestroy,可能系统向客户端进程发送了scheduleDestroy之后,触发了TimeOut,从而强制触发了Destroy操作并将WindowToken移除。
受限于系统对App管理,无法从App层获取系统event日志。
问题分析
当进程启动一段时间后,并处于后台/前台,如来电/语音电话/Home键。
解决方案
Activity第一次执行onResume时,判断是否处于后台以及本次onCreate到onResume时长是否过长,一定概率触发异常;在Activity的onResume调用结束,判断消息队列是否已经存在当前Activity的H.DESTROY_ACTIVITY,如果有该消息,则说明AMS已经将WMS缓存的windowToken移除,客户端主动调用finish接口,可解决。
通用方案:ActivityManager去监听willActivityBevisible调用,当前Token在服务AMS是否存在;如果不存在则AMS/WMS已经销毁当前Activity的Token对象。主动调用finish,之后addView不要执行。
网友评论