当前位置:首页 » Android开发技术

Android Crash解决方案之android.view.WindowManager$BadTokenException

2016-07-05 10:27 本站整理 浏览(16)

【崩溃堆栈】:

android.view.WindowManager$BadTokenException: Unable to add window -- token null is not for an application

at android.view.ViewRootImpl.setView(ViewRootImpl.java:543)

at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:259)

at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)

at android.app.Dialog.show(Dialog.java:286)

at android.app.AlertDialog$Builder.show(AlertDialog.java:951)

at bugrpt.test.CrashCase.showDialog(CrashCase.java:104)

at bugrpt.test.CrashCase.signalCrash(CrashCase.java:126)

at com.example.crash.MainActivity$9.onClick(MainActivity.java:231)

at android.view.View.performClick(View.java:4438)

at android.view.View$PerformClick.run(View.java:18422)

at android.os.Handler.handleCallback(Handler.java:733)

at android.os.Handler.dispatchMessage(Handler.java:95)

at android.os.Looper.loop(Looper.java:136)

at android.app.ActivityThread.main(ActivityThread.java:5045)

at java.lang.reflect.Method.invokeNative(Native Method)

at java.lang.reflect.Method.invoke(Method.java:515)

at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)

at dalvik.system.NativeStart.main(Native Method)

【崩溃代码与现象】:

其中,mContext由getApplicationContext()得到。

【Bug分析】:

在分析该错误之前,我们先看下AlertDialog.Builder的函数原型,如下:

参数为Context类型,根据上面的代码,传入的也是Context类型参数,貌似没有什么问题。其实不然,getApplicationContext()获得的context为整个应用的上下文,而对于AlertDialog来说,是需要依赖一个View,而View是对应于Activity的。所以,一般传入应该为Acitivity.this。

另外,下面几种情况也会引起该异常,分别如下:

A、在activity的oncreate方法中使用popupwindow出现以下错误:

异常:

android.view.WindowManager$BadTokenException: Unable to add window --token null is not valid; is your activity running?

错误代码如下:

pop = new PopupWindow(pop_view,320,250);

pop.showAtLocation(parent, Gravity.TOP,0, 0);

解决方法:

在控件渲染未完成前,就调用了pop.showAtLocation(parent, Gravity.TOP,0, 0)方法。

B、dialog.show()引起的android.view.WindowManager$BadTokenException错误:

异常:

android.view.WindowManager$BadTokenException: Unable to add window -- token android.os.BinderProxy@427b7270 is not valid; is your activity running?

错误原因:

Dialog在show的时候必须要有一个activity作为窗口载体,但是承载Dialog的activity已经被销毁了,不存在了,所以报上面的异常。

【解决方案】

针对上面引起异常的不同情况,下面分别说明:

本案例异常的解决方案:

对AlertDialog来说,需要依赖一个View,而View是对应于Activity的。所以,一般传入应该为Acitivity.this,即Activity自身context。

其他案例:

A、对于未渲染完成,就调用了showAtLocation方法的解决方案:

1、移到事件中(比如一个button的click事件中);

2、移到子线程中;另起一线程,在线程中不断循环,直到判断控件是否渲染完毕(如长宽大于0),不推荐。。。

3、移到重写的控件(parent)中,在控件ondraw()完后生成pop。

4、或者采用有如下的方案,原理为:当activity获得焦点之后,activity是加载完毕的了。其中showPopupWindow(getApplicationContext())是自己定义的专门显示popupwindow的一个函数。

B、对于Dialog调用已经销毁的activity的解决方案:

在show之前加判断activity是否被销毁了,如下:

if(!isFinishing()){

dialog.show();

}