👉关于作者
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣 !!!
专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
有什么需要欢迎私我,交流群让学习不再孤单。
👉前提
WindowManager 悬浮窗大家应该经常用了,在这咱不说他的具体实现,也不谈他的源码分析。
主要探讨权限适配,层级介绍,还有可能的Bug。
网络异常,图片无法展示
|
👉实践过程
😜层级
悬浮层本质上是将view送给WindowManager去玩,它将view设置不同类型,也就有了不同的层级(z轴)展示,不一样的价钱不一样的服务。
总体来说有应用窗口(APPLICATION_WINDOW)、子窗口(SUB_WINDOW)、系统窗口(SYSTEM_WINDOW)三种类型,应用窗口z轴范围是1~99,子窗口的范围是1001~1999,系统窗口是(2000~2999)。
来做个全套:
网络异常,图片无法展示
|
网络异常,图片无法展示
|
网络异常,图片无法展示
|
😜Android版本7.1.1以上
除了TYPE_TOAST之外都需要申请悬浮窗的权限,否则出现:
android.view.WindowManager$BadTokenException: Unable to add window android.view.ViewRootImpl$W@8d2124d -- permission denied for this window type at android.app.ActivityThread.handleCreateService(ActivityThread.java:2887) at android.app.ActivityThread.-wrap4(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1427) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:148) at android.app.ActivityThread.main(ActivityThread.java:5417) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 复制代码
以为申请权限就了事了? 不可能,还有:
android.view.WindowManager$BadTokenException: Unable to add window -- window android.view.ViewRootImpl$W@363f7b1 has already been added at android.view.ViewRootImpl.setView(ViewRootImpl.java:691) at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:342) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:94) at android.widget.Toast$TN.handleShow(Toast.java:434) at android.widget.Toast$TN$2.handleMessage(Toast.java:345) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6119) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 复制代码
Android官方版本升级对这块权限做了不小的调整,google对其进行了管控,防止滥用应用悬浮窗造成各种干扰,影响体验。
😜解决问题
- 申请悬浮窗权限,或者使用层级较低的TYPE_PHONE悬浮窗。
if (Build.VERSION.SDK_INT > 24) { wmParams.type = WindowManager.LayoutParams.TYPE_PHONE; } else { wmParams.type = WindowManager.LayoutParams.TYPE_TOAST; } 复制代码
- 系统8.0以上使用SYSTEM_ALERT_WINDOW 权限的应用无法再使用以下窗口类型来在其他应用和系统窗口上方显示提醒窗口:
- TYPE_PHONE
- TYPE_PRIORITY_PHONE
- TYPE_SYSTEM_ALERT
- TYPE_SYSTEM_OVERLAY
- TYPE_SYSTEM_ERROR
- 相反,应用必须使用名为 TYPE_APPLICATION_OVERLAY 的新窗口类型。
- 将build.gradle 的sdk版本不超过7.0
- 想到更好的实现方式,之后找产品或者设计怼回去
👉其他
📢作者:小空和小芝中的小空
📢转载说明-务必注明来源:
https://www.zhihu.com/people/zhimalier
https://juejin.cn/user/4265760844943479
📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。