作者:创世魂
● 帮助说明
无障碍的所有操作均位于“无障碍服务支持”模块中,使用时首先需要添加其模块。
● 准备工作
1、下载“开发者助手”APP
① 可进入酷安网下载:https://www.coolapk.com/apk/com.toshiba_dealin.developerhelper
② 本程序的主要作用:获取APP组件ID值,通过获取的ID值可实现对该组件进行一些操作。
③ 例如:模拟点击、获取组件内容等。
④ 安装完毕后,会在手机上看到下图所示的软件图标。
⑤ 注意:如果手机没有进行root,本软件运行可能会有一些异常情况,但不影响软件节点分析。
2、开启“开发者助手”无障碍服务。
① 打开系统“设置”找到“无障碍”,打开无障碍后,找到“开发者助手”点击进入。
② 注:不同系统之间,无障碍的位置可能有所差异,具体查看该手机的帮助手册。
③ 进入后点击开关按钮打开该服务。
3、打开“开发者助手”APP。
① 打开软件后勾选前三个选项,最后点击黄色箭头所指向的按钮。
② 如果前三个选项已处于勾选状态,则直接点击按钮。
③ 点击按钮后“开发者助手”窗口将关闭,桌面上将出现如图所示的悬浮按钮。
● 查看窗口名
1、打开任意APP。
2、点击“开发者助手”悬浮按钮将出现以下界面。
3、窗口名就位于“当前Activity”。
4、点击窗口名后可弹出信息框,可对窗口名进行复制。
● 查看组件ID
1、点击“开发者助手”悬浮按钮将出现以下界面。
2、点击界面中的“点击开始”按钮,开始分析界面。
3、分析完毕后,软件上会出现绿色的方框。
注:方框的数量由软件内的资源量决定。
4、此时点击“按钮”后会出现如下图所示的控件属性。
5、“id-Name”一栏后显示的就就是当前组件的ID值。
注意:有些软件的组件可能没有ID值。
注意2:ID值在实际使用时,只要后面的“rg_n”。
6、点击ID值后会弹出信息框,可进行ID值的复制操作。
● 创建无障碍服务
1、准备工作:
① 打开火山安装目录内“ samples\vprj_android\samples\accessibility\src”目录。
② 复制当前目录内的“res”文件夹。
2、粘贴res文件夹:
① 右键项目,选择“打开所在的文件夹”。
② 把复制的“res”文件夹粘贴到本项目的目录内。
③ 注意:本文件夹内的任何文件名都不要随意修改。
3、无障碍描述信息填写:
① 打开当前项目“res\values”目录。
② 使用记事本编辑“vol_accessibility_service_strings.xml”文件。
③ 当前文件中可编辑“无障碍描述”信息,描述信息会显示在“无障碍设置”中。
4、定义无障碍服务类:
① 新建一个类(Ctrl+D),基础类填写“无障碍服务类”,名称随意勾选公开。
② 属性名:“@安卓.附加清单”
属性值:“<. android:label="火山自定义无障碍服务">
<meta-data android:name="android.accessibilityservice" android:resource = "@xml/voldev_accessibility_service_config"/> </.>”
③ 属性名:“@安卓.外部资源”
属性值:“res”。
本属性的作用,就是用来指定复制过来的“res”文件夹。
注意:本文件夹名称不能修改。
④ 属性名:“@强制输出”
属性值:“真”。
火山开发采用按需求编译模式,未被引用的代码都会被剔除。
使用本属性可强制输出,让本服务被正常编译。
5、添加虚拟方法:
① 右键“无障碍服务类”
② 选择“添加‘XX’的虚拟方法”。
③ 依次添加“服务已连接”和“被解除所有绑定”方法。
④ 添加完毕后,让当前两个虚拟方法分别弹出提示框。
这两个虚拟方法可以理解为“无障碍服务”的开启和关闭的监听事件。
开启后会触发“服务已连接”,关闭后会触发“被解除所有绑定”。
6、开启程序无障碍:
① 编译安装程序,安装后就可在系统设置无障碍中看到当前程序的无障碍服务。
② 点击进入当前服务。
③ 进入后可看到“无障碍服务描述文本”以及“服务开关”,默认处于关闭状态。
④ 运行效果如下图(GIF)
当开关开启或关闭,当前程序都会监听到当前服务是否开启或关闭。
● 判断当前无障碍服务是否开启
帮助说明:
1、判断无障碍服务是否开启,需要用到三个类。
无障碍管理类:系统级服务,用于对无障碍事件的调度或查询系统当前的无障碍服务状态.
① 本类可单独使用,不会依赖无障碍服务。
② 获取实例方法:“安卓环境.获取系统服务 (本对象, 安卓环境.无障碍管理服务)”。
无障碍服务信息列表类:本类是列表模板类,可通过“无障碍管理类.取已启用服务列表()”获取本对象。
③ 本对象中存储了所有的无障碍信息。
无障碍服务信息类:本类中存储了,单个的无障碍信息数据。
④ 可通过“无障碍服务信息列表类.取成员()”获取本对象。
2、除了以上三个大类外,还需要用到三个方法。
子文本替换:取出的无障碍服务信息中包含多余的字符,需要通过本方法进行字符过滤。
取类名:本方法可用来取出指定类的java名称,可用来记录或者对比,返回值为文本型。
文本包含:通过本方法可判断所有已经开启的无障碍服务中是否包含当前服务。
如果包含了当前服务,则当前服务必然处于开启状态。
界面准备如下图:
打开启动类界面设计器,拖放一个“按钮”即可,
代码编写(1):
1、新建一个方法(Ctrl+M),方法名随意,返回值填写“逻辑型”。
2、定义类型为“无障碍管理类”变量,勾选参考,通过“安卓环境.获取系统服务()”方法获得本对象。
因本方法返回的是“对象类”,因此需要将其强转为“无障碍管理类”,并赋值给定义的变量。
3、定义类型为“无障碍服务信息列表类”变量,勾选参考。
通过“无障碍”变量,调用“取已启用服务列表(无障碍反馈类型.所有反馈)”方法,赋值给定义的“服务列表”变量。
本方法可取出所有已启用的无障碍服务。
4、定义“计次”整数变量,利用“循环”方法取出“服务列表”内所有成员。
5、定义类型为“无障碍服务信息类”变量,勾选参考。
通过“服务列表”变量,调用“取成员()”方法,赋值给定义的“无障碍信息”变量。
本方法可依次取出单个的无障碍信息。
6、定义“服务ID”文本型变量,利用“子文本替换()”方法,替换掉“无障碍信息.服务ID”中多余的字符。
每个无障碍服务都有一个固定的服务ID,通过定义的“无障碍信息”变量可获取此ID。
服务ID中存在一个多余的字符“/”,需通过本方法剔除。
7、定义“当前服务名”文本型变量,通过“取类名()”方法,取出“自定义无障碍服务”的java名称。
将取出的名称,赋值给定义的文本型变量。
8、利用“文本包含()”方法,判断“服务ID”中是否存在“当前服务名”。
如果存在则执行“返回(真)”,并执行“跳出循环”,表示当前服务已经开启。
9、最后在“循环”方法外,输入“返回(假)”,表示在已经开启的服务列表内未发现当前服务,即当前服务没有开启。
代码编写(2):
1、“按钮1”被点击后,直接判断“无障碍服务是否开启()”方法的返回值。
如果返回真,则提示“无障碍服务已经开启”,返回假则提示“没有开启服务”。
2、如果没有开启服务可执行“无障碍管理类.打开设置(本对象)”方法,可直接打开无障碍设置界面。
运行效果如下图(GIF):
首次运行无障碍服务必然处于关闭状态。
因此点击“按钮1”后会弹出“没有开启服务”并直接打开“无障碍设置”。
开启无障碍服务后,点击“返回”可重新回到当前程序。
此时再次点击“按钮1”会提示“无障碍服务已经开启”。
● 无障碍节点简述和获取方法
1、无障碍针对某个程序的窗口进行操作时,会把这个窗口当成一棵大树。
2、如下图所示:当前“窗口”为根节点,窗口上的所有组件全部都是“子节点”。
3、查找到的节点,通常存储在“无障碍节点信息类”和“无障碍节点信息列表类”中。
4、窗口根节点可通过“取根节点活动窗口 ()”方法获取,返回值为“无障碍节点信息类”。
5、组件节点通过“窗口根节点值.指定资源ID查找节点 ()”方法获取。
本方法继承自“无障碍节点信息类”,共有两个参数,支持动态调用。
参数1:动态调用时本参数忽略即可,否则填写欲操作的对象。
参数2:填写“程序包名”+“:id/”+“组件ID值”。
返回值为“无障碍节点信息列表类”,可通过“取成员()”方法取出指定节点。
● 结合上述的节点知识,实现模拟单击
获取窗口信息:
“通知_收到新事件”帮助文档:
无障碍所有的操作都是基于虚拟方法,参数返回“无障碍事件类”,可进行具体的无障碍操作。
代码编写说明:
1、添加“通知_接收新事件”虚拟方法,定义“是否点击”逻辑变量。
① 本虚拟方法会持续监听,“是否点击”变量用于防止按钮重复点击。
2、在虚拟方法下定义三个变量,类型分别为“无障碍节点信息类”和“无障碍节点信息列表类”。
① 三个变量全部勾选参考,用于存储窗口和组件节点信息。
3、判断“事件对象.事件类型”是否等于“无障碍事件类型.窗口状态改变”。
① 顾名思义,用于判断程序窗口是否被改变。
4、利用“文本相等”命令,判断窗口名称是否等于“事件对象.类名”。
① 如果相等,代表当前手机显示的窗口为指定的窗口。
5、通过“取根节点活动窗口()”方法,取出窗口节点赋值给“窗口根节点”变量。
6、判断当前窗口节点是否为空对象,防止获取失败。
7、调用“指定资源ID查找节点()”方法,查找“按钮1”的组件。
① 将查找到的节点赋值给“按钮列表”变量。
② 组件ID书写格式:“包名”+“:id/”+“组件id”
8、判断“按钮列表”是否为空对象,或者成员数是否大于0,防止获取失败。
9、通过“取成员()”方法取出当前“按钮节点”。
① 因只是一个组件,参数值直接填写0即可。
10、判断“是否点击”变量是否为假,用于防止重复点击。
11、通过“按钮节点”调用“执行动作()”方法,来模拟点击。
① “执行动作”帮助文档:
② 参数1:动态调用时省略即可,否则填写当前对象。
③ 参数2:调用方式“无障碍服务节点动作类型.XXX”。
④ 参数3:保留空对象即可。
12、最后需要设置“是否点击=真”。
代码编写如下图:
运行结果如下图(GIF):
左图:无障碍下模拟点击,并且只会点击一次。
右图:正常点击状态。
● 模拟长按
代码编写如下图:
在源代码的基础上,将“执行动作()”方法内的参数修改成“无障碍服务节点动作类型.长按操作”即可。
运行效果如下图(GIF):
左图:无障碍模拟长按。
右图:正常长按。
● 无障碍节点信息类
帮助文档如下图:
1、本类中所有的属性和方法和“窗口组件”基础类的用法基本一致。
2、可以理解为窗口组件的另外一种表示形式,此处举例“读组件内容”操作。
注意:本类和“窗口组件”基础类同理,并非所有方法都能正常使用。
例如:在本类中存在一个“内容”写属性,但是本属性并不能给“编辑框”赋值,赋值需要用“执行动作”方法。
● 取组件内容
通过“开发者助手”取出窗口组件信息:
代码编写如下图:
取编辑框的组件内容很简单,在源代码的基础上通过“编辑框节点”调用“内容”读属性即可。
注意:取组件内容仅限于“按钮”,“文本框”或者“编辑框”等存储文本字符串的组件。
并不能读取图片框的图片数据。
运行结果如下图(GIF):
打开“计算器”这个程序,编辑框的内容就会被弹出。
● 写组件内容
帮助说明:
写组件内容无法修改图片框组件的,只能修改编辑框类的组件数据。
代码编写如下图:
1、定义“数据包类”变量,调用“写文本字段()”方法,设置要写入的新内容。
字段名务必填写:无障碍服务节点动作参数类型.指定文本内容。
2、调用“睡眠当前线程()”延时1秒后调用“执行动作()”方法。
参数1:必须填写“无障碍服务节点动作类型.设置文本”。
参数2:填写定义的“数据包”变量。
运行效果如下图(GIF):
● 监听指定编辑框内容改变
想要实现监听指定编辑框内容被改变,需要学习两个新的方法。
“查找指定焦点节点”和“对象是否相等”
“查找指定焦点节点”帮助文档:
1、本方法继承自“无障碍服务类”。
2、通过本方法可查找指定焦点节点,参数值填写“假”即可查找编辑框组件。
3、本方法的返回值为“无障碍节点信息类”。
“对象是否相等”帮助文档:
1、本方法继承自对象类。
2、顾名思义,通过本方法可判断两个对象是否相等。
3、相等返回真,不相等返回假。
代码编写如下图:
1、定义一个“逻辑型”的成员变量,用于判断是否为指定窗口。
2、判断“事件类型”是否为“窗口状态改变”,用于确定逻辑变量的逻辑值。
3、判断“事件类型”是否为“文本已改变”,用于监听内容被改变。
4、判断是否为指定窗口,如果为指定窗口则执行编辑框节点判断操作。
5、查找要监听的编辑框节点。
6、调用“查找指定焦点节点()”方法,查找带有焦点的编辑框节点。
7、如果两个节点相等,则表示要监听的编辑框内容被改变。
运行效果如下图(GIF):
● 监听指定编辑框选区被改变
代码编写如下图:
在源代码的基础上简单修改即可实现本功能。
1、判断“事件类型”是否等于“文本选择被改变”。
2、继续判断是否为指定窗口。
3、取出要监听的编辑框节点。
4、判断选区位置是否相同,目的是判断是否存在选区。
5、如果存在选区,计算选区长度后,利用“取子文本()”方法取出被选择文本。
运行效果如下图(GIF):
可看到选择第一个编辑框内容,会弹出选区文本。
选择第二个编辑框无任何反应。
● 监听指定组件被单击
代码编写如下图:
在源代码的基础上简单修改即可实现本功能。
1、判断“事件类型”是否等于“被单击”。
2、继续判断是否为指定窗口。
3、取出要监听的组件节点。
4、调用“事件对象.取节点信息()”方法,可取出当前响应事件的组件节点。
5、调用“对象是否相等()”方法,判断两个节点对象是否相等。
6、如果相等表示指定组件被点击,不相等则相反。
运行效果如下图(GIF):
● 监听状态栏消息内容
代码编写如下图:
在源代码的基础上简单修改即可实现本功能。
1、判断“事件类型”是否等于“通知栏状态改变”。
2、随后判断“事件对象.取分配对象()”是否属于“安卓通知栏”。
3、定义类型为“字符串列表类”变量,勾选参考,调用“取文本()”方法赋值给字符串变量。
4、通过字符串变量调用“取成员()”方法,取出的最后一个成员就是当前状态栏显示文本。
① 安卓5.X以下版本,通知栏消息会在状态栏显示消息文本
② 5.X以上不再支持文本显示,但是并不影响消息监听。
③ 监听的状态栏内容,实际上就是监听的通知栏消息。
运行效果如下图(GIF):
点击要监听的软件按钮后,当前程序会弹出一条通知消息。
因当前系统是安卓5.1,状态栏内容并不会显示在状态栏上,但并不影响无障碍程序监听。
● 模拟通知栏消息点击
代码编写如下图:
在源代码的基础上简单修改即可实现本功能。
1、定义类型为“安卓通知栏”的变量,勾选参考。
2、取出分配对象强转为“安卓通知栏”并赋值给“通知栏”变量。
3、通过定义的“通知栏”变量调用“取条目启动对象().发送()”,即可实现模拟通知栏消息点击。
运行效果如下图(GIF):
左图:无障碍模拟通知栏点击。
右图:正常状态下点击通知栏消息。