Unable to add window -- token null is not for an application

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

最近有一个需求,就是在Service开启一个Dialog,简单,我就按照平常做Dialog的做法,自定义了Dialog,但是我运行的时候报了一个错误。

Unable to add window -- token null is not for an application_第1张图片

从字面上也很容易理解“BadTokenException: Unable to add window – token null is not for an application”,发生一个BadTokenException的异常,不能添加Window。
在解释这个问题前,有必要先理清一些概念:

Window: 定义窗口样式和行为的抽象基类,用于作为顶层的view加到WindowManager中,其实现类是PhoneWindow。
每个Window都需要指定一个Type(应用窗口、子窗口、系统窗口)。Activity对应的窗口是应用窗口;PopupWindow,ContextMenu,OptionMenu是常用的子窗口;像Toast和系统警告提示框(如ANR)就是系窗口,还有很多应用的悬浮框也属于系统窗口类型。

WindowManager:用来在应用与window之间的管理接口,管理窗口顺序,消息等。

WindowManagerService:简称Wms,WindowManagerService管理窗口的创建、更新和删除,显示顺序等,是WindowManager这个管理接品的真正的实现类。它运行在System_server进程,作为服务端,客户端(应用程序)通过IPC调用和它进行交互。

Token:这里提到的Token主是指窗口令牌(Window Token),是一种特殊的Binder令牌,Wms用它唯一标识系统中的一个窗口。

跟Activity对应的窗口一样,Dialog有一个PhoneWindow的实例。Dialog 的类型是TYPE_APPLICATION,属于应用窗口类型。
Dialog初化始时是通过Context.getSystemServer 来获取 WindowManager,而如果用Application或者Service的Context去获取这个WindowManager服务的话,会得到一个WindowManagerImpl的实例,这个实例里token也是空的。之后在Dialog的show方法中将Dialog的View(PhoneWindow.getDecorView())添加到WindowManager时会给token设置默认值还是null。

如果这个Context是Activity,则直接返回Activity的mWindowManager,这个mWindowManager在Activity的attach方法被创建,Token指向此Activity的Token,mParentWindow为Activity的Window本身。

就算用Application的Context也是调不起来的,也就是说要用一个Activity的Context才能调起这个Dialog,但是我需要的是在Service中调起来呢?

我们可以在Dialog中设置Dialog的类型,将它的属性改为系统窗口。如下图:

Unable to add window -- token null is not for an application_第2张图片

getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);或者是getWindow().setType(WindowManager.LayoutParams.TYPE_TOAST); 当你用SYSTEM_ALERT的时候,必须要给权限它。

Unable to add window -- token null is not for an application_第3张图片

权限:< uses-permission android:name=”android.permission.SYSTEM_ALERT_WINDOW” / >

若有不足的地方,请大家帮忙指出,谢谢大家来观看。

你可能感兴趣的:(安卓开发)