Android 无障碍全局悬浮窗实现示例
作者:自动化BUG制造器 发布时间:2023-07-30 08:50:01
Android 无障碍的全局悬浮窗可以在屏幕上添加 UI 供用户进行快捷操作,可以展示在所有应用程序之上长期展示。另一方面,在一些自动化场景下,可以用来屏蔽用户行为,防止用户手动操作打断自动化流程。
无障碍添加 UI
无障碍服务添加 UI 十分简单,使用 LayoutInflater 在 AccessibilityService 的 onServiceConnected
添加一个 UI:
// in AccessibilityService, service 代表 AccessibilityService 的子类实例
private fun initView() {
// 在屏幕顶部添加一个 View
val wm = service.getSystemService(AccessibilityService.WINDOW_SERVICE) as? WindowManager
val lp = WindowManager.LayoutParams().apply {
type = TYPE_ACCESSIBILITY_OVERLAY // 因为此权限才能展示处理
layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
format = PixelFormat.TRANSLUCENT
flags = flags or
FLAG_LAYOUT_NO_LIMITS or
FLAG_NOT_TOUCHABLE or // 透传触摸事件
FLAG_NOT_FOCUSABLE or // 透传输入事件
FLAG_LAYOUT_IN_SCREEN
width = MATCH_PARENT
height = MATCH_PARENT
}
// 通过 LayoutInflater 创建 View
val rootView = LayoutInflater.from(service).inflate(R.layout.float_layer, null)
wm?.addView(rootView, lp)
}
然后在自定义的无障碍服务中去调用这个方法:
class MyAccessibilityService: AccessibilityService() {
override fun onServiceConnected() {
super.onServiceConnected()
initView()
}
// ...
}
需要注意的是,这里不能将 initView
添加到 onCreate
生命周期中,官方文档也有一些放在 onCreate 中的操作,但实际上都会导致 crash 。
java.lang.RuntimeException: Unable to create service com.chunyu.accessibilitydemo.service.AccessibilityDemoService: android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
无障碍服务所有的初始化工作,都要放在 onServiceConnected
中执行。这样就可以将自定义的 UI 展示到屏幕上了。
关于无障碍服务的配置,可以参考官方 API 。
配置分析
从使用上来看,无障碍蒙层是通过 WindowManager 添加到屏幕上的。而关键的一些信息在 WindowManager.LayoutParams 配置的数据中。
Type
Window 有一个关键的属性 type ,它被定义在 WindowManager 的内部类 LayoutParams 中,它可以控制 Window 的显示次序。主要分为三种:
Application Window:应用程序窗口 1-99 ,应用程序窗口一般位于最底层。
System Window:系统窗口 2000-2999 ,系统级窗口一般位于最顶层,不会被其他的window遮住。
Sub Window:子窗口 1000-1999,子窗口一般是显示在应用窗口之上。
从三种窗口的值也可推断出,type 的值越大,Window 就越靠近用户。
在上面的使用中,我们将 type 设置为 TYPE_ACCESSIBILITY_OVERLAY
,它的值是 2032 ,是一个系统窗口,所以可以展示在应用程序之上。 TYPE_ACCESSIBILITY_OVERLAY
,是无障碍服务用来展示 UI 专用的 窗口类型 。使用它可以在所有的应用程序上展示蒙层。
Flag
flag 中包含了两个关键的值 FLAG_NOT_TOUCHABLE
和 FLAG_NOT_FOCUSABLE
,和一些其他的 flag 。配置这两个内容,蒙层将不会影响任何用户操作。
FLAG_NOT_TOUCHABLE
:可以将 Window 设置为永不接收触摸事件,从而能够将触摸事件透传给蒙层遮盖住的区域,不阻塞用户操作。FLAG_NOT_FOCUSABLE
:可以将 Window 设置为永不获取按键输入焦点,用户无法向这个 Window 发送按键或其他的按钮时间,而被它覆盖的内容可以接收并响应事件。FLAG_LAYOUT_NO_LIMITS
:允许窗口延伸到屏幕之外。FLAG_LAYOUT_IN_SCREEN
:将窗口放置在整个屏幕中,忽略来自父窗口的任何约束。
LayoutInDisplayCutoutMode
这个属性可以用来控制 Window 在刘海屏的布局方式。
LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
:仅当刘海屏完全包含在系统栏中时,才允许窗口扩展到刘海区域。 否则,窗口的布局使其不与刘海区域重叠。LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
:允许 Window 延伸到短的一侧边缘的刘海区域。LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
:Window 不允许延伸到刘海屏区域。LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
:允许 Window 延伸到所有的屏幕边缘刘海区域。
来源:https://juejin.cn/post/7108668826727743519


猜你喜欢
- 一、何为栈?栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称
- 函数指针最近看android camera 的source ,发现大量的call back ,多线程,有必要对其中的基础 :函数指针复习一下
- 前言本文简单介绍了设计模式的一种——职责链模式 一、职责链模式的定义与特点定义:为了避免请求发送者与多个请求处理者耦合在一起,于是
- 目录一 为什么要用锁二 synchronized怎么实现的三 CAS来者何人四synchronized和CAS孰优孰劣轻量级锁重量级锁总结提
- JPA主键@Id,@IdClass,@Embeddable,@EmbeddedId1、自动主键默认情况下,主键是一个连续的64位数字(lon
- spring boot2.x已经出来好一阵了,而且spring cloud 的最新Release版本Finchley.RELEASE,默认集
- 在Springboot+Mybatis-plus不使用SQL语句进行多表添加操作我所遇到的问题准备工作在测试环境下模拟思维分解一下:创建出一
- 最近开发项目中,有个在屏幕上任意拖动的悬浮窗功能,其实就是利用 WindowManager的api来完成这个需求,具体的实现的功能如下:1.
- 前言进入正题之前还是先回顾一个会被问无数遍的问题:stop和interrupt的区别是什么?简单的说就是,stop的话,那线程就真的结束了。
- 在上篇文章给大家介绍了WebService教程详解(一)使用工具的原因:1、 使用工具可以更好的了解WebService请求的过程 2、 使
- 需求在配置类中,从application.properties中读取一个复杂list。如List<Person>或者初始化一个m
- Menustrip控件是一个菜单栏控件,可以加载菜单栏,在很多系统中都有用到。本文介绍下该控件的一些属性的常用方式。在页面FormMain_
- 1、Aop 全程是Aspect Oriented Programming 即面向切面编程,通过预编译方式和运行期 * 实现程序功能的同一维
- 前面照着android系统的裁剪图片的功能自己写了一个相似的工具。功能是大体上实现了,但留下了一个调用的问题:如何从我的程序调用这个裁剪工具
- private void button1_Click(object sender, EventArgs e) &nbs
- 值栈:值栈是一个集合中的几个对象保持下列对象提供的顺序:值栈可以通过JSP,Velocity或者Freemarker的标签。有各种不同的标签
- 本文实例讲述了C#多线程之Thread中Thread.IsAlive属性用法。分享给大家供大家参考。具体如下:Thread.IsAlive属
- 前言:图片选择器基本上是每个App必备的东西,用公认好的第三方也可以,但是自己写的改起来方便,用起来顺手,而且这东西想想可能没动手之前想想比
- 简介Exchanger是一个用于线程间数据交换的工具类,它提供一个公共点,在这个公共点,两个线程可以交换彼此的数据。当一个线程调用excha
- 关键词IDEA 如何控制编辑左侧的功能图标 ICONIDEA 左侧的图标不见了怎么恢复1、操作步骤依次打开 File | Settings