无障碍服务 - auto
基于控件的操作指的是选择屏幕上的控件,获取其信息或对其进行操作。对于一般软件而言,基于控件的操作对不同机型有很好的兼容性;但是对于游戏而言,由于游戏界面并不是由控件构成,无法采用本章节的方法,也无法使用本章节的函数。有关游戏脚本的编写,请参考《基于坐标的操作》。
基于控件的操作依赖于无障碍服务,因此最好在脚本开头使用`auto()`函数来确保无障碍服务已经启用。如果运行到某个需要权限的语句无障碍服务并没启动,则会抛出异常并跳转到无障碍服务界面。这样的用户体验并不好,因为需要重新运行脚本,后续会加入等待无障碍服务启动并让脚本继续运行的函数。
您也可以在脚本开头使用`"auto";`表示这个脚本需要无障碍服务,但是不推荐这种做法,因为这个标记必须在脚本的最开头(前面不能有注释或其他语句、空格等),我们推荐使用`auto()`函数来确保无障碍服务已启用。
# 检查无障碍服务 |auto
| 函数名 | 返回值 | 备注 |
| ---------- | :------: | ------------------------------------------------------------ |
| auto() | | 检查无障碍服务是否已经启用,如果没有启用则抛出异常并跳转到无障碍服务启用界面; |
| **参数名** | **类型** | |
| mode | 字符串 | 无障碍模式 |
mode的可选值为:
- `fast` 快速模式。该模式下会启用控件缓存,从而选择器获取屏幕控件更快。对于需要快速的控件操作的脚本可以使用该模式,一般脚本则没有必要使用该函数。
- `normal` 正常模式,默认。
> 如果不加mode参数,则为正常模式。
>
> 建议使用`auto.waitFor()`和`auto.setMode()`代替该函数,因为`auto()`函数如果无障碍服务未启动会停止脚本;而`auto.waitFor()`则会在在无障碍服务启动后继续运行。
- 示例:
```
auto("fast");
```
- 示例2:
```
auto();
```
# 检查无障碍服务 |waitFor
| 函数名 | 返回值 | 备注 |
| -------------- | :----: | ------------------------------------------------------------ |
| auto.waitFor() | | 检查无障碍服务是否已经启用,如果没有启用则跳转到无障碍服务启用界面,并等待无障碍服务启动;当无障碍服务启动后脚本会继续运行。 |
# 设置无障碍模式为mode |setMode
| 函数名 | 返回值 | 备注 |
| -------------- | :------: | ---------------------- |
| auto.setMode() | | 设置无障碍模式为mode; |
| **参数名** | **类型** | |
| mode | 字符串 | 无障碍模式 |
mode的可选值为:
- `fast` 快速模式。该模式下会启用控件缓存,从而选择器获取屏幕控件更快。对于需要快速的控件查看和操作的脚本可以使用该模式,一般脚本则没有必要使用该函数。
- `normal` 正常模式,默认。
# 启用有关automator |setFlags
| 函数名 | 返回值 | 备注 |
| --------------- | :-----------: | ------------------------------ |
| auto.setFlags() | | 启用有关automator的一些特性。 |
| **参数名** | **类型** | |
| flags | 字符串\|Array | 一些标志,来启用和禁用某些特性 |
- flags {string} | {Array} 一些标志,来启用和禁用某些特性,包括:
- `findOnUiThread` 使用该特性后,选择器搜索时会在主进程进行。该特性用于解决线程安全问题导致的次生问题,不过目前貌似已知问题并不是线程安全问题。
- `useUsageStats` 使用该特性后,将会以"使用情况统计"服务的结果来检测当前正在运行的应用包名(需要授予"查看使用情况统计"权限)。如果觉得currentPackage()返回的结果不太准确,可以尝试该特性。
- `useShell` 使用该特性后,将使用shell命令获取当前正在运行的应用的包名、活动名称,但是需要root权限。
启用有关automator的一些特性。例如:
```
auto.setFlags(["findOnUiThread", "useShell"]);
```
# 获取无障碍服务 |service
| 函数名 | 返回值 | 备注 |
| -------------- | :----: | ------------------------------------------------------ |
| auto.service() | | 获取无障碍服务。如果无障碍服务没有启动,则返回`null`。 |
参见[AccessibilityService](https://developer.android.com/reference/android/accessibilityservice/AccessibilityService)。
# 获取当前所有窗口 |windows
| 函数名 | 返回值 | 备注 |
| -------------- | :----: | ------------------------------------------------------------ |
| auto.windows() | Array | 当前所有窗口([AccessibilityWindowInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityWindowInfo))的数组,可能包括状态栏、输入法、当前应用窗口,弹出窗口、悬浮窗、分屏应用窗口等。可以分别获取每个窗口的布局信息。 |
获取当前所有窗口([AccessibilityWindowInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityWindowInfo))的数组,可能包括状态栏、输入法、当前应用窗口,弹出窗口、悬浮窗、分屏应用窗口等。可以分别获取每个窗口的布局信息。
> 该函数需要Android 5.0以上才能运行。
# 获取当前窗口布局元素 |root
| 函数名 | 返回值 | 备注 |
| ----------- | :----: | ------------------------------------------------------------ |
| auto.root() | 布尔型 | 当前窗口的布局根元素。如果无障碍服务未启动或者WindowFilter均返回false,则会返回`null`。 |
> 当前窗口的布局根元素。如果无障碍服务未启动或者WindowFilter均返回false,则会返回`null`。
>
> 如果不设置windowFilter,则当前窗口即为活跃的窗口(获取到焦点、正在触摸的窗口);如果设置了windowFilter,则获取的是过滤的窗口中的第一个窗口。
>
> 如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素。
# 获取当前活跃窗口布局元素 |rootInActiveWindow
| 函数名 | 返回值 | 备注 |
| ------------------------- | :------: | ------------------------------------------------------------ |
| auto.rootInActiveWindow() | UiObject | 当前活跃的窗口(获取到焦点、正在触摸的窗口)的布局根元素。如果无障碍服务未启动则为`null` |
# 设置窗口过滤器 |setWindowFilter
| 函数名 | 返回值 | 备注 |
| ---------------------- | :------: | ------------------------------------------------------------ |
| auto.setWindowFilter() | UiObject | 设置窗口过滤器。 |
| **参数名** | **类型** | |
| filter | Function | 参数为窗口([AccessibilityWindowInfo](https://developer.android.com/reference/android/view/accessibility/AccessibilityWindowInfo)),返回值为Boolean的函数。 |
> 这个过滤器可以决定哪些窗口是目标窗口,并影响选择器的搜索。例如,如果想要选择器在所有窗口(包括状态栏、输入法等)中搜索,只需要使用以下代码:
```
auto.setWindowFilter(function(window){
//不管是如何窗口,都返回true,表示在该窗口中搜索
return true;
});
```
- 又例如,当前使用了分屏功能,屏幕上有Auto.js和QQ两个应用,但我们只想选择器对QQ界面进行搜索,则:
```
auto.setWindowFilter(function(window){
// 对于应用窗口,他的title属性就是应用的名称,因此可以通过title属性来判断一个应用
return window.title == "QQ";
});
```
> 选择器默认是在当前活跃的窗口中搜索,不会搜索诸如悬浮窗、状态栏之类的,使用WindowFilter则可以控制搜索的窗口。
>
> 需要注意的是, 如果WindowFilter返回的结果均为false,则选择器的搜索结果将为空。
>
> 另外setWindowFilter函数也会影响`auto.windowRoots`的结果。
>
> 该函数需要Android 5.0以上才有效。
# 获取过滤的窗口布局元素 |windowRoots
| 函数名 | 返回值 | 备注 |
| ------------------ | :----: | -------------------------------------------------------- |
| auto.windowRoots() | Array | 返回当前被WindowFilter过滤的窗口的布局根元素组成的数组。 |
> 如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素的数组。