异常分析之Toast引起BadTokenException
1、现象分析
-
在targetSdkVersion升级到26以上后,多出了很多BadTokenException异常,与Toast有关。
Crash堆栈.png
-
通过堆栈查看源码知道Toast是通过内部类TN的handleShow()方法来展示浮窗,而这个方式是可能会抛出WindowManager$BadTokenException异常的,PAI26之后Google对这个异常进行了捕获,但API26之前的并未作处理:
Toast$TN.handleShow().png
-
在API26之前(特别是26)的机器上有一个稳定复现的路径,在主线程调用Toast的show方法后,阻塞3s左右会抛出上面的BadTolenException异常并导致crash:
BadTokenException复现代码.png
2、解决方案
-
在API26之前,我们可以模仿Android8中Google针对这个异常的处理方式,通过反射自定义一个Handler的代理,使其捕获这个异常,从而保证应用不会因此crash。
自定义Handler.png
-
定义Handler的代理,用来对Toast中TN的Handler做一个封装
-
下面是通过反射的方式对Toast中TN的Handler做处理:
通过反射对Toast中TN的Handler做处理.png