Unable to add window -- token android.os.BinderProxy@8c05554 is not valid; is your activity running?
android.view.ViewRootImpl.setView(ViewRootImpl.java:679)
常见的问题解析:
该异常表示不能添加窗口,通常是所要依附的view已经不存在导致的。
[解决方案]:
Dialog&AlertDialog,WindowManager不能正确使用时,经常会报出该异常,原因比较多,几个常见的场景如下:
1.上一个页面没有destroy的时候,之前的Activity已经接收到了广播。如果此时之前的Activity进行UI层面的操作处理,就会造成crash。UI层面的刷新,一定要注意时机,建议使用set_result来代替广播的形式进行刷新操作,避免使用广播的方式,代码不直观且容易出错。
2.Dialog在Actitivty退出后弹出。在Dialog调用show方法进行显示时,必须要有一个Activity作为窗口的载体,如果Activity被销毁,那么导致Dialog的窗口载体找不到。建议在Dialog调用show方法之前先判断Activity是否已经被销毁。
3.Service&Application弹出对话框或WindowManager添加view时,没有设置window type为TYPE_SYSTEM_ALERT。需要在调用dialog.show()方法前添加dialog.getWindow().SetType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT)。
4.6.0的系统上, (非定制 rom 行为)若没有给予悬浮窗权限, 会弹出该问题, 可以通过Settings.canDrawOverlays来判断是否有该权限. 5.某些不稳定的MIUI系统bug引起的权限问题,系统把Toast也当成了系统级弹窗,android
6.0的系统Dialog弹窗需要用户手动授权,若果app没有加入SYSTEM_ALERT_WINDOW权限就会报这个错。需要加入给app加系统Dialog弹窗权限,并动态申请权限,不满足第一条会出现没权限闪退,不满足第二条会出现没有Toast的情况。
而我这里要讲的不是普通的BadTokenException异常,而是在系统7.1上由Toast类中报出的异常。如果你遇到异常与下面的一致,而且实在Android7.1上发生的,按照https://github.com/drakeet/ToastCompat这里的解决办法(需要封装下Toast),就一定可以解决这个问题。
详细bug日志如下:
1 android.view.ViewRootImpl.setView(ViewRootImpl.java:679) | |
2 android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342) | |
3 android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93) | |
4 android.widget.Toast$TN.handleShow(Toast.java:459) | |
5 android.widget.Toast$TN$2.handleMessage(Toast.java:342) | |
6 android.os.Handler.dispatchMessage(Handler.java:102) | |
7 android.os.Looper.loop(Looper.java:154) | |
8 android.app.ActivityThread.main(ActivityThread.java:6121) | |
9 java.lang.reflect.Method.invoke(Native Method) | |
10 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:912) | |
11 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:802) |
这个问题百度了很久都没有找到对应的解决办法,最后在谷歌上找到了,特意贴出来,帮助那些同样遇到此问题的人。
出现这个异常的原因:
在Android API25中,即系统7.1上,Toast类的handleShow(IBinder windowToken)方法添加了一个参数,但是他会抛出异常,而且不管你传给Toast的上下文是Activity、ApplicationContext、还是Service,都无法避免这个异常。这一点在API26中有给出说明,API26版本中给mWM.addView(mView, mParams)添加了try-catch,用于捕获改异常。说明如下:
// Since the notification manager service cancels the token right
// after it notifies us to cancel the toast there is an inherent
// race and we may attempt to add a window after the token has been
// invalidated. Let us hedge against that.
地址:https://github.com/square/leakcanary/issues/844
解决办法,原文中已经有人给出了Toast的封装类:https://github.com/drakeet/ToastCompat