背景
由于Launcher卡片是用WindowManager. addView(card)的方式,添加到屏幕上(卡片是系统窗口),这导致与其他系统弹窗(激活对话框、输入法对话框等)的显示层级会发生冲突。具体现象如下:
明确问题
根据需求文档,期望的各个浮窗的层级定义如下: 期望层级: 实际层级: 从上面明确问题过程中,可以推导出:如果能降低Launcher卡片的显示层级。即降低到和地图一样的层级,使得卡片的生命周期能跟随地图Activity一致,随地图显示和隐藏,则可以让其他对话框都浮在Launcher卡片上面。即做成地图Activity上的一个PopupWindow。
对策
临时措施
- 导航在pause的时候,隐藏卡片。
- 导航在输入法弹起来的时候,隐藏卡片。
永久措施
方案一:直接添加应用层窗口, 需要获取导航进程的token。 方案二:导航以AAR的方式集成卡片。需要调整launcher其他模块和卡片的通信方案,改动比较大。 方案三:launcher留出容器,加载导航的activity。
临时方案都可能导致其他问题,综合考量,选择了侵入性小的永久实施方案一: Launcher卡片SDK提供AIDL接口,导航通过这个接口,把它的activity的token传到Launcher进程来,Launcher以wm.addView()的方式,把window token设置这个acitivityToken,就可以把卡片显示成地图的子窗口了。 [This type of content is unavailable for download at the moment.] 获取activity的token代码如下:
测试效果:
总结
解决问题过程中,最关键的是明确问题,发现问题的规律。这里就是卡片层级问题。当发现用activity级别的window type时, 会报bad token的异常,可推导出系统添加window需要一个token。查看源码发现token就是一个binder对象,所以我们可以把地图activity的token通过binder通信传递到Launcher这边来。
|