博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android悬浮窗服务卡死,Android 悬浮窗兼容问题谈
阅读量:1533 次
发布时间:2019-04-21

本文共 4294 字,大约阅读时间需要 14 分钟。

悬浮窗应该算各大厂商最先开始对应用下手的地方。

悬浮窗之所以讨人厌同样是因为被滥用,就像狗皮膏药一样贴在屏幕的上下左右,不管切换到哪个应用始终显示在最上层。悬浮窗的需求有点从电脑端延续的味道,以前桌面上经常跑出来个狮子,有个悬浮球,或者歌词。但那个时候占用桌面面积小,相比手机屏幕尺寸,现在的悬浮窗很容易覆盖住真正内容。那Android上面悬浮窗最初设计是想解决什么问题呢?

悬浮窗也即一个Window。Window Type有很多种,比如TYPE_PHONE,TYPE_TOAST,TYPE_SYSTEM_ALERT等,用在来电,低电量显示,状态栏,短暂toast提醒等。Android系统给每一种Window类型定义了一个高度,依次从上往下显示。官方文档描述是这样的:

<img src="https://pic2.zhimg.com/v2-467a286945b81153f80c99603d7c8555_b.png" data-rawwidth="599" data-rawheight="358" class="origin_image zh-lightbox-thumb" width="599" data-original="https://pic2.zhimg.com/v2-467a286945b81153f80c99603d7c8555_r.png"> 下面这些值是系统定义的window类型,他们不是给普通应用用的。

6924484b3018dc1d3e624e0338afdf53.png 下面这些值是系统定义的window类型,他们不是给普通应用用的。

既然不是预定义给应用用的,为啥应用能用呢?

<img src="https://pic1.zhimg.com/v2-bcb54ba3add46c2995452759502795bc_b.png" data-rawwidth="469" data-rawheight="629" class="origin_image zh-lightbox-thumb" width="469" data-original="https://pic1.zhimg.com/v2-bcb54ba3add46c2995452759502795bc_r.png"> 从源码来看(摘自4.4版本,6.0以后版本权限管理更加严格),TYPE_TOAST的注释表明似乎是一段未写完的代码。而像TYPE_PHONE这类则是需要SYSTEM_ALERT_WINDOW权限,在6.0之前这是非常容易获取到的,只要在Manifest里面申明下即可。6.0以后需要运行时动态申请这个权限,申请方式跟普通的地理位置权限还不太一样,如下的方式:

76ebaf228d3b2c21192e87ab891cf865.png 从源码来看(摘自4.4版本,6.0以后版本权限管理更加严格),TYPE_TOAST的注释表明似乎是一段未写完的代码。而像TYPE_PHONE这类则是需要SYSTEM_ALERT_WINDOW权限,在6.0之前这是非常容易获取到的,只要在Manifest里面申明下即可。6.0以后需要运行时动态申请这个权限,申请方式跟普通的地理位置权限还不太一样,如下的方式:

if (!Settings.canDrawOverlays(MainActivity.this)) {

Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:" + getPackageName()));

startActivityForResult(intent, 10);

}

复制代码

为什么TYPE_TOAST不需要权限仍然不得而知。事实上从某一次跟官方的现场交流会上,官方人员也承认悬浮窗事实上也不是设计给应用用的。而且当他们惊讶的发现国内市场悬浮窗的需求如此强大之后,他们做了一件惊人的改变:就是在Android O上面针对国内市场悬浮窗需求特别修改了悬浮窗的设计。

<img src="https://pic1.zhimg.com/v2-52dee01583cab2048edb02329fbee064_b.png" data-rawwidth="750" data-rawheight="432" class="origin_image zh-lightbox-thumb" width="750" data-original="https://pic1.zhimg.com/v2-52dee01583cab2048edb02329fbee064_r.png"> 在Android O上面特别增加了TYPE_APPLICATION_OVERLAY来满足悬浮窗需求。需要注意的是即使你的应用TargetSdk不是等于O版本,可以继续使用TYPE_PHONE(O版本已废弃),但会显示在TYPE_APPLICATION_OVERLAY下面(所以想要显示在最上面要尽快适配O版本)。在使用TYPE_APPLICATION_OVERLAY的时候,系统还会进行提示是否允许该应用显示悬浮窗。

7baca7f0f12aa2cf0e2db58bf07429bf.png 在Android O上面特别增加了TYPE_APPLICATION_OVERLAY来满足悬浮窗需求。需要注意的是即使你的应用TargetSdk不是等于O版本,可以继续使用TYPE_PHONE(O版本已废弃),但会显示在TYPE_APPLICATION_OVERLAY下面(所以想要显示在最上面要尽快适配O版本)。在使用TYPE_APPLICATION_OVERLAY的时候,系统还会进行提示是否允许该应用显示悬浮窗。

