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_TOUCHABLEFLAG_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

标签:Android,无障碍,全局悬浮窗
0
投稿

猜你喜欢

  • C#使用NPOI导入Excel的方法详解

    2021-08-29 07:39:35
  • Springboot actuator应用后台监控实现

    2022-02-01 11:48:16
  • 详解Spring Aop实例之AspectJ注解配置

    2023-02-04 02:52:53
  • Reactor 多任务并发执行且结果按顺序返回第一个

    2021-08-15 03:32:46
  • Spring Boot + Vue 前后端分离项目如何踢掉已登录用户

    2021-07-23 21:57:35
  • C#编程实现四舍五入、向上及下取整的方法

    2023-10-25 07:59:38
  • Spring中RedisTemplate的基本使用浅析

    2023-03-08 05:46:50
  • 使用mybatis-plus的insert方法遇到的问题及解决方法(添加时id值不存在异常)

    2023-11-12 19:25:55
  • 简单了解java标识符的作用和命名规则

    2022-06-18 17:49:09
  • Android防止点击过快造成多次响应事件的解决方法

    2023-05-24 16:26:09
  • java mybatis如何操作postgresql array数组类型

    2023-04-25 22:59:37
  • Android判断用户的网络类型实例讲解(2/3/4G、wifi)

    2022-11-10 23:27:51
  • c# 在windows中操作IIS设置FTP服务器的示例

    2023-07-18 06:13:01
  • SpringCloud Edgware.SR3版本中Ribbon的timeout设置方法

    2023-03-07 10:45:46
  • 深入分析NTFS中文件被锁定导致Process.Start失败的详解

    2023-08-24 06:11:25
  • Android编程实现全局获取Context及使用Intent传递对象的方法详解

    2022-02-27 08:50:13
  • Java并发编程之Fork/Join框架的理解

    2023-09-30 14:14:01
  • Android离线Doc文档访问速度慢的有效解决方法

    2021-06-27 02:10:39
  • Unity常用命令模式详解

    2021-12-30 16:58:08
  • 分布式医疗挂号系统SpringCache与Redis为数据字典添加缓存

    2023-06-28 02:26:55
  • asp之家 软件编程 m.aspxhome.com