1、自界说AccessibilityService
继承 AccessibilityService,重写 onInterrupt() 和 onAccessibilityEvent() 方法(这两个方法是 必须重写 的)。在onAccessibilityEvent() 方法中,val rootNode = rootInActiveWindow 获取当前活动窗口的根节点。rootInActiveWindow 是 AccessibilityNodeInfo 类型的一个属性,它代表了当前活动窗口的根节点。这个根节点是一个包含所有 UI 组件的树形结构的顶层节点,可以从它开始递归地遍历整个界面元素。
- package com.codelab.basics
- import android.accessibilityservice.AccessibilityService
- import android.graphics.Rect
- import android.os.Environment
- import android.util.Log
- import android.view.accessibility.AccessibilityEvent
- import android.view.accessibility.AccessibilityNodeInfo
- import java.io.File
- class MyAccessibilityService : AccessibilityService() {
- override fun onAccessibilityEvent(event: AccessibilityEvent?) {
- val rootNode = rootInActiveWindow//用于获取当前活动窗口的根节点
- if (rootNode != null) {
- val xmlContent = StringBuilder()
- xmlContent.append("<?xml version="1.0" encoding="UTF-8"?>\n")
- xmlContent.append("<ViewHierarchy>\n")
- buildXml(rootNode, xmlContent, 1)
- xmlContent.append("</ViewHierarchy>")
- //将生成的 XML 内容先打印到日志中
- Log.d("GeneratedXML", xmlContent.toString())
- // 保存到文件
- saveToFile("view_hierarchy_full.xml", xmlContent.toString())
- }
- }
- override fun onInterrupt() {
- // 无障碍服务被中断时的回调
- }
- private fun buildXml(node: AccessibilityNodeInfo?, xmlContent: StringBuilder, depth: Int) {
- if (node == null) return
- // 添加缩进
- val indent = " ".repeat(depth)
- // 开始标签
- xmlContent.append("$indent<View ")
- // 获取所有公开属性
- val bounds = Rect()
- node.getBoundsInScreen(bounds) // 获取节点在屏幕上的边界
- xmlContent.append("class="${node.className}" ")
- xmlContent.append("text="${node.text}" ")
- xmlContent.append("description="${node.contentDescription}" ")
- xmlContent.append("viewId="${node.viewIdResourceName}" ")
- xmlContent.append("packageName="${node.packageName}" ")
- xmlContent.append("bounds="${bounds.flattenToString()}" ")
- xmlContent.append("clickable="${node.isClickable}" ")
- xmlContent.append("enabled="${node.isEnabled}" ")
- xmlContent.append("focusable="${node.isFocusable}" ")
- xmlContent.append("focused="${node.isFocused}" ")
- xmlContent.append("scrollable="${node.isScrollable}" ")
- xmlContent.append("selected="${node.isSelected}" ")
- xmlContent.append("checkable="${node.isCheckable}" ")
- xmlContent.append("checked="${node.isChecked}" ")
- // 如果有子节点,则保留内部层次
- if (node.childCount > 0) {
- xmlContent.append(">\n")
- for (i in 0 until node.childCount) {
- buildXml(node.getChild(i), xmlContent, depth + 1)
- }
- xmlContent.append("$indent</View>\n")
- } else {
- // 无子节点直接闭合标签
- xmlContent.append("/>\n")
- }
- }
- private fun saveToFile(fileName: String, content: String) {
- try {
- val file = File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), fileName)
- file.writeText(content)
- Log.d("MyAccessibilityService", "XML 文件已保存: ${file.absolutePath}")
- } catch (e: Exception) {
- Log.e("MyAccessibilityService", "保存文件时出错: ${e.message}")
- }
- }
- }
复制代码 2、Service注册
AccessbilityService本质还是Service,所以需要在 AndroidManifest.xml 中进行注册:
- <service
- android:name=".MyAccessibilityService"
- android:exported="false"
- android:label="BasicsCodelab"
- android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
- <intent-filter>
- <action android:name="android.accessibilityservice.AccessibilityService" />
- </intent-filter>
- </service>
复制代码
- android:name=".MyAccessibilityService":
- 该属性指定无障碍服务的类名称,MyAccessibilityService 是一个继承自 AccessibilityService 的类。这个类负责处置惩罚无障碍相关的变乱。
- android:exported="false":
- 用于明确标识该服务是否可以被其他应用启动或绑定。设置为 false 表现该服务不会被外部应用访问,只能由系统或该应用内访问。对于无障碍服务,通常设置为 false。
- android:label="BasicsCodelab":
- 该属性为无障碍服务指定了一个用户友好的名称。在设备的设置界面中,用户可以看到该服务的名称。BasicsCodelab 是你的服务显示的名称,可以根据需要更改为你的应用或服务的名称。
- android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE":
- 这个权限声明白该服务需要一个特定的权限才气绑定到无障碍服务。BIND_ACCESSIBILITY_SERVICE 权限是系统权限,通常只能由系统或具有相应权限的应用绑定,确保只有合适的应用能够访问这个服务。
- <intent-filter>:
- 在这个 intent-filter 中,<action android:name="android.accessibilityservice.AccessibilityService" /> 使系统知道该服务是一个无障碍服务。
- 这告诉 Android 系统,该服务的 action 是 android.accessibilityservice.AccessibilityService,它是系统辨认无障碍服务的尺度动作。
- <meta-data>:
- meta-data 元素用于指示系统该服务的配置文件位置。它的 android:name="android.accessibilityservice" 属性是系统所需的标识符。
- android:resource="@xml/accessible_service_config" 指定了该服务的配置文件 accessible_service_config.xml,该文件位于 res/xml/ 目录中。
- accessible_service_config.xml 是一个 XML 配置文件,其中界说了无障碍服务的具体配置,如服务接收的变乱类型、反馈类型、设置页面等。
3、监听相关配置
在 res 文件夹下xml文件夹 (没有的话新建),然后新建一个配置xml文件
在里面写入如下代码:
- <?xml version="1.0" encoding="utf-8"?>
- <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
- android:accessibilityEventTypes="typeAllMask"
- android:accessibilityFeedbackType="feedbackGeneric"
- android:accessibilityFlags="flagDefault"
- android:canRetrieveWindowContent="true"
- android:notificationTimeout="100"
- android:description="@string/app_name"
- android:packageNames="com.codelab.basics"/>
复制代码
- android:accessibilityEventTypes="typeAllMask"
- 界说服务接收的无障碍变乱类型。
- typeAllMask 表现接收所有类型的无障碍变乱。
- 其他常用变乱类型:
- typeViewClicked: 视图被点击变乱。
- typeViewFocused: 视图得到焦点变乱。
- typeWindowStateChanged: 窗口状态变化变乱。
- android:accessibilityFeedbackType="feedbackGeneric"
- 指定服务提供的反馈类型。
- feedbackGeneric 是通用的反馈类型,实用于多种无障碍服务场景。
- 其他反馈类型:
- feedbackSpoken: 语音反馈。
- feedbackHaptic: 触觉反馈(振动)。
- feedbackAudible: 音频反馈。
- feedbackVisual: 视觉反馈。
- android:accessibilityFlags="flagDefault"
- 配置无障碍服务的行为标志。
- flagDefault 是默认标志,通常用于尺度无障碍服务。
- 其他标志:
- flagIncludeNotImportantViews: 包罗非紧张视图(例如装饰性视图)。
- flagRequestTouchExplorationMode: 哀求触摸探索模式(用于支持触摸屏的服务)。
- android:canRetrieveWindowContent="true"
- 指定服务是否可以检索窗口内容。
- 假如设置为 true,服务可以访问窗口的内容(例如视图层次结构)。
- 对于需要操纵或查询视图节点的无障碍服务,这个属性必须设置为 true。
- android:notificationTimeout="100"
- 设置无障碍变乱的关照超时时间,单位为毫秒。
- 用于合并频繁的变乱,避免服务处置惩罚过多的变乱关照。
- android:description="@string/app_name"
- 提供无障碍服务的形貌信息,通常显示在设备的无障碍设置页面中。
- @string/app_name 指向 strings.xml 中界说的字符串资源。可以修改为更具体的形貌,例如 "This service provides additional accessibility features."。
- android:packageNames="com.codelab.basics"
- 指定服务监听的目的应用的包名。
- 假如留空,则表现服务可以接收所有应用的无障碍变乱。
- 当仅需要监听特定应用的无障碍变乱时,可以通过此属性限定服务的范围。
4、启用无障碍服务
运行APP,设置 → 无障碍 → 找到我们的APP → 若显示关闭说明无障碍服务没启动→点开→同意
运行结果
当前页面:
Android Studio日志系统Logcat:
将存储于android的xml文件导出至PC:
进入adb.exe的文件夹,在文件管理器地点栏输入cmd进入命令行。然后输入以下命令:
- adb pull /手机存储路径/文件名 本地路径
复制代码 命令行界面如下:
xml文件如下:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |