Auto.Js 第三章:坐标、控件 - 模拟真人操作
教程基于Auto.js 4.0.1版本
目标:模拟真人手势操作
对手机的操作存在几种方式:
- 点击
- 长按
- 滑动
- 按实体按键
后面的是衍生的,并不是主要操作。
5. 多击
6. 多手势
关于控件:可以通过控件拿到坐标,再偏移坐标获得我们想要做的手势。
使用坐标完成手势操作
| 核心内容 |
|---|
| 坐标 (x,y):屏幕上任意一个点的x轴和y轴。原点(0,0)在左上角。从左往右 x轴越来越大。从上往下 y轴越来越大。1080*1920分辨率的手机屏幕中,左上角(0,0),右上角(1080,0),左下角(0,1920),右下角(1080,1920)。 |
| 手势:点击、长按、滑动、连续点击、多个地方同时点击、多个地方同时滑动都是手势。坐标可以决定手势的位置,包括起始位置、中间位置(可以有多个)、终点位置。 |
| 手势时长:和名字一样,很多手势都是有时间限制的,按下超过1秒判断为长按,按下0.1秒(100ms)判断为点击。 |
设置分辨率
setScreenMetrics(width, height)
width <number> 屏幕宽度,单位像素
height <number> 屏幕高度,单位像素
设置脚本坐标点击所适合的屏幕宽高。如果脚本运行时,屏幕宽度不一致会自动放缩坐标。
设置分辨率可以让同样的坐标在不同分辨率的设备上的操作位置相同。
点击
可以使用以下函数:
1、需要无障碍权限(Android 7.0):click(x, y) press(x, y, duration)
2、需要root(兼容低版本安卓): Tap(x, y) RootAutomator.tap(x, y[, id]) RootAutomator.press(x, y, duration[, id])RootAutomator.touchDown(x, y[, id]) RootAutomator.touchMove(x, y[, id]) RootAutomator.touchUp([id]) 使用Shell命令
初级教程只讲无障碍,不讲root。click
代码:
// 点击(x,y)为(400,500)的坐标位置
click(400,500);
运行结果:一闪而过,点击了一下 x轴为400,y轴为500的位置。
点击时的截图
press
时间参数需要很小,最好小于10,不然可能会被判定为长按。官方的longClick()函数的值约为600。
只有在长按执行完成(大约600毫秒)时脚本才会继续执行。
代码:
// 按下(x,y)为(500,500)的位置,按下去的时间为 1毫秒
press(500,500,1);
运行结果:
函数:
click(x, y)
x <number> 要点击的坐标的x值
y <number> 要点击的坐标的y值
模拟点击坐标(x, y),并返回是否点击成功。只有在点击执行完成后脚本才继续执行。
press(x, y, duration)#
x <number> 要按住的坐标的x值
y <number> 要按住的坐标的y值
duration <number> 按住时长,单位毫秒
模拟按住坐标(x, y), 并返回是否成功。只有按住操作执行完成时脚本才会继续执行。
如果按住时间过短,那么会被系统认为是点击;如果时长超过500毫秒,则认为是长按。
一般而言,只有按住过程中被其他事件中断才会操作失败。
长按
可以使用以下函数:
1、需要无障碍权限(Android 7.0): longClick(x, y) press(x, y, duration)
2、需要root(兼容低版本安卓): RootAutomator.press(x, y, duration[, id]) RootAutomator.longPress(x, y[\, id])RootAutomator.touchDown(x, y[, id]) RootAutomator.touchMove(x, y[, id]) RootAutomator.touchUp([id]) 使用Shell命令
longClick
长按,和click很像,点击时间更长,其他都一样。
代码:
// 长按(约为600毫秒)(x,y)为(500,800)的坐标位置
longClick(500,800);
运行结果:
点击时的截图
press
时间参数需要稍大,不然会被判定为点击。
代码:
// 按下(x,y)为(500,500)的位置,按下去的时间(第三个参数)为 500毫秒
press(300,500,500);
结果:
由于长按的位置没有可以长按的操作,所以没有触发其他事件。
函数:
longClick(x, y)
x <number> 要长按的坐标的x值
y <number> 要长按的坐标的y值
模拟长按坐标(x, y), 并返回是否成功。只有在长按执行完成(大约600毫秒)时脚本才会继续执行。
一般而言,只有长按过程中被其他事件中断(例如用户自行点击)才会长按失败。
press(x, y, duration)#
x <number> 要按住的坐标的x值
y <number> 要按住的坐标的y值
duration <number> 按住时长,单位毫秒
模拟按住坐标(x, y), 并返回是否成功。只有按住操作执行完成时脚本才会继续执行。
如果按住时间过短,那么会被系统认为是点击;如果时长超过500毫秒,则认为是长按。
一般而言,只有按住过程中被其他事件中断才会操作失败。
滑动
可以使用以下函数:
1、需要无障碍权限(Android 7.0):swipe(x1, y1, x2, y2, duration) gesture(duration, [x1, y1], [x2, y2], ...) gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)
2、需要root(兼容低版本安卓):Swipe(x1, y1, x2, y2, [duration]) RootAutomator.swipe(x1, x2, y1, y2[, duration, id]) RootAutomator.touchDown(x, y[, id]) RootAutomator.touchMove(x, y[, id]) RootAutomator.touchUp([id]) 使用Shell命令
swipe
代码:
// 从(500,800)的位置滑动到(500,300)的位置,使用1000毫秒(1秒)的时间来完成滑动
swipe(500,800,500,300,1000);
结果:
gesture
代码:
// 从(500,800)的位置滑动到(500,300)的位置,再移动到(200,300)的位置,使用1000毫秒(1秒)的时间来完成滑动,会被Autojs进行优化
gesture(1000,[500,800],[500,300],[200,300]);
结果:
函数:
swipe(x1, y1, x2, y2, duration)
x1 <number> 滑动的起始坐标的x值
y1 <number> 滑动的起始坐标的y值
x2 <number> 滑动的结束坐标的x值
y2 <number> 滑动的结束坐标的y值
duration <number> 滑动时长,单位毫秒
模拟从坐标(x1, y1)滑动到坐标(x2, y2),并返回是否成功。只有滑动操作执行完成时脚本才会继续执行。
一般而言,只有滑动过程中被其他事件中断才会滑动失败。
gesture(duration, [x1, y1], [x2, y2], ...)
duration <number> 手势的时长
[x, y] ... 手势滑动路径的一系列坐标
模拟手势操作。例如gesture(1000, [0, 0], [500, 500], [500, 1000])为模拟一个从(0, 0)到(500, 500)到(500, 100)的手势操作,时长为2秒。
// 补充,多手势
gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)
同时模拟多个手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。
按实体按键 Keys
| 核心内容 |
|---|
| 模拟按下了实体键的哪一个按键,有root的情况下可以模拟外置键盘的按键。比如"回车"按键。 |
按键模拟部分提供了一些模拟物理按键的全局函数,包括Home、音量键、照相键等,有的函数依赖于无障碍服务,有的函数依赖于root权限。
一般来说,以大写字母开头的函数都依赖于root权限。执行此类函数时,如果没有root权限,则函数执行后没有效果,并会在控制台输出一个警告。
代码:
back();
结果:
运行前:
运行后:
代码:
powerDialog();
结果:
运行前
运行后
函数:
back()
返回 <boolean>
模拟按下返回键。返回是否执行成功。 此函数依赖于无障碍服务。
powerDialog()
返回 <boolean>
弹出电源键菜单。返回是否执行成功。 此函数依赖于无障碍服务。
多击
在短时间内多次使用点击函数对同一个或临近的坐标位置进行点击。就是多次点击。
代码:
// 循环点击10次(500,500)的坐标位置,每次点击间隔10ms(毫秒)
for(let i=0; i<10; i++){
click(500,500);
sleep(10);
}
多手势
可以使用以下函数:
1、需要无障碍权限(Android 7.0): gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)
2、需要root(兼容低版本安卓):RootAutomator.touchDown(x, y[, id]) RootAutomator.touchMove(x, y[, id]) RootAutomator.touchUp([id]) 使用Shell命令
gestures
代码:
// 手势1:从(500,800)的位置滑动到(500,300)的位置,使用1000毫秒(1秒)的时间来完成滑动,不等待,不延迟
// 手势2:从(200,300)的位置滑动到(500,300)的位置,使用1000毫秒(1秒)的时间来完成滑动,不等待,不延迟
gestures(
[0,1000,[500,800],[500,300]],
[0,1000,[200,300],[500,300]]
);
结果:
函数:
gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)
同时模拟多个手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。
控件
| 核心内容 |
|---|
| 获取屏幕上的一个控件,对该控件进行点击、勾选等操作。可以获取控件的坐标,与坐标操作进行联动,有些特殊效果。 |
| 控件:手机App是通过很多个组件(拼图)拼起来的,所以组件才可以移动或者其他动画。游戏一般只有几个控件,其中的画面类似于图片,是一张一张的放到其中最大的控件里面播放的,也就是帧数(FPS)。 |
将控件放到这里的原因是因为他们之间有较大联系。
可以通过控件拿到坐标,再偏移坐标获得我们想要做的手势。
基于控件的操作
基于控件的操作指的是选择屏幕上的控件,获取其信息或对其进行操作。对于一般软件而言,基于控件的操作对不同机型有很好的兼容性;但是对于游戏而言,由于游戏界面并不是由控件构成,无法采用本章节的方法,也无法使用本章节的函数。有关游戏脚本的编写,请参考《基于坐标的操作》。
基于控件的操作依赖于无障碍服务,因此最好在脚本开头使用auto()函数来确保无障碍服务已经启用。如果运行到某个需要权限的语句无障碍服务并没启动,则会抛出异常并跳转到无障碍服务界面。这样的用户体验并不好,因为需要重新运行脚本,后续会加入等待无障碍服务启动并让脚本继续运行的函数。
您也可以在脚本开头使用"auto";表示这个脚本需要无障碍服务,但是不推荐这种做法,因为这个标记必须在脚本的最开头(前面不能有注释或其他语句、空格等),我们推荐使用auto()函数来确保无障碍服务已启用。
控件这一章分成5个知识点
1、auto - 分屏状态 [v4.1.0新增](可忽略)
4.0使用的功能几乎只有一个:检查无障碍服务是否开启auto() ui模式,检查无障碍服务是否开启auto.waitFor() 普通模式,检查无障碍服务是否开启auto.setMode(mode) 开启控件缓存
函数
auto() ui模式下使用
auto.waitFor() 普通模式下使用
auto.setMode(mode)
mode <string> 模式
设置无障碍模式为mode。mode的可选值为:
normal 正常模式,默认。
fast 快速模式。该模式下会启用控件缓存,从而选择器获取屏幕控件更快。对于需要快速的控件查看和操作的脚本可以使用该模式,一般脚本则没有必要使用该函数。
以下内容来自官方文档
v4.1.0新增
auto.serivce
获取无障碍服务。如果无障碍服务没有启动,则返回null。
auto.windows
当前所有窗口(AccessibilityWindowInfo)的数组,可能包括状态栏、输入法、当前应用窗口,弹出窗口、悬浮窗、分屏应用窗口等。可以分别获取每个窗口的布局信息。
该函数需要Android 5.0以上才能运行。
auto.root
当前窗口的布局根元素。如果无障碍服务未启动或者WindowFilter均返回false,则会返回null。
如果不设置windowFilter,则当前窗口即为活跃的窗口(获取到焦点、正在触摸的窗口);如果设置了windowFilter,则获取的是过滤的窗口中的第一个窗口。
如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素。
auto.rootInActiveWindow
当前活跃的窗口(获取到焦点、正在触摸的窗口)的布局根元素。如果无障碍服务未启动则为null
auto.setFlags(flags) 启用和禁用某些特性。
flags <string> | <Array> 一些标志,来启用和禁用某些特性,包括:
findOnUiThread 使用该特性后,选择器搜索时会在主进程进行。该特性用于解决线程安全问题导致的次生问题,不过目前貌似已知问题并不是线程安全问题。
useUsageStats 使用该特性后,将会以"使用情况统计"服务的结果来检测当前正在运行的应用包名(需要授予"查看使用情况统计"权限)。如果觉得currentPackage()返回的结果不太准确,可以尝试该特性。
useShell 使用该特性后,将使用shell命令获取当前正在运行的应用的包名、活动名称,但是需要root权限。
启用有关automator的一些特性。例如:
auto.setFlags(["findOnUiThread", "useShell"]);
auto.setWindowFilter(filter)
设置窗口过滤器。该函数需要Android 5.0以上才有效。
filter <Function> 参数为窗口(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以上才有效。
auto.windowRoots
返回当前被WindowFilter过滤的窗口的布局根元素组成的数组。
如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素的数组。
2、布局分析
需要从悬浮窗进入,所以第一步是开启悬浮窗。需要给悬浮窗权限。
1、在左侧边栏打开悬浮窗
2、通过悬浮窗进入布局分析模式
(1) 点击悬浮窗后选第三个(中间)按钮 
(2) 布局分析有两种模式 
3.1 布局范围分析
会将当前获取到的控件全部画出来,每一个绿色框框都是一个控件。
在布局简单或需求简单的时候完全够用。
点击控件后会出现3个选项:
查看控件信息:控件信息用于控件选择器。
在布局层次中查看:转到布局层次分析中查看当前控件。
生成代码:可以根据选项来直接生成选择器代码。在主流平台上很多时候都不好使。

点击控件出现的三个功能
查看控件信息:
在布局层次中查看:
生成代码:
3.2 布局层次分析
可以查看控件的层次结构,可以补充范围层次的不足。在多个控件重叠在一起的时候,范围分析很难选中自己想要的控件,此时层次分析就可以用来补上。
在点击控件时,后方会使用红色线条框出来当前控件的范围。很多没在屏幕上,或者大小为0的控件将不会被标出来。
长按控件会弹出来三个选项,和范围分析差不多,除了第二个选项是转到范围分析。


3、UiSelector - 控件选择器对象
| 核心内容 |
|---|
| 通过选择器获取到控件/控件集合 |
| 链式调用:控件选择器支持链式调用。例如className(“ImageView”).depth(10).findOne().click(),通过链式调用来组合条件。 |
他是一个对象,那么就需要一个获取他的方式:selector()
返回 <UiSelector>
创建一个新的选择器。但一般情况不需要使用该函数,因为可以直接用相应条件的语句创建选择器。
代码:
// 查看选择器的包名(可以说是对象的类型的全名)比如说:柴犬和二哈,狗 就是他们的类名。
log(selector().getClass())
结果:
查看text()控件选择器的类名
代码:
log(text("日志").getClass());
结果:
函数:
selector()
返回 <UiSelector>
创建一个新的选择器。但一般情况不需要使用该函数,因为可以直接用相应条件的语句创建选择器。
4、UiObject - 控件对象
| 核心内容 |
|---|
| 对控件进行点击。不能编辑控件,只能使用控件提供的功能,控件给了点击操作就能点击,给了勾选就能勾选。对控件进行点击,是直接对控件发出点击事件,不是通过坐标点击,所以指针位置不会有任何记录反应。 |
| 获取坐标:获取坐标给Auto.Js的其他模块使用。比如给"基于坐标的操作"模块来使用。给"图色"模块来使用 |
通过上面的选择器获取到的控件,就是控件对象(UiObject)。可以对控件进行点击、长按等操作。
可以通过获取控件坐标来做一些操作,比如找到桌面上QQ的位置,通过坐标将其滑动移到另外一个位置。
UiCollection对象
继承于数组Array对象,特点是可以对里面的所有控件进行统一操作,而不需要遍历出来一个个操作。UiObject拥有的函数,他也拥有。
简单来讲:他给我们提供了批量操作。
点击auto.js日志界面左上角的返回按钮
其他操作函数类似,出了函数名不一样,可能有参数,其他都一样。
通过布局分析知道返回上一级的按钮的desc属性后通过该属性来确定控件。
代码:
// 使用选择器选出控件
let uo = desc("转到上一层级").findOne(10);
// 如果控件不为空则进行点击
if(uo) uo.click();
// 可以简写
// desc("转到上一层级").findOne(10).click();
结果:
运行前:
运行后:
函数:
UiObject.click()
返回 <Boolean>
点击该控件,并返回是否点击成功。
如果该函数返回false,可能是该控件不可点击(clickable为false),当前界面无法响应该点击等。
5、Rect - 矩形对象
表示一个矩形(范围)。大致有4个属性6个函数。
Rect={
// 4个属性,分别代表上下左右的距离(以(0,0)为中心点)
left: 1, // 长方形左边界的x坐标
right: 1, // 长方形右边界的x坐标
top: 1, // 长方形上边界的y坐标
bottom: 1, // 长方形下边界的y坐标
// 函数
centerX: ()=>{}, // 长方形中点x坐标。
centerY: ()=>{}, // 长方形中点y坐标。
width: ()=>{}, // 长方形宽度。通常可以作为控件宽度。
height: ()=>{}, // 长方形高度。通常可以作为控件高度。
}
Rect.contains(r)
r <Rect>
返回值 <Boolean>
返回是否包含另一个长方形r。包含指的是,长方形r在该长方形的里面(包含边界重叠的情况)。
Rect.intersect(r)
r <Rect>
返回值 <Boolean>
返回是否和另一个长方形相交。
拿到日志界面返回上一级按钮的Rect对象
代码:
// 使用选择器选出控件
let uo = desc("转到上一层级").findOne(10);
// 进行点击
if(uo) {
let rect = uo.bounds();
log(rect);
}
// 可以简写
// log(desc("转到上一层级").findOne(10).bounds())
结果:
函数:
bounds()
返回 Rect
返回控件在屏幕上的范围,其值是一个Rect对象。
函数列表:
CoordinatesBasedAutomation - 基于坐标的操作
| 函数名 | 功能 | 参数 | 返回值 |
|---|---|---|---|
| setScreenMetrics(width, height) | 设置脚本坐标点击所适合的屏幕宽高。如果脚本运行时,屏幕宽度不一致会自动放缩坐标。 | number,number | - |
| click(x, y) | 模拟点击坐标(x, y) | number,number | boolean |
| longClick(x, y) | 模拟长按坐标(x, y) | number,number | boolean |
| press(x, y, duration) | 模拟按住坐标(x, y) | number,number,number | boolean |
| swipe(x1, y1, x2, y2, duration) | 模拟从坐标(x1, y1)滑动到坐标(x2, y2) | number,number,number,number | boolean |
| gesture(duration, [x1, y1], [x2, y2], …) | 模拟手势操作 | number,[x, y]… | - |
| gestures([delay1, duration1, [x1, y1], [x2, y2], …], [delay2, duration2, [x3, y3], [x4, y4], …], …) | 同时模拟多个手势,每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。 | Array… | - |
| RootAutomator.tap(x, y[, id]) | 点击位置(x, y),中id是一个整数值,用于区分多点触摸,不同的id表示不同的"手指",如果不需要多点触摸,则不需要id这个参数。 | number,number,number | - |
| RootAutomator.press(x, y, duration[, id]) | 模拟按下位置(x, y),时长为duration毫秒。 | number,number,number,number | - |
| RootAutomator.longPress(x, y[duration, id]) | 模拟长按位置(x, y)。 | number,number,number,number | - |
| RootAutomator.swipe(x1, x2, y1, y2[, duration, id]) | 模拟一次从(x1, y1)到(x2, y2)的时间为duration毫秒的滑动。 | num,num,num,num,num,num | - |
| RootAutomator.touchDown(x, y[, id]) | 模拟手指按下位置(x, y)。 | number,number,number | - |
| RootAutomator.touchMove(x, y[, id]) | 模拟移动手指到位置(x, y)。 | number,number,number | - |
| RootAutomator.touchUp([id]) | 模拟手指弹起。 | number,number,number | - |
| Tap(x, y) | 点击位置(x, y) | number,number | - |
| Swipe(x1, y1, x2, y2, [duration]) | 从(x1, y1)位置滑动到(x2, y2)位置。 | number,number,number | - |
Keys - 按键模拟
需要无障碍权限的函数:
back() 返回键
home() Home键
powerDialog() 弹出电源键菜单
notifications() 拉出通知栏
quickSettings() 显示快速设置(下拉通知栏到底)
recents() 显示最近任务
splitScreen() 分屏。需要系统自身功能的支持
需要ROOT权限的函数:
Home() Home键
Back() 返回键
Power() 电源键,和无障碍服务的电源菜单不同
Menu() 菜单键
VolumeUp() 音量上键
VolumeDown() 音量下键
Camera() 模拟按下照相键
Up() 物理按键上
Down() 物理按键下
Left() 物理按键左
Right() 物理按键右
OK() 物理按键确定
KeyCode(code) code <number> | 要按下的按键的数字代码或名称。 模拟物理按键。例如KeyCode(29)和KeyCode("KEYCODE_A")是按下A键。
KeyCode(code)
code <number> | 要按下的按键的数字代码或名称。参见下表。 模拟物理按键。例如KeyCode(29)和KeyCode("KEYCODE_A")是按下A键。
附录: KeyCode对照表
KeyCode KeyEvent Value
KEYCODE_MENU 1
KEYCODE_SOFT_RIGHT 2
KEYCODE_HOME 3
KEYCODE_BACK 4
KEYCODE_CALL 5
KEYCODE_ENDCALL 6
KEYCODE_0 7
KEYCODE_1 8
KEYCODE_2 9
KEYCODE_3 10
KEYCODE_4 11
KEYCODE_5 12
KEYCODE_6 13
KEYCODE_7 14
KEYCODE_8 15
KEYCODE_9 16
KEYCODE_STAR 17
KEYCODE_POUND 18
KEYCODE_DPAD_UP 19
KEYCODE_DPAD_DOWN 20
KEYCODE_DPAD_LEFT 21
KEYCODE_DPAD_RIGHT 22
KEYCODE_DPAD_CENTER 23
KEYCODE_VOLUME_UP 24
KEYCODE_VOLUME_DOWN 25
KEYCODE_POWER 26
KEYCODE_CAMERA 27
KEYCODE_CLEAR 28
KEYCODE_A 29
KEYCODE_B 30
KEYCODE_C 31
KEYCODE_D 32
KEYCODE_E 33
KEYCODE_F 34
KEYCODE_G 35
KEYCODE_H 36
KEYCODE_I 37
KEYCODE_J 38
KEYCODE_K 39
KEYCODE_L 40
KEYCODE_M 41
KEYCODE_N 42
KEYCODE_O 43
KEYCODE_P 44
KEYCODE_Q 45
KEYCODE_R 46
KEYCODE_S 47
KEYCODE_T 48
KEYCODE_U 49
KEYCODE_V 50
KEYCODE_W 51
KEYCODE_X 52
KEYCODE_Y 53
KEYCODE_Z 54
KEYCODE_COMMA 55
KEYCODE_PERIOD 56
KEYCODE_ALT_LEFT 57
KEYCODE_ALT_RIGHT 58
KEYCODE_SHIFT_LEFT 59
KEYCODE_SHIFT_RIGHT 60
KEYCODE_TAB 61
KEYCODE_SPACE 62
KEYCODE_SYM 63
KEYCODE_EXPLORER 64
KEYCODE_ENVELOPE 65
KEYCODE_ENTER 66
KEYCODE_DEL 67
KEYCODE_GRAVE 68
KEYCODE_MINUS 69
KEYCODE_EQUALS 70
KEYCODE_LEFT_BRACKET 71
KEYCODE_RIGHT_BRACKET 72
KEYCODE_BACKSLASH 73
KEYCODE_SEMICOLON 74
KEYCODE_APOSTROPHE 75
KEYCODE_SLASH 76
KEYCODE_AT 77
KEYCODE_NUM 78
KEYCODE_HEADSETHOOK 79
KEYCODE_FOCUS 80
KEYCODE_PLUS 81
KEYCODE_MENU 82
KEYCODE_NOTIFICATION 83
KEYCODE_SEARCH 84
TAGLAST KEYCODE 85
WidgetsBasedAutomation - 基于控件的操作
UiSelector
| 属性 | 介绍 |
|---|---|
| text | 控件的text(文本)属性是文本控件上的显示的文字,例如微信左上角的"微信"文本。 |
| desc | 控件的desc(描述,全称为Content-Description)属性是对一个控件的描述,例如网易云音乐右上角的放大镜图标的描述为搜索。要查看一个控件的描述,同样地可以借助悬浮窗查看。 |
| packageName | 包名。包名表示控件所在的应用包名,例如QQ界面的控件的包名为"com.tencent.mobileqq"。 |
| id | 控件的id属性通常是可以用来确定控件的唯一标识,如果一个控件有id,那么使用id来找到他是最好的方法。要查看屏幕上的控件的id,可以开启悬浮窗并使用界面工具,点击相应控件即可查看。若查看到的控件id为null, 表示该控件没有id。另外,在列表中会出现多个控件的id相同的情况。例如微信的联系人列表,每个头像的id都是一样的。此时不能用id来唯一确定控件。 |
| bounds | 控件在屏幕上的范围。 |
| drawingOrder | 控件在父控件的绘制顺序。 |
| indexInParent | 控件在父控件的位置。 |
| clickable | 控件是否可点击。 |
| longClickable | 控件是否可长按。 |
| checkable | 控件是否可勾选。 |
| checked | 控件是否可已勾选。 |
| scrollable | 控件是否可滑动。 |
| selected | 控件是否已选择。 |
| editable | 控件是否可编辑。 |
| visibleToUser | 控件是否可见。 |
| enabled | 控件是否已启用。 |
| depth | 控件的布局深度。 |
| className | 类名。类名表示一个控件的类型,例如文本控件为"android.widget.TextView", 图片控件为"android.widget.ImageView"等。 |
className属性
常见控件的类名如下:android.widget.TextView 文本控件
android.widget.ImageView 图片控件
android.widget.Button 按钮控件
android.widget.EditText 输入框控件
android.widget.AbsListView 列表控件
android.widget.LinearLayout 线性布局
android.widget.FrameLayout 帧布局
android.widget.RelativeLayout 相对布局
android.widget.RelativeLayout 相对布局
android.support.v7.widget.RecyclerView 通常也是列表控件
选择器对象的方法列表
| 函数名 | 函数获取的控件 | 参数类型 |
|---|---|---|
| selector() | 创建一个新的选择器 | - |
| - | text 属性 | - |
| text(str) | 属性和参数相同 | String |
| textContains(str) | 属性包含参数 | String |
| textStartsWith(prefix) | 属性以参数开头 | String |
| textEndsWith(suffix) | 属性参数结尾 | String |
| textMatches(reg) | 属性满足参数正则表达式 | String |
| - | desc 属性 | - |
| desc(str) | 属性和参数相同 | String |
| descContains(str) | 属性包含参数 | String |
| descStartsWith(prefix) | 属性以参数开头 | String |
| descEndsWith(suffix) | 属性参数结尾 | String |
| descMatches(reg) | 属性满足参数正则表达式 | String |
| - | id 属性 | - |
| id(resId) | 属性和参数相同 | String |
| idContains(str) | 属性包含参数 | String |
| idStartsWith(prefix) | 属性以参数开头 | String |
| idEndsWith(suffix) | 属性参数结尾 | String |
| idMatches(reg) | 属性满足参数正则表达式 | String |
| - | className 属性 | - |
| className(str) | 属性和参数相同 | String |
| classNameContains(str) | 属性包含参数 | String |
| classNameStartsWith(prefix) | 属性以参数开头 | String |
| classNameEndsWith(suffix) | 属性参数结尾 | String |
| classNameMatches(reg) | 属性满足参数正则表达式 | String |
| - | packageName 属性 | - |
| packageName(str) | 属性和参数相同 | String |
| packageNameContains(str) | 属性包含参数 | String |
| packageNameStartsWith(prefix) | 属性以参数开头 | String |
| packageNameEndsWith(suffix) | 属性参数结尾 | String |
| packageNameMatches(reg) | 属性满足参数正则表达式 | String |
| - | bounds 属性 | - |
| bounds(left, top, right, buttom) | 属性和参数相同 | number,number,number,number |
| boundsInside(left, top, right, buttom) | 属性包含参数-必须整个控件都在范围内 | number,number,number,number |
| boundsContains(left, top, right, buttom) | 属性包含参数-有一部分在范围内 | number,number,number,number |
| - | - | - |
| drawingOrder(order) | 控件在父视图中的绘制顺序,该属性在Android 7.0以上才能使用。 | number |
| clickable([b = true]) | 控件是否可点击 | boolean |
| longClickable([b = true]) | 控件是否可长按 | boolean |
| checkable([b = true]) | 控件是否可勾选 | boolean |
| selected([b = true]) | 控件是否被选 | boolean |
| enabled([b = true]) | 控件是否已启用 | boolean |
| scrollable([b = true]) | 控件是否可滑动 | boolean |
| editable([b = true]) | 控件是否可编辑 | boolean |
| multiLine([b = true]) | 文本或输入框控件是否是多行显示的 | boolean |
| - | - | - |
| findOne(time) | 在指定时间内找到一个符合条件的控件。不传参数就是不限时间。 | number |
| findOnce(i) | 就是只找一次符合条件的控件,在找到的控件数组里面按参数i来选择,如果没有则返回null。 | number |
| find() | 就是只找一次符合条件的控件,不管找到几个都返回结果,可以使用length属性来判断是否找到控件。 | - |
| untilFind() | 就是没传参数的findOne() | - |
| exists() | 判断屏幕上是否存在控件符合选择器所确定的条件。 | - |
findOne(time)
timeout <number> 搜索的超时时间,单位毫秒
简单来说:在指定时间内找到一个符合条件的控件。不传参数就是不限时间。
根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到屏幕上出现满足条件的一个控件为止,并返回该控件。如果找不到控件,当屏幕内容发生变化时会重新寻找,直至超时,如果未传参数,则直至找到,否则一直阻塞。
findOnce(i)
i <number> 索引
简单来说:就是只找一次符合条件的控件,在找到的控件数组里面按参数i来选择,如果没有则返回null。
根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,并返回第 i + 1 个符合条件的控件;如果没有找到符合条件的控件,或者符合条件的控件个数 < i, 则返回null。
注意这里的控件次序,是搜索算法深度优先搜索(DSF)决定的。
find()
简单来说:就是只找一次符合条件的控件,不管找到几个都返回结果,可以使用length属性来判断是否找到控件。
根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,找到所有满足条件的控件集合并返回。这个搜索只进行一次,并不保证一定会找到,因而会出现返回的控件集合为空的情况。
不同于findOne()或者findOnce()只找到一个控件并返回一个控件,find()函数会找出所有满足条件的控件并返回一个控件集合。之后可以对控件集合进行操作。
untilFind()
简单来说:就是没传参数的findOne()
根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到找到至少一个满足条件的控件为止,并返回所有满足条件的控件集合。
该函数与find()函数的区别在于,该函数永远不会返回空集合;但是,如果屏幕上一直没有出现满足条件的控件,则该函数会保持阻塞。
exists()
判断屏幕上是否存在控件符合选择器所确定的条件。例如要判断某个文本出现就执行某个动作,可以用:
if(text(“某个文本”).exists()){
//要支持的动作
}
UiObject
empty()
返回 <Boolean>
返回控件集合是否为空。
UiCollection.find(selector)
selector <UiSelector>
返回 <UiCollection>
根据selector所确定的条件在该控件集合的控件、子控件、孙控件...中找到所有符合条件的控件并返回找到的控件集合。
注意这会递归地遍历控件集合里所有的控件以及他们的子控件。和数组的filter函数不同。
UiCollection.findOne(selector)
selector <UiSelector>
返回 <UiOobject>
根据选择器selector在该控件集合的控件的子控件、孙控件...中搜索符合该选择器条件的控件,并返回找到的第一个控件;如果没有找到符合条件的控件则返回null。
控件对象的方法列表
| 函数名 | 函数获取的控件 | 参数类型 | 返回值 |
|---|---|---|---|
| click() | 点击该控件 | - | boolean |
| longClick() | 长按该控件 | - | boolean |
| setText(text) | 设置输入框控件的文本内容 | string | boolean |
| copy() | 对输入框文本的选中内容进行复制 | - | boolean |
| cut() | 对输入框文本的选中内容进行剪切 | - | boolean |
| paste() | 对输入框控件进行粘贴操作,把剪贴板内容粘贴到输入框中 | - | boolean |
| setSelection(start, end) | 对输入框控件设置选中的文字内容,该函数也可以用来设置光标位置,只要参数的end等于start,即可把输入框光标设置在start的位置。 | number,number | boolean |
| scrollForward() | 对控件执行向前滑动的操作 | - | boolean |
| scrollBackward() | 对控件执行向后滑动的操作 | - | boolean |
| select() | 对控件执行"选中"操作,并返回是否操作成功。"选中"和isSelected()的属性相关,但该操作十分少用。 | - | boolean |
| collapse() | 对控件执行折叠操作 | - | boolean |
| expand() | 对控件执行操作 | - | boolean |
| show() | 对集合中所有控件执行显示操作 | - | boolean |
| scrollUp() | 对集合中所有控件执行向上滑的操作 | - | boolean |
| scrollDown() | 对集合中所有控件执行向下滑的操作 | - | boolean |
| scrollLeft() | 对集合中所有控件执行向左滑的操作 | - | boolean |
| scrollRight() | 对集合中所有控件执行向右滑的操作 | - | boolean |
| children() | 返回该控件的所有子控件组成的控件集合。 | - | UiCollection (类似Array) |
| childCount() | 返回子控件数目。 | - | number |
| child(i) | 获取第i+1个子控件 | number | UiObject |
| parent() | 获取该控件的父控件 | - | UiObject |
| bounds() | 获取控件在屏幕上的范围,其值是一个Rect对象。 | - | Rect |
| boundsInParent() | 控件在父控件中的范围 | - | Rect |
| drawingOrder() | 返回控件在父控件中的绘制次序。该函数在安卓7.0及以上才有效,7.0以下版本调用会返回0。 | - | number |
| id() | 获取控件的id,如果一个控件没有id,则返回null。 | - | string |
| text() | 获取控件的文本,如果控件没有文本,返回""。 | - | string |
| findByText(str) | 根据文本text在子控件中递归地寻找并返回文本或描述(desc)包含这段文本str的控件,返回它们组成的集合。该函数会在当前控件的子控件,孙控件,曾孙控件…中搜索text或desc包含str的控件,并返回它们组合的集合。 | string | UiCollection |
| findOne(selector) | 根据选择器selector在该控件的子控件、孙控件…中搜索符合该选择器条件的控件,并返回找到的第一个控件;如果没有找到符合条件的控件则返回null。 | UiSelector | UiOobject |
| find(selector) | 根据选择器selector在该控件的子控件、孙控件…中搜索符合该选择器条件的控件,并返回它们组合的集合。 | UiSelector | UiCollection |
更多推荐



所有评论(0)