悬浮窗在国内的市场环境下有几个问题:

6.0以下即使Manifest里面定义了,也会被厂商自己扩展出来的悬浮窗开关默认禁掉

TYPE_TOAST在MIUI等机器上面被当做等同于TYPE_PHONE需要SYSTEM_ALERT_WINDOW权限

开发者需要做的事情:

优先使用TYPE_TOAST,但需要注意4.4版本之前无法接收事件也即无法交互以及MIUI问题。

6.0及以后使用动态权限申请一般不会有问题,6.0之前可以根据机型动态下发权限打开页面的路径,来做到提醒用户去打开权限。尽可能引导用户,否则就等着来反馈为啥显示不了。

留意Android O对悬浮窗做出的重大修改对自己造成的影响

TYPE_TOAST在7.1版本上面还有一些小修改,一个uid只能加一个;曾经比较流行将Toast作为一个单例,隐藏toast的时候修改view的visibility为gone来替换removeView,然后通过不断setText和setVisibility为VISIBILE来实现Toast内容快速切换(原生Toast必须要等duration时长消失后再出现下一个)。使用这种方式在7.1版本上面会出现问题,该版本上面在应用失去焦点的时候会有个定时器自动隐藏掉这个Toast Window,setText和setVisibility无法恢复显示这个Window了。

<img src="https://pic1.zhimg.com/v2-f581b898818b1ddfd6ccca2565ec4770_b.png" data-rawwidth="578" data-rawheight="444" class="origin_image zh-lightbox-thumb" width="578" data-original="https://pic1.zhimg.com/v2-f581b898818b1ddfd6ccca2565ec4770_r.png">

44c6d703367426fbac81cf6c76dd2c6e.png<img src="https://pic1.zhimg.com/v2-7bda4ec729a2a6d055e428418c8d4194_b.png" data-rawwidth="608" data-rawheight="257" class="origin_image zh-lightbox-thumb" width="608" data-original="https://pic1.zhimg.com/v2-7bda4ec729a2a6d055e428418c8d4194_r.png">

6a8c73e9a9e99599c78018a2ee1fe8b2.png<img src="https://pic1.zhimg.com/v2-48f2bba37362efddf88f0cd80ce4fe60_b.png" data-rawwidth="687" data-rawheight="309" class="origin_image zh-lightbox-thumb" width="687" data-original="https://pic1.zhimg.com/v2-48f2bba37362efddf88f0cd80ce4fe60_r.png">

f9ec013d54e0774ed2c2955a8f66c49a.png<img src="https://pic4.zhimg.com/v2-cf3c6f23b9cd78d086987970d02f3abf_b.png" data-rawwidth="532" data-rawheight="304" class="origin_image zh-lightbox-thumb" width="532" data-original="https://pic4.zhimg.com/v2-cf3c6f23b9cd78d086987970d02f3abf_r.png"> WindowManagerService里面有两处判断焦点失去之后起定时器隐藏Toast Window。我们可以显示removeView之后再addView来进行兼容。

7ccb0685da7b6566ce509575074f05df.png WindowManagerService里面有两处判断焦点失去之后起定时器隐藏Toast Window。我们可以显示removeView之后再addView来进行兼容。

更多文章和互动请关注微信公众号:anzhuozhimei

转载地址:http://vxydy.baihongyu.com/

你可能感兴趣的文章
第一个linux 驱动
查看>>
Boss直聘招聘信息爬取
查看>>
OpenCV 纵向、横向拼接图片
查看>>
tkinter 点击退出执行的程序
查看>>
python在windows和linux环境的进程支持对比
查看>>
激活函数(激励函数)理解总结
查看>>
池化层的作用
查看>>
检测视频或摄像头中的目标
查看>>
Python非线性回归-武汉疫情确诊、疑似、死亡、治愈人数预测
查看>>
Unet结构原理
查看>>
【语义分割】批量制作多类语义分割数据集
查看>>
循环神经网络RNN与LSTM--基础知识
查看>>
00Python预习
查看>>
01Python字符串/列表/元组
查看>>
03Python函数/对象的方法
查看>>
02布尔表达式/条件判断
查看>>
04格式化字符串与循环+注释
查看>>
05文件的读写+字典
查看>>
思考题1:根据日志计算同类型文件的大小
查看>>
思考题2:根据数据库记录,输出学生课程签到记录
查看>>