描述
我想正常人也不会去用这些类型的 Window Type 吧:TYPE_APPLICATION_ATTACHED_DIALOG
、TYPE_APPLICATION_PANEL
、TYPE_APPLICATION_SUB_PANEL
...
然而某个项目中用到的某个库因为某些 bug 需要利用这些特殊类型的 Window 做 workaround...
于是我尝试创建这些特殊类型的 Window:
override fun onStart() {
super.onStart()
windowManager.addView(
bigVideoFrontLayout,
WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
)
)
}
给我整了个原地爆炸:
android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
这就显得非常诡异,Activity 都 start 了你却告诉我它没有在 running ?
另外,假如我把上面那些特殊类型的 Window 换成普通的 TYPE_APPLICATION
,它是能够正常工作的(只不过不符合我的需求)。
那么,这究竟是怎么回事呢?
解决
这东西是真的难以面向搜索引擎编程,用这些特殊类型 Window 的人还是太少了,自己摸索了一下找到了原因和解决方案。记录一下来为你互联网的知识库做一点微小的贡献。
首先,日志真的没骗人,Activity 此时虽然 start 了但还谈不上 running。
这些特殊类型的 Window 依赖于 Activity 本身 attach 的 Window,但是在 onStart()
时 Activity 还没有 attached to Window ,而这就是问题所在,本质上是一个时序问题。
因此,解决它只需要将代码移动到 onAttachedToWindow()
中即可。
override fun onAttachedToWindow() {
super.onAttachedToWindow()
windowManager.addView(
bigVideoFrontLayout,
WindowManager.LayoutParams(
WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or
WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
)
)
}
此外,WindowManager.LayoutParams
本身也有个 token
属性,可以把 window.decorView.windowToken
之类的塞给它来方便调试(不过正常工作的时候并不需要给它赋值)。