- Overview - 综述
- Q&A - 常见问题 -
- Globals - 一般全局函数 -
- WidgetsBasedAutomation - 基于控件的触摸模拟 -
- CoordinatesBasedAutomation - 基于坐标的触摸模拟 -
- Images - 图片与图色处理 +
- App - 应用 +
- Canvas - 画布
- Console - 控制台 -
- Events - 事件与监听 -
- Timers - 定时器 -
- Shell - Shell命令 -
- UI - 用户界面 +
- CoordinatesBasedAutomation - 基于坐标的操作 +
- Crypto - 加解密与消息摘要 +
- Device - 设备
- Dialogs - 对话框 +
- Engines - 脚本引擎 +
- Events - 事件与监听 +
- Floaty - 悬浮窗
- Files - 文件系统 -
- Storages - 本地存储 +
- Globals - 一般全局函数
- Http - HTTP -
- App - 应用 -
- Engines - 脚本引擎 +
- Images - 图片与图色处理 +
- Keys - 按键模拟 +
- Media - 多媒体
- Modules - 模块 +
- Sensors - 传感器 +
- Shell - Shell命令 +
- Storages - 本地存储
- Threads - 多线程 -
- Work with Java - 调用Java API +
- Timers - 定时器 +
- UI - 用户界面 +
- WidgetsBasedAutomation - 基于控件的操作 +
- Work with Java - 调用Java API
Auto.js 3.0.0 文档
+Auto.js Pro-8.2.0 文档
-
+
- Overview - 综述 +
- Q&A - 常见问题 +
- App - 应用 +
- Canvas - 画布 +
- Console - 控制台 +
- CoordinatesBasedAutomation - 基于坐标的操作 +
- Crypto - 加解密与消息摘要 +
- Device - 设备 +
- Dialogs - 对话框 +
- Engines - 脚本引擎 +
- Events - 事件与监听 +
- Floaty - 悬浮窗 +
- Files - 文件系统 +
- Globals - 一般全局函数 +
- Http - HTTP +
- Images - 图片与图色处理 +
- Keys - 按键模拟 +
- Media - 多媒体 +
- Modules - 模块 +
- Sensors - 传感器 +
- Shell - Shell命令 +
- Storages - 本地存储 +
- Threads - 多线程 +
- Timers - 定时器 +
- UI - 用户界面 +
- WidgetsBasedAutomation - 基于控件的操作 +
- Work with Java - 调用Java API +
-
+
- Overview - 综述 +
- Q&A - 常见问题 +
- App - 应用 +
- Canvas - 画布 +
- Console - 控制台 +
- CoordinatesBasedAutomation - 基于坐标的操作 +
- Crypto - 加解密与消息摘要 +
- Device - 设备 +
- Dialogs - 对话框 +
- Engines - 脚本引擎 +
- Events - 事件与监听 +
- Floaty - 悬浮窗 +
- Files - 文件系统 +
- Globals - 一般全局函数 +
- Http - HTTP +
- Images - 图片与图色处理 +
- Keys - 按键模拟 +
- Media - 多媒体 +
- Modules - 模块 +
- Sensors - 传感器 +
- Shell - Shell命令 +
- Storages - 本地存储 +
- Threads - 多线程 +
- Timers - 定时器 +
- UI - 用户界面 +
- WidgetsBasedAutomation - 基于控件的操作 +
- Work with Java - 调用Java API +
Auto.js Pro-8.2.0 文档
+ ++
目录
+ +-
+
- 首页 +
- Q&A +
- 如何阅读本文档 - Documentation +
- 应用 - App +
- 一般全局函数 - Globals +
- 控制台 - Console +
- 基于坐标的操作 - CoordinatesBasedAutomation +
- 加解密与消息摘要 - Crypto +
- 设备 - Device +
- 对话框 - Dialogs +
- 脚本引擎 - Engines +
- 事件与监听 - Events +
- 悬浮窗 - Floaty +
- 文件系统 - Files +
- HTTP - Http +
- 图片与颜色 - Images +
- 画布 - Canvas +
- 按键模拟 - Keys +
- 多媒体 - Media +
- 模块 - Modules +
- 基于控件的操作 - WidgetsBaseAutomation +
- 传感器 - Sensor +
- Shell - Shell +
- 本地储存 - Storages +
- 多线程 - Threads +
- 定时器 - Timers +
- 用户界面 - UI +
- 调用Java - Work with Java +
Auto.js Pro-8.1.0 文档
+Auto.js Pro-8.2.0 文档
索引 | @@ -115,6 +116,47 @@
目录
-
+
- canvas.getWidth() +
- canvas.getHeight() +
- canvas.drawRGB(r, int g, int b) +
- canvas.drawARGB(a, r, g, b) +
- canvas.drawColor(color) +
- canvas.drawColor(color, mode) +
- canvas.drawPaint(paint) +
- canvas.drawPoint(x, y, paint) +
- canvas.drawPoints(pts, paint) +
- canvas.drawLine(startX, startY, stopX, stopY, paint) +
- canvas.drawRect(r, paint) +
- canvas.drawRect(left, top, right, bottom, android.graphics.Paint paint) +
- canvas.drawOval(android.graphics.RectF oval, android.graphics.Paint paint) +
- canvas.drawOval(float left, float top, float right, float bottom, android.graphics.Paint paint) +
- canvas.drawCircle(float cx, float cy, float radius, android.graphics.Paint paint) +
- canvas.drawArc(android.graphics.RectF oval, float startAngle, float sweepAngle, boolean useCenter, android.graphics.Paint paint) +
- canvas.drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, android.graphics.Paint paint) +
- canvas.drawRoundRect(android.graphics.RectF rect, float rx, float ry, android.graphics.Paint paint) +
- canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, android.graphics.Paint paint) +
- canvas.drawPath(android.graphics.Path path, android.graphics.Paint paint) +
- canvas.drawBitmap(android.graphics.Bitmap bitmap, float left, float top, android.graphics.Paint paint) +
- canvas.drawText(java.lang.String text, float x, float y, android.graphics.Paint paint) +
- canvas.drawTextOnPath(java.lang.String text, android.graphics.Path path, float hOffset, float vOffset, android.graphics.Paint paint) +
- canvas.translate(dx, dy) +
- canvas.scale(sx, sy) +
- canvas.scale(float sx, float sy, float px, float py) +
- canvas.rotate(float degrees) +
- canvas.rotate(float degrees, float px, float py) +
- canvas.skew(float sx, float sy) +
- console.show()
- console.hide() @@ -136,32 +178,32 @@
- print(text)
目录
-
-
- setScreenMetrics(width, height) +
- 基于坐标的触摸模拟 -
- 安卓7.0以上的触摸和手势模拟
-
-
- click(x, y) -
- longClick(x, y) -
- press(x, y, duration) -
- 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], ...], ...) +
- 安卓7.0以上的触摸和手势模拟 -
- RootAutomator
-
-
- RootAutomator.tap(x, y[, id]) -
- RootAutomator.swipe(x1, x2, y1, y2[, duration, id]) -
- RootAutomator.press(x, y, duration[, id]) -
- RootAutomator.longPress(x, y[\, id]) -
- RootAutomator.touchDown(x, y[, id]) -
- RootAutomator.touchMove(x, y[, id]) -
- RootAutomator.touchUp([id]) +
- RootAutomator -
- 使用root权限点击和滑动的简单命令
-
-
- Tap(x, y) -
- Swipe(x1, y1, x2, y2, [duration]) +
- 使用root权限点击和滑动的简单命令
- Crypto
-
@@ -585,136 +627,6 @@
目录
- module (模块) -
- 基于控件的操作 - -
- SimpleActionAutomator - -
- UiSelector
-
-
- selector() -
- UiSelector.algorithm(algorithm) -
- UiSelector.text(str) -
- UiSelector.textContains(str) -
- UiSelector.textStartsWith(prefix) -
- UiSelector.textEndsWith(suffix) -
- UiSelector.textMatches(reg) -
- UiSelector.desc(str) -
- UiSelector.descContains(str) -
- UiSelector.descStartsWith(prefix) -
- UiSelector.descEndsWith(suffix) -
- UiSelector.descMatches(reg) -
- UiSelector.id(resId) -
- UiSelector.idContains(str) -
- UiSelector.idStartsWith(prefix) -
- UiSelector.idEndsWith(suffix) -
- UiSelector.idMatches(reg) -
- UiSelector.className(str) -
- UiSelector.classNameContains(str) -
- UiSelector.classNameStartsWith(prefix) -
- UiSelector.classNameEndsWith(suffix) -
- UiSelector.classNameMatches(reg) -
- UiSelector.packageName(str) -
- UiSelector.packageNameContains(str) -
- UiSelector.packageNameStartsWith(prefix) -
- UiSelector.packageNameEndsWith(suffix) -
- UiSelector.packageNameMatches(reg) -
- UiSelector.bounds(left, top, right, buttom) -
- UiSelector.boundsInside(left, top, right, buttom) -
- UiSelector.boundsContains(left, top, right, buttom) -
- UiSelector.drawingOrder(order) -
- UiSelector.clickable([b = true]) -
- UiSelector.longClickable([b = true]) -
- UiSelector.checkable([b = true]) -
- UiSelector.selected([b = true]) -
- UiSelector.enabled([b = true]) -
- UiSelector.scrollable([b = true]) -
- UiSelector.editable([b = true]) -
- UiSelector.multiLine([b = true]) -
- UiSelector.findOne() -
- UiSelector.findOne(timeout) -
- UiSelector.findOnce() -
- UiSelector.findOnce(i) -
- UiSelector.find() -
- UiSelector.untilFind() -
- UiSelector.exists() -
- UiSelector.waitFor() -
- UiSelector.filter(f) -
- - UiObject
-
-
- UiObject.click() -
- UiObject.longClick() -
- UiObject.setText(text) -
- UiObject.copy() -
- UiObject.cut() -
- UiObject.paste() -
- UiObject.setSelection(start, end) -
- UiObject.scrollForward() -
- UiObject.scrollBackward() -
- UiObject.select() -
- UiObject.collapse() -
- UiObject.expand() -
- UiObject.show() -
- UiObject.scrollUp() -
- UiObject.scrollDown() -
- UiObject.scrollLeft() -
- UiObject.scrollRight() -
- children() -
- childCount() -
- child(i) -
- parent() -
- bounds() -
- boundsInParent() -
- drawingOrder() -
- id() -
- text() -
- findByText(str) -
- findOne(selector) -
- find(selector) -
- - UiCollection - -
- Rect - -
- UiSelector进阶
- Sensors
- sensors.register(sensorName[, delay])
- sensors.unregister(emitter) @@ -973,6 +885,136 @@
- 尺寸的单位: Dimension
- Drawables
- 颜色 +
- 基于控件的操作 + +
- SimpleActionAutomator + +
- UiSelector
-
+
- selector() +
- UiSelector.algorithm(algorithm) +
- UiSelector.text(str) +
- UiSelector.textContains(str) +
- UiSelector.textStartsWith(prefix) +
- UiSelector.textEndsWith(suffix) +
- UiSelector.textMatches(reg) +
- UiSelector.desc(str) +
- UiSelector.descContains(str) +
- UiSelector.descStartsWith(prefix) +
- UiSelector.descEndsWith(suffix) +
- UiSelector.descMatches(reg) +
- UiSelector.id(resId) +
- UiSelector.idContains(str) +
- UiSelector.idStartsWith(prefix) +
- UiSelector.idEndsWith(suffix) +
- UiSelector.idMatches(reg) +
- UiSelector.className(str) +
- UiSelector.classNameContains(str) +
- UiSelector.classNameStartsWith(prefix) +
- UiSelector.classNameEndsWith(suffix) +
- UiSelector.classNameMatches(reg) +
- UiSelector.packageName(str) +
- UiSelector.packageNameContains(str) +
- UiSelector.packageNameStartsWith(prefix) +
- UiSelector.packageNameEndsWith(suffix) +
- UiSelector.packageNameMatches(reg) +
- UiSelector.bounds(left, top, right, buttom) +
- UiSelector.boundsInside(left, top, right, buttom) +
- UiSelector.boundsContains(left, top, right, buttom) +
- UiSelector.drawingOrder(order) +
- UiSelector.clickable([b = true]) +
- UiSelector.longClickable([b = true]) +
- UiSelector.checkable([b = true]) +
- UiSelector.selected([b = true]) +
- UiSelector.enabled([b = true]) +
- UiSelector.scrollable([b = true]) +
- UiSelector.editable([b = true]) +
- UiSelector.multiLine([b = true]) +
- UiSelector.findOne() +
- UiSelector.findOne(timeout) +
- UiSelector.findOnce() +
- UiSelector.findOnce(i) +
- UiSelector.find() +
- UiSelector.untilFind() +
- UiSelector.exists() +
- UiSelector.waitFor() +
- UiSelector.filter(f) +
+ - UiObject
-
+
- UiObject.click() +
- UiObject.longClick() +
- UiObject.setText(text) +
- UiObject.copy() +
- UiObject.cut() +
- UiObject.paste() +
- UiObject.setSelection(start, end) +
- UiObject.scrollForward() +
- UiObject.scrollBackward() +
- UiObject.select() +
- UiObject.collapse() +
- UiObject.expand() +
- UiObject.show() +
- UiObject.scrollUp() +
- UiObject.scrollDown() +
- UiObject.scrollLeft() +
- UiObject.scrollRight() +
- children() +
- childCount() +
- child(i) +
- parent() +
- bounds() +
- boundsInParent() +
- drawingOrder() +
- id() +
- text() +
- findByText(str) +
- findOne(selector) +
- find(selector) +
+ - UiCollection + +
- Rect + +
- UiSelector进阶
目录
综述#
本文档的章节大致上是以模块来分的,总体上可以分成"自动操作"类模块(控件操作、触摸模拟、按键模拟等)和其他类模块(设备、应用、界面等)。
"自动操作"的部分又可以大致分为基于控件和基于坐标的操作。基于坐标的操作是传统按键精灵、触摸精灵等脚本软件采用的方式,通过屏幕坐标来点击、长按指定位置模拟操作,从而到达目的。例如click(100, 200)
, press(100, 200, 500)
等。这种方式在游戏类脚本中比较有可行性,结合找图找色、坐标放缩功能也能达到较好的兼容性。但是,这种方式对一般软件脚本却难以达到想要的效果,而且这种方式需要安卓7.0版本以上或者root权限才能执行。所以对于一般软件脚本(例如批量添加联系人、自动提取短信验证码等等),我们采用基于控件的模拟操作方式,结合通知事情、按键事情等达成更好的工作流。这些部分的文档参见基于控件的操作和基于坐标的操作。
综述#
除此之外,Auto.js内置了对Promise。 -
+除此之外,Auto.js内置了对Promise。
+Q & A#
如何定时运行脚本#
@@ -1359,6 +1402,154 @@app.getInstalledApps([options])# +
canvas提供了使用画布进行2D画图的支持,可用于简单的小游戏开发或者图片编辑。使用canvas可以轻松地在一张图片或一个界面上绘制各种线与图形。
+canvas的坐标系为平面直角坐标系,以控件左上角为原点,控件上边沿为x轴正方向,控件左边沿为y轴正方向。例如分辨率为1920*1080的屏幕上,canvas控件覆盖全屏,画一条从屏幕左上角到屏幕右下角的线段为:
+canvas.drawLine(0, 0, 1080, 1920, paint);
+
canvas的绘制依赖于画笔Paint, 通过设置画笔的粗细、颜色、填充等可以改变绘制出来的图形。例如绘制一个红色实心正方形为:
+var paint = new Paint();
+//设置画笔为填充,则绘制出来的图形都是实心的
+paint.setStyle(Paint.STYLE.FILL);
+//设置画笔颜色为红色
+paint.setColor(colors.RED);
+//绘制一个从坐标(0, 0)到坐标(100, 100)的正方形
+canvas.drawRect(0, 0, 100, 100, paint);
+
如果要绘制正方形的边框,则通过设置画笔的Style来实现:
+var paint = new Paint();
+//设置画笔为描边,则绘制出来的图形都是轮廓
+paint.setStyle(Paint.STYLE.STROKE);
+//设置画笔颜色为红色
+paint.setColor(colors.RED);
+//绘制一个从坐标(0, 0)到坐标(100, 100)的正方形
+canvas.drawRect(0, 0, 100, 100, paint);
+
结合画笔,canvas可以绘制基本图形、图片等。
+canvas.getWidth()#
+-
+
- 返回 <number> +
返回画布当前图层的宽度。
+canvas.getHeight()#
+-
+
- 返回 <number> +
返回画布当前图层的高度。
+canvas.drawRGB(r, int g, int b)#
+将整个可绘制区域填充为r、g、b指定的颜色。相当于 canvas.drawColor(colors.rgb(r, g, b))
。
canvas.drawARGB(a, r, g, b)#
+将整个可绘制区域填充为a、r、g、b指定的颜色。相当于 canvas.drawColor(colors.argb(a, r, g, b))
。
canvas.drawColor(color)#
+-
+
color
<number> 颜色值
+
将整个可绘制区域填充为color指定的颜色。
+canvas.drawColor(color, mode)#
+-
+
color
<number> 颜色值
+mode
<PorterDuff.Mode> Porter-Duff操作
+
将整个可绘制区域填充为color指定的颜色。
+canvas.drawPaint(paint)#
+-
+
paint
<Paint> 画笔
+
将整个可绘制区域用paint指定的画笔填充。相当于绘制一个无限大的矩形,但是更快。 +通过该方法可以绘制一个指定的着色器的图案。
+canvas.drawPoint(x, y, paint)#
+在可绘制区域绘制由坐标(x, y)指定的点。 +点的形状由画笔的线帽决定(参见paint.setStrokeCap(cap))。 +点的大小由画笔的宽度决定(参见paint.setStrokeWidth(width))。
+++如果画笔宽度为0,则也会绘制1个像素至4个(若抗锯齿启用)。
+
相当于 canvas.drawPoints([x, y], paint)
。
canvas.drawPoints(pts, paint)#
+-
+
pts
<Array> 点坐标数组 [x0, y0, x1, y1, x2, y2, ...]
+paint
<Paint> 画笔
+
在可绘制区域绘制由坐标数组指定的多个点。
+canvas.drawLine(startX, startY, stopX, stopY, paint)#
+在可绘制区域绘制由起点坐标(startX, startY)和终点坐标(endX, endY)指定的线。 +绘制时会忽略画笔的样式(Style)。也就是说,即使样式设为“仅填充(FILL)”也会绘制。 +退化为点的线(长度为0)不会被绘制。
+canvas.drawRect(r, paint)#
+-
+
r
<Rect> 矩形边界
+paint
<Paint> 画笔
+
在可绘制区域绘制由矩形边界r指定的矩形。 +绘制时画笔的样式(Style)决定了是否绘制矩形界线和填充矩形。
+canvas.drawRect(left, top, right, bottom, android.graphics.Paint paint)#
+在可绘制区域绘制由矩形边界(left, top, right, bottom)指定的矩形。 +绘制时画笔的样式(Style)决定了是否绘制矩形界线和填充矩形。
+canvas.drawOval(android.graphics.RectF oval, android.graphics.Paint paint)#
+canvas.drawOval(float left, float top, float right, float bottom, android.graphics.Paint paint)#
+canvas.drawCircle(float cx, float cy, float radius, android.graphics.Paint paint)#
+canvas.drawArc(android.graphics.RectF oval, float startAngle, float sweepAngle, boolean useCenter, android.graphics.Paint paint)#
+canvas.drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, android.graphics.Paint paint)#
+canvas.drawRoundRect(android.graphics.RectF rect, float rx, float ry, android.graphics.Paint paint)#
+canvas.drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, android.graphics.Paint paint)#
+canvas.drawPath(android.graphics.Path path, android.graphics.Paint paint)#
+canvas.drawBitmap(android.graphics.Bitmap bitmap, float left, float top, android.graphics.Paint paint)#
+canvas.drawText(java.lang.String text, float x, float y, android.graphics.Paint paint)#
+canvas.drawTextOnPath(java.lang.String text, android.graphics.Path path, float hOffset, float vOffset, android.graphics.Paint paint)#
+canvas.translate(dx, dy)#
+平移指定距离。
+canvas.scale(sx, sy)#
+以原点为中心,将坐标系平移缩放指定倍数。
+canvas.scale(float sx, float sy, float px, float py)#
+canvas.rotate(float degrees)#
+canvas.rotate(float degrees, float px, float py)#
+canvas.skew(float sx, float sy)#
+画笔#
+变换矩阵#
+路径#
+Porter-Duff操作#
+着色器#
+遮罩过滤器#
+颜色过滤器#
+路径特效#
+区域#
+Console#
控制台模块提供了一个和Web浏览器中相似的用于调试的控制台。用于输出一些调试信息、中间结果等。 @@ -1514,8 +1705,8 @@
print(text)#
+
+基于坐标的触摸模拟#
Stability: 2 - Stable
本章节介绍了一些使用坐标进行点击、滑动的函数。这些函数有的需要安卓7.0以上,有的需要root权限。
要获取要点击的位置的坐标,可以在开发者选项中开启"指针位置"。
基于坐标的脚本通常会有分辨率的问题,这时可以通过setScreenMetrics()
函数来进行自动坐标放缩。这个函数会影响本章节的所有点击、长按、滑动等函数。通过设定脚本设计时的分辨率,使得脚本在其他分辨率下自动放缩坐标。
基于坐标的触摸模拟#
+setScreenMetrics(width, height)#
- width <number> 屏幕宽度,单位像素
- height <number> 屏幕高度,单位像素
@@ -1536,9 +1727,9 @@ 基于坐标的触摸模拟#
+安卓7.0以上的触摸和手势模拟#
Stability: 2 - Stable注意以下命令只有Android7.0及以上才有效
-click(x, y)#
+click(x, y)#
x
<number> 要点击的坐标的x值
y
<number> 要点击的坐标的y值
@@ -1546,14 +1737,14 @@ click(x, y)#
+longClick(x, y)#
模拟长按坐标(x, y), 并返回是否成功。只有在长按执行完成(大约600毫秒)时脚本才会继续执行。
一般而言,只有长按过程中被其他事件中断(例如用户自行点击)才会长按失败。
-press(x, y, duration)#
+press(x, y, duration)#
x
<number> 要按住的坐标的x值
y
<number> 要按住的坐标的y值
@@ -1568,7 +1759,7 @@ press(x, y, duration)#
+swipe(x1, y1, x2, y2, duration)#
x1
<number> 滑动的起始坐标的x值
y1
<number> 滑动的起始坐标的y值
@@ -1578,18 +1769,18 @@ press(x, y, duration)#
+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], ...], ...)#
+gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)#
同时模拟多个手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。
例如手指捏合:
gestures([0, 500, [800, 300], [500, 1000]],
[0, 500, [300, 1500], [500, 1000]]);
-
RootAutomator#
+RootAutomator#
Stability: 2 - StableRootAutomator是一个使用root权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。
一个脚本中最好只存在一个RootAutomator,并且保证脚本结束退出他。可以在exit事件中退出RootAutomator,例如:
var ra = new RootAutomator();
@@ -1600,7 +1791,7 @@ gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [
...
注意以下命令需要root权限
-RootAutomator.tap(x, y[, id])#
+RootAutomator.tap(x, y[, id])#
x
<number> 横坐标
y
<number> 纵坐标
@@ -1616,7 +1807,7 @@ RootAutomator.tap(x, y[, id])#
+RootAutomator.swipe(x1, x2, y1, y2[, duration, id])#
模拟一次从(x1, y1)到(x2, y2)的时间为duration毫秒的滑动。
-RootAutomator.press(x, y, duration[, id])#
+RootAutomator.press(x, y, duration[, id])#
模拟按下位置(x, y),时长为duration毫秒。
-RootAutomator.longPress(x, y[\, id])#
+RootAutomator.longPress(x, y[\, id])#
x
<number> 横坐标
y
<number> 纵坐标
@@ -1643,26 +1834,26 @@ RootAutomator.longPress(x, y[\, id])#
+RootAutomator.touchDown(x, y[, id])#
模拟手指按下位置(x, y)。
-RootAutomator.touchMove(x, y[, id])#
+RootAutomator.touchMove(x, y[, id])#
模拟移动手指到位置(x, y)。
-RootAutomator.touchUp([id])#
+RootAutomator.touchUp([id])#
id
<number> 多点触摸id,可选,默认为1
模拟手指弹起。
-使用root权限点击和滑动的简单命令#
+使用root权限点击和滑动的简单命令#
Stability: 1 - Experimental 注意:本章节的函数在后续版本很可能有改动!请勿过分依赖本章节函数的副作用。推荐使用RootAutomator
代替本章节的触摸函数。
以下函数均需要root权限,可以实现任意位置的点击、滑动等。
@@ -1683,19 +1874,19 @@ 使用root权限点击和滑动的简单命令#
+Tap(x, y)#
- x, y <number> 要点击的坐标。
点击位置(x, y), 您可以通过"开发者选项"开启指针位置来确定点击坐标。
-Swipe(x1, y1, x2, y2, [duration])#
+Swipe(x1, y1, x2, y2, [duration])#
滑动。从(x1, y1)位置滑动到(x2, y2)位置。
-
+
Crypto#
@@ -4870,2601 +5061,2601 @@ module (模块)#
-基于控件的操作指的是选择屏幕上的控件,获取其信息或对其进行操作。对于一般软件而言,基于控件的操作对不同机型有很好的兼容性;但是对于游戏而言,由于游戏界面并不是由控件构成,无法采用本章节的方法,也无法使用本章节的函数。有关游戏脚本的编写,请参考《基于坐标的操作》。
-基于控件的操作依赖于无障碍服务,因此最好在脚本开头使用auto()
函数来确保无障碍服务已经启用。如果运行到某个需要权限的语句无障碍服务并没启动,则会抛出异常并跳转到无障碍服务界面。这样的用户体验并不好,因为需要重新运行脚本,后续会加入等待无障碍服务启动并让脚本继续运行的函数。
-您也可以在脚本开头使用"auto";
表示这个脚本需要无障碍服务,但是不推荐这种做法,因为这个标记必须在脚本的最开头(前面不能有注释或其他语句、空格等),我们推荐使用auto()
函数来确保无障碍服务已启用。
-auto([mode])#
-
-mode
<string> 模式
-
-检查无障碍服务是否已经启用,如果没有启用则抛出异常并跳转到无障碍服务启用界面;同时设置无障碍模式为mode。mode的可选值为:
+
+Sensors#
+Stability: 2 - Stablesensors模块提供了获取手机上的传感器的信息的支持,这些传感器包括距离传感器、光线光感器、重力传感器、方向传感器等。需要指出的是,脚本只能获取传感器的数据,不能模拟或伪造传感器的数据和事件,因此诸如模拟摇一摇的功能是无法实现的。
+要监听一个传感器时,需要使用sensors.register()
注册监听器,之后才能开始监听;不需要监听时则调用sensors.unregister()
注销监听器。在脚本结束时会自动注销所有的监听器。同时,这种监听会使脚本保持运行状态,如果不注销监听器,脚本会一直保持运行状态。
+例如,监听光线传感器的代码为:
+
//光线传感器监听
+sensors.register("light").on("change", (event, light)=>{
+ log("当前光强度为", light);
+});
+
要注意的是,每个传感器的数据并不相同,所以对他们调用on()
监听事件时的回调函数参数也不是相同,例如光线传感器参数为(event, light)
,加速度传感器参数为(event, ax, ay, az)
。甚至在某些设备上的传感器参数有所增加,例如华为手机的距离传感器为三个参数,一般手机只有一个参数。
+常用的传感器及其事件参数如下表:
-fast
快速模式。该模式下会启用控件缓存,从而选择器获取屏幕控件更快。对于需要快速的控件操作的脚本可以使用该模式,一般脚本则没有必要使用该函数。
-normal
正常模式,默认。
+accelerometer
加速度传感器,参数(event, ax, ay, az)
:
+
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+ax
<number> x轴上的加速度,单位m/s^2
+ay
<number> y轴上的加速度,单位m/s^2
+az
<number> z轴上的加速度,单位m/s^2
+这里的x轴,y轴,z轴所属的坐标系统如下图(其中z轴垂直于设备屏幕表面):
+!
+
-如果不加mode参数,则为正常模式。
-建议使用auto.waitFor()
和auto.setMode()
代替该函数,因为auto()
函数如果无障碍服务未启动会停止脚本;而auto.waitFor()
则会在在无障碍服务启动后继续运行。
-示例:
-auto("fast");
-
示例2:
-auto();
-
auto.waitFor()#
-检查无障碍服务是否已经启用,如果没有启用则跳转到无障碍服务启用界面,并等待无障碍服务启动;当无障碍服务启动后脚本会继续运行。
-因为该函数是阻塞的,因此除非是有协程特性,否则不能在ui模式下运行该函数,建议在ui模式下使用auto()
函数。
-auto.setMode(mode)#
-
-mode
<string> 模式
+
+orientation
方向传感器,参数(event, azimuth, pitch, roll)
:
+
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+azimuth
<number> 方位角,从地磁指北方向线起,依顺时针方向到y轴之间的水平夹角,单位角度,范围0~359
+pitch
<number> 绕x轴旋转的角度,当设备水平放置时该值为0,当设备顶部翘起时该值为正数,当设备尾部翘起时该值为负数,单位角度,范围-180~180
+roll
<number> 绕y轴顺时针旋转的角度,单位角度,范围-90~90
-
设置无障碍模式为mode。mode的可选值为:
+
+gyroscope
陀螺仪传感器,参数(event, wx, wy, wz)
:
-fast
快速模式。该模式下会启用控件缓存,从而选择器获取屏幕控件更快。对于需要快速的控件查看和操作的脚本可以使用该模式,一般脚本则没有必要使用该函数。
-normal
正常模式,默认。
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+wx
<number> 绕x轴的角速度,单位弧度/s
+wy
<number> 绕y轴的角速度,单位弧度/s
+wz
<number> 绕z轴的角速度,单位弧度/s
-auto.setFlags(flags)#
-[v4.1.0新增]
+
+magnetic_field
磁场传感器,参数(event, bx, by, bz)
:
-flags
<string> | <Array> 一些标志,来启用和禁用某些特性,包括:
-findOnUiThread
使用该特性后,选择器搜索时会在主进程进行。该特性用于解决线程安全问题导致的次生问题,不过目前貌似已知问题并不是线程安全问题。
-useUsageStats
使用该特性后,将会以"使用情况统计"服务的结果来检测当前正在运行的应用包名(需要授予"查看使用情况统计"权限)。如果觉得currentPackage()返回的结果不太准确,可以尝试该特性。
-useShell
使用该特性后,将使用shell命令获取当前正在运行的应用的包名、活动名称,但是需要root权限。
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+bx
<number> x轴上的磁场强度,单位uT
+by
<number> y轴上的磁场强度,单位uT
+bz
<number> z轴上的磁场强度,单位uT
+gravity
重力传感器,参数(event, gx, gy, gz)
:
+
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+gx
<number> x轴上的重力加速度,单位m/s^2
+gy
<number> y轴上的重力加速度,单位m/s^2
+gz
<number> z轴上的重力加速度,单位m/s^2
-启用有关automator的一些特性。例如:
-auto.setFlags(["findOnUiThread", "useShell"]);
-
auto.serivce#
-[v4.1.0新增]
+
+linear_acceleration
线性加速度传感器,参数(event, ax, ay, az)
:
-- AccessibilityService
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+ax
<number> x轴上的线性加速度,单位m/s^2
+ay
<number> y轴上的线性加速度,单位m/s^2
+az
<number> z轴上的线性加速度,单位m/s^2
-获取无障碍服务。如果无障碍服务没有启动,则返回null
。
-
-auto.windows#
-[v4.1.0新增]
+
+ambient_temperature
环境温度传感器,大部分设备并不支持,参数(event, t)
:
-- <Array>
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+t
<number> 环境温度,单位摄氏度。
-当前所有窗口(AccessibilityWindowInfo)的数组,可能包括状态栏、输入法、当前应用窗口,弹出窗口、悬浮窗、分屏应用窗口等。可以分别获取每个窗口的布局信息。
-该函数需要Android 5.0以上才能运行。
-auto.root#
-[v4.1.0新增]
+
+light
光线传感器,参数(event, light)
:
-- <UiObject>
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+light
<number> 环境光强度,单位lux
-当前窗口的布局根元素。如果无障碍服务未启动或者WindowFilter均返回false,则会返回null
。
-如果不设置windowFilter,则当前窗口即为活跃的窗口(获取到焦点、正在触摸的窗口);如果设置了windowFilter,则获取的是过滤的窗口中的第一个窗口。
-如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素。
-auto.rootInActiveWindow#
-[v4.1.0新增]
+
+pressure
压力传感器,参数(event, p)
:
-- <UiObject>
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+p
<number> 大气压,单位hPa
-当前活跃的窗口(获取到焦点、正在触摸的窗口)的布局根元素。如果无障碍服务未启动则为null
。
-auto.setWindowFilter(filter)#
-[v4.1.0新增]
+
+proximity
距离传感器,参数(event, distance)
:
-filter
<Function> 参数为窗口(AccessibilityWindowInfo),返回值为Boolean的函数。
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+distance
<number> 一般指设备前置摄像头旁边的距离传感器到前方障碍物的距离,并且很多设备上这个值只有两种情况:当障碍物较近时该值为0,当障碍物较远或在范围内没有障碍物时该值为5
-设置窗口过滤器。这个过滤器可以决定哪些窗口是目标窗口,并影响选择器的搜索。例如,如果想要选择器在所有窗口(包括状态栏、输入法等)中搜索,只需要使用以下代码:
-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#
-[v4.1.0新增]
+
+relative_humidity
湿度传感器,大部分设备并不支持,参数(event, rh)
:
-- <Array>
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+rh
<number> 相对湿度,范围为0~100(百分比)
-返回当前被WindowFilter过滤的窗口的布局根元素组成的数组。
-如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素的数组。
-SimpleActionAutomator#
-Stability: 2 - StableSimpleActionAutomator提供了一些模拟简单操作的函数,例如点击文字、模拟按键等。这些函数可以直接作为全局函数使用。
-click(text[, i])#
-返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。
-该函数可以点击大部分包含文字的按钮。例如微信主界面下方的"微信", "联系人", "发现", "我"的按钮。
通常与while同时使用以便点击按钮直至成功。例如:
-while(!click("扫一扫"));
-
当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部点击成功。
-i是从0开始计算的, 也就是, click("啦啦啦", 0)
表示点击屏幕上第一个"啦啦啦", click("啦啦啦", 1)
表示点击屏幕上第二个"啦啦啦"。
-
-文本所在区域指的是,从文本处向其父视图寻找,直至发现一个可点击的部件为止。
-
-click(left, top, bottom, right)#
+sensors.register(sensorName[, delay])#
-left
<number> 要点击的长方形区域左边与屏幕左边的像素距离
-top
<number> 要点击的长方形区域上边与屏幕上边的像素距离
-bottom
<number> 要点击的长方形区域下边与屏幕下边的像素距离
-right
<number> 要点击的长方形区域右边与屏幕右边的像素距离
+sensorName
<string> 传感器名称,常用的传感器名称如上面所述
+delay
<number> 传感器数据更新频率,可选,默认为sensors.delay.normal
。可用的值如下:
+sensors.delay.normal
正常频率
+sensors.delay.ui
适合于用户界面的更新频率
+sensors.delay.game
适合于游戏的更新频率
+sensors.delay.fastest
最快的更新频率】
-
注意,该函数一般只用于录制的脚本中使用,在自己写的代码中使用该函数一般不要使用该函数。
-点击在指定区域的控件。当屏幕中并未包含与该区域严格匹配的区域,或者该区域不能点击时返回false,否则返回true。
-有些按钮或者部件是图标而不是文字(例如发送朋友圈的照相机图标以及QQ下方的消息、联系人、动态图标),这时不能通过click(text, i)
来点击,可以通过描述图标所在的区域来点击。left, bottom, top, right描述的就是点击的区域。
-至于要定位点击的区域,可以在悬浮窗使用布局分析工具查看控件的bounds属性。
-通过无障碍服务录制脚本会生成该语句。
-longClick(text[, i]))#
-
-text
<string> 要长按的文本
-i
<number> 如果相同的文本在屏幕中出现多次,则i表示要长按第几个文本, i从0开始计算
+
+- 返回 SensorEventEmiiter
-返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。
-当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部长按成功。
-scrollUp([i])#
+
注册一个传感器监听并返回SensorEventEmitter。
+例如:
+
console.show();
+//注册传感器监听
+var sensor = sensors.register("gravity");
+if(sensor == null){
+ toast("不支持重力传感器");
+ exit();
+}
+//监听数据
+sensor.on("change", (gx, gy, gz)=>{
+ log("重力加速度: %d, %d, %d", gx, gy, gz);
+});
+
可以通过delay参数来指定传感器数据的更新频率,例如:
+var sensor = sensors.register("gravity", sensors.delay.game);
+
另外,如果不支持sensorName
所指定的传感器,那么该函数将返回null
;但如果sensors.ignoresUnsupportedSensor
的值被设置为true
, 则该函数会返回一个不会分发任何传感器事件的SensorEventEmitter。
+例如:
+sensors.ignoresUnsupportedSensor = true;
+//无需null判断
+sensors.register("gravity").on("change", (gx, gy, gz)=>{
+ log("重力加速度: %d, %d, %d", gx, gy, gz);
+});
+
更多信息,参见SensorEventEmitter和sensors.ignoresUnsupportedSensor。
+sensors.unregister(emitter)#
-i
<number> 要滑动的控件序号
+emiiter
SensorEventEmitter
-找到第i+1个可滑动控件上滑或左滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。
-另外不加参数时scrollUp()
会寻找面积最大的可滑动的控件上滑或左滑,例如微信消息列表等。
-参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)
为滑动第一个可滑动控件。
-scrollDown([i])#
+注销该传感器监听器。被注销的监听器将不再能监听传感器数据。
+//注册一个传感器监听器
+var sensor = sensors.register("gravity");
+if(sensor == null){
+ exit();
+}
+//2秒后注销该监听器
+setTimeout(()=> {
+ sensors.unregister(sensor);
+}, 2000);
+
sensors.unregisterAll()#
+注销所有传感器监听器。
+sensors.ignoresUnsupportedSensor#
找到第i+1个可滑动控件下滑或右滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。
-另外不加参数时scrollUp()
会寻找面积最大的可滑动的控件下滑或右滑。
-参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)
为滑动第一个可滑动控件。
-setText([i, ]text)#
+表示是否忽略不支持的传感器。如果该值被设置为true
,则函数sensors.register()
即使对不支持的传感器也会返回一个无任何数据的虚拟传感器监听,也就是sensors.register()
不会返回null
从而避免非空判断,并且此时会触发sensors
的"unsupported_sensor"事件。
+
//忽略不支持的传感器
+sensors.ignoresUnsupportedSensor = true;
+//监听有不支持的传感器时的事件
+sensors.on("unsupported_sensor", function(sensorName){
+ toastLog("不支持的传感器: " + sensorName);
+});
+//随便注册一个不存在的传感器。
+log(sensors.register("aaabbb"));
+
事件: 'unsupported_sensor'#
返回是否输入成功。当找不到对应的文本框时返回false。
-不加参数i则会把所有输入框的文本都置为text。例如setText("测试")
。
-这里的输入文本的意思是,把输入框的文本置为text,而不是在原来的文本上追加。
-input([i, ]text)#
-当sensors.ignoresUnsupportedSensor
被设置为true
并且有不支持的传感器被注册时触发该事件。事件参数的传感器名称。
+SensorEventEmitter#
+注册传感器返回的对象,其本身是一个EventEmmiter,用于监听传感器事件。
+事件: 'change'#
+
+..args
<Any> 传感器参数
-返回是否输入成功。当找不到对应的文本框时返回false。
-不加参数i则会把所有输入框的文本追加内容text。例如input("测试")
。
-UiSelector#
-UiSelector即选择器,用于通过各种条件选取屏幕上的控件,再对这些控件进行点击、长按等动作。这里需要先简单介绍一下控件和界面的相关知识。
-一般软件的界面是由一个个控件构成的,例如图片部分是一个图片控件(ImageView),文字部分是一个文字控件(TextView);同时,通过各种布局来决定各个控件的位置,例如,线性布局(LinearLayout)里面的控件都是按水平或垂直一次叠放的,列表布局(AbsListView)则是以列表的形式显示控件。
-控件有各种属性,包括文本(text), 描述(desc), 类名(className), id等等。我们通常用一个控件的属性来找到这个控件,例如,想要点击QQ聊天窗口的"发送"按钮,我们就可以通过他的文本属性为"发送"来找到这个控件并点击他,具体代码为:
-var sendButton = text("发送").findOne();
-sendButton.click();
-
在这个例子中, text("发送")
表示一个条件(文本属性为"发送"),findOne()
表示基于这个条件找到一个符合条件的控件,从而我们可以得到发送按钮sendButton,再执行sendButton.click()
即可点击"发送"按钮。
-用文本属性来定位按钮控件、文本控件通常十分有效。但是,如果一个控件是图片控件,比如Auto.js主界面右上角的搜索图标,他没有文本属性,这时需要其他属性来定位他。我们如何查看他有什么属性呢?首先打开悬浮窗和无障碍服务,点击蓝色的图标(布局分析), 可以看到以下界面:
-之后我们点击搜索图标,可以看到他有以下属性:
-我们注意到这个图标的desc(描述)属性为"搜索",那么我们就可以通过desc属性来定位这个控件,得到点击搜索图标的代码为:
-desc("搜索").findOne().click();
-
可能心细的你可能注意到了,这个控件还有很多其他的属性,例如checked, className, clickable等等,为什么不用这些属性来定位搜索图标呢?答案是,其他控件也有这些值相同的属性、尝试一下你就可以发现很多其他控件的checked属性和搜索控件一样都是false
,如果我们用checked(false)
作为条件,将会找到很多控件,而无法确定哪一个是搜索图标。因此,要找到我们想要的那个控件,选择器的条件通常需要是可唯一确定控件的。我们通常用一个独一无二的属性来定位一个控件,例如这个例子中就没有其他控件的desc(描述)属性为"搜索"。
-另外,对于这个搜索图标而言,id属性也是唯一的,我们也可以用id("action_search").findOne().click()
来点击这个控件。如果一个控件有id属性,那么这个属性很可能是唯一的,除了以下几种情况:
-
-- QQ的控件的id属性很多都是"name",也就是在QQ界面难以通过id来定位一个控件
-- 列表中的控件,比如QQ联系人列表,微信联系人列表等
+
当传感器数据改变时触发该事件;该事件触发的最高频繁由sensors.register()
指定的delay参数决定。
+事件参数根据传感器类型不同而不同,具体参见本章最前面的列表。
+一个监听光线传感器和加速度传感器并且每0.5秒获取一个数据并最终写入一个csv表格文件的例子如下:
+
//csv文件路径
+cosnt csvPath = "/sdcard/sensors_data.csv";
+//记录光线传感器的数据
+var light = 0;
+//记录加速度传感器的数据
+var ax = 0;
+var ay = 0;
+var az = 0;
+//监听光线传感器
+sensors.register("light", sensors.delay.fastest)
+ .on("change", l => {
+ light = l;
+ });
+//监听加速度传感器
+sensors.register("accelerometer", sensors.delay.fastest)
+ .on("change", (ax0, ay0, az0) => {
+ ax = ax0;
+ ay = ay0;
+ az = az0;
+ });
+
+var file = open(csvPath, "w");
+//写csv表格头
+file.writeline("light,ax,ay,az")
+//每0.5秒获取一次数据并写入文件
+setInterval(()=>{
+ file.writeline(util.format("%d,%d,%d,%d", light, ax, ay, az));
+}, 500);
+//10秒后退出并打开文件
+setTimeout(()=>{
+ file.close();
+ sensors.unregsiterAll();
+ app.viewFile(csvPath);
+}, 10 * 1000);
+
+
事件: 'accuracy_change'#
+
+accuracy
<number> 表示传感器精度。为以下值之一:
+- -1 传感器未连接
+- 0 传感器不可读
+- 1 低精度
+- 2 中精度
+- 3 高精度
-尽管id属性很方便,但也不总是最方便的,例如对于微信和网易云音乐,每次更新他的控件id都会变化,导致了相同代码对于不同版本的微信、网易云音乐并不兼容。
-除了这些属性外,主要还有以下几种属性:
-
-className
类名。类名表示一个控件的类型,例如文本控件为"android.widget.TextView", 图片控件为"android.widget.ImageView"等。
-packageName
包名。包名表示控件所在的应用包名,例如QQ界面的控件的包名为"com.tencent.mobileqq"。
-bounds
控件在屏幕上的范围。
-drawingOrder
控件在父控件的绘制顺序。
-indexInParent
控件在父控件的位置。
-clickable
控件是否可点击。
-longClickable
控件是否可长按。
-checkable
控件是否可勾选。
-checked
控件是否可已勾选。
-scrollable
控件是否可滑动。
-selected
控件是否已选择。
-editable
控件是否可编辑。
-visibleToUser
控件是否可见。
-enabled
控件是否已启用。
-depth
控件的布局深度。
+
-有时候只靠一个属性并不能唯一确定一个控件,这时需要通过属性的组合来完成定位,例如className("ImageView").depth(10).findOne().click()
,通过链式调用来组合条件。
-通常用这些技巧便可以解决大部分问题,即使解决不了问题,也可以通过布局分析的"生成代码"功能来尝试生成一些选择器代码。接下来的问题便是对选取的控件进行操作,包括:
+当传感器精度改变时会触发的事件。比较少用。
+
+
+shell即Unix Shell,在类Unix系统提供与操作系统交互的一系列命令。
+很多程序可以用来执行shell命令,例如终端模拟器。
+在Auto.js大致等同于用adb执行命令"adb shell"。其实现包括两种方式:
-click()
点击。点击一个控件,前提是这个控件的clickable属性为true
-longClick()
长按。长按一个控件,前提是这个控件的longClickable属性为true
-setText()
设置文本,用于编辑框控件设置文本。
-scrollForward()
, scrollBackward()
滑动。滑动一个控件(列表等), 前提是这个控件的scrollable属性为true
-exits()
判断控件是否存在
-waitFor()
等待控件出现
+- 通过
java.lang.Runtime.exec
执行(shell, Tap, Home等函数)
+- 通过内嵌终端模拟器执行(RootAutomator, Shell等对象)
-这些操作包含了绝大部分控件操作。根据这些我们可以很容易写出一个"刷屏"脚本(代码仅为示例,请不要在别人的群里测试,否则容易被踢):
-while(true){
- className("EditText").findOne().setText("刷屏...");
- text("发送").findOne().clicK();
-}
-
上面这段代码也可以写成:
-while(true){
- className("EditText").setText("刷屏...");
- text("发送").clicK();
-}
-
如果不加findOne()
而直接进行操作,则选择器会找出所有符合条件的控件并操作。
-另外一个比较常用的操作的滑动。滑动操作的第一步是找到需要滑动的控件,例如要滑动QQ消息列表则在悬浮窗布局层次分析中找到AbsListView
,这个控件就是消息列表控件,如下图:
-长按可查看控件信息,注意到其scrollable属性为true,并找出其id为"recent_chat_list",从而下滑QQ消息列表的代码为:
-id("recent_chat_list").className("AbsListView").findOne().scrollForward();
-
scrollForward()
为向前滑,包括下滑和右滑。
-选择器的入门教程暂且要这里,更多信息可以查看下面的文档和选择器进阶。
-selector()#
+shell函数#
+Stability: 2 - Stableshell(cmd[, root])#
创建一个新的选择器。但一般情况不需要使用该函数,因为可以直接用相应条件的语句创建选择器。
-由于历史遗留原因,本不应该这样设计(不应该让id()
, text()
等作为全局函数,而是应该用By.id()
, By.text()
),但为了后向兼容性只能保留这个设计。
-这样的API设计会污染全局变量,后续可能会支持"去掉这些全局函数而使用By.***"的选项。
-UiSelector.algorithm(algorithm)#
-[v4.1.0新增]
+一次性执行命令cmd, 并返回命令的执行结果。返回对象的其属性如下:
-algorithm
<string> 搜索算法,可选的值有:
-DFS
深度优先算法,选择器的默认算法
-BFS
广度优先算法
-
-
-
-指定选择器的搜索算法。例如:
-
log(selector().text("文本").algorithm("BFS").find());
-
广度优先在控件所在层次较低时,或者布局的层次不多时,通常能更快找到控件。
-UiSelector.text(str)#
-
-str
<string> 控件文本
-- 返回 <UiSelector> 返回选择器自身以便链式调用
-
-为当前选择器附加控件"text等于字符串str"的筛选条件。
-控件的text(文本)属性是文本控件上的显示的文字,例如微信左上角的"微信"文本。
-UiSelector.textContains(str)#
-
-为当前选择器附加控件"text需要包含字符串str"的筛选条件。
-这是一个比较有用的条件,例如QQ动态页和微博发现页上方的"大家都在搜...."的控件可以用textContains("大家都在搜").findOne()
来获取。
-UiSelector.textStartsWith(prefix)#
+示例(强制停止微信) :
+var result = shell("am force-stop com.tencent.mm", true);
+log(result);
+console.show();
+if(result.code == 0){
+ toast("执行成功");
+}else{
+ toast("执行失败!请到控制台查看错误信息");
+}
+
Shell#
+Stability: 2 - Stableshell函数通过用来一次性执行单条命令并获取结果。如果有多条命令需要执行,用Shell对象的效率更高。这是因为,每次运行shell函数都会打开一个单独的shell进程并在运行结束后关闭他,这个过程需要一定的时间;而Shell对象自始至终使用同一个shell进程。
+new Shell(root)#
为当前选择器附加控件"text需要以prefix开头"的筛选条件。
-这也是一个比较有用的条件,例如要找出Auto.js脚本列表中名称以"QQ"开头的脚本的代码为textStartsWith("QQ").find()
。
-UiSelector.textEndsWith(suffix)#
+
- width <number> 屏幕宽度,单位像素
- height <number> 屏幕高度,单位像素 @@ -1536,9 +1727,9 @@
x
<number> 要点击的坐标的x值y
<number> 要点击的坐标的y值
@@ -1546,14 +1737,14 @@ x
<number> 要按住的坐标的x值y
<number> 要按住的坐标的y值
@@ -1568,7 +1759,7 @@ x1
<number> 滑动的起始坐标的x值y1
<number> 滑动的起始坐标的y值
@@ -1578,18 +1769,18 @@ duration
<number> 手势的时长- [x, y] ... 手势滑动路径的一系列坐标
x
<number> 横坐标y
<number> 纵坐标
@@ -1616,7 +1807,7 @@ x
<number> 横坐标y
<number> 纵坐标
@@ -1643,26 +1834,26 @@ id
<number> 多点触摸id,可选,默认为1- x, y <number> 要点击的坐标。
mode
<string> 模式
-fast
快速模式。该模式下会启用控件缓存,从而选择器获取屏幕控件更快。对于需要快速的控件操作的脚本可以使用该模式,一般脚本则没有必要使用该函数。
-normal
正常模式,默认。
+
+accelerometer
加速度传感器,参数(event, ax, ay, az)
:-
+
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+ax
<number> x轴上的加速度,单位m/s^2
+ay
<number> y轴上的加速度,单位m/s^2
+
+az
<number> z轴上的加速度,单位m/s^2 +这里的x轴,y轴,z轴所属的坐标系统如下图(其中z轴垂直于设备屏幕表面):!
+
如果不加mode参数,则为正常模式。
-建议使用
-auto.waitFor()
和auto.setMode()
代替该函数,因为auto()
函数如果无障碍服务未启动会停止脚本;而auto.waitFor()
则会在在无障碍服务启动后继续运行。示例:
-auto("fast"); -
示例2:
-auto(); -
auto.waitFor()#
-检查无障碍服务是否已经启用,如果没有启用则跳转到无障碍服务启用界面,并等待无障碍服务启动;当无障碍服务启动后脚本会继续运行。
-因为该函数是阻塞的,因此除非是有协程特性,否则不能在ui模式下运行该函数,建议在ui模式下使用
-auto()
函数。auto.setMode(mode)#
--
-
mode
<string> 模式
+
+
+orientation
方向传感器,参数(event, azimuth, pitch, roll)
:-
+
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+azimuth
<number> 方位角,从地磁指北方向线起,依顺时针方向到y轴之间的水平夹角,单位角度,范围0~359
+pitch
<number> 绕x轴旋转的角度,当设备水平放置时该值为0,当设备顶部翘起时该值为正数,当设备尾部翘起时该值为负数,单位角度,范围-180~180
+roll
<number> 绕y轴顺时针旋转的角度,单位角度,范围-90~90
设置无障碍模式为mode。mode的可选值为:
+
+gyroscope
陀螺仪传感器,参数(event, wx, wy, wz)
:-
-
fast
快速模式。该模式下会启用控件缓存,从而选择器获取屏幕控件更快。对于需要快速的控件查看和操作的脚本可以使用该模式,一般脚本则没有必要使用该函数。
-normal
正常模式,默认。
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+wx
<number> 绕x轴的角速度,单位弧度/s
+wy
<number> 绕y轴的角速度,单位弧度/s
+wz
<number> 绕z轴的角速度,单位弧度/s
auto.setFlags(flags)#
-[v4.1.0新增]
+
+magnetic_field
磁场传感器,参数(event, bx, by, bz)
:-
-
flags
<string> | <Array> 一些标志,来启用和禁用某些特性,包括:-
-
findOnUiThread
使用该特性后,选择器搜索时会在主进程进行。该特性用于解决线程安全问题导致的次生问题,不过目前貌似已知问题并不是线程安全问题。
-useUsageStats
使用该特性后,将会以"使用情况统计"服务的结果来检测当前正在运行的应用包名(需要授予"查看使用情况统计"权限)。如果觉得currentPackage()返回的结果不太准确,可以尝试该特性。
-useShell
使用该特性后,将使用shell命令获取当前正在运行的应用的包名、活动名称,但是需要root权限。
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+bx
<number> x轴上的磁场强度,单位uT
+by
<number> y轴上的磁场强度,单位uT
+bz
<number> z轴上的磁场强度,单位uT
+
+gravity
重力传感器,参数(event, gx, gy, gz)
:-
+
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+gx
<number> x轴上的重力加速度,单位m/s^2
+gy
<number> y轴上的重力加速度,单位m/s^2
+gz
<number> z轴上的重力加速度,单位m/s^2
启用有关automator的一些特性。例如:
-auto.setFlags(["findOnUiThread", "useShell"]); -
auto.serivce#
-[v4.1.0新增]
+
+linear_acceleration
线性加速度传感器,参数(event, ax, ay, az)
:-
-
- AccessibilityService +
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+ax
<number> x轴上的线性加速度,单位m/s^2
+ay
<number> y轴上的线性加速度,单位m/s^2
+az
<number> z轴上的线性加速度,单位m/s^2
获取无障碍服务。如果无障碍服务没有启动,则返回
- -null
。auto.windows#
-[v4.1.0新增]
+
+ambient_temperature
环境温度传感器,大部分设备并不支持,参数(event, t)
:-
-
- <Array> +
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+t
<number> 环境温度,单位摄氏度。
当前所有窗口(AccessibilityWindowInfo)的数组,可能包括状态栏、输入法、当前应用窗口,弹出窗口、悬浮窗、分屏应用窗口等。可以分别获取每个窗口的布局信息。
-该函数需要Android 5.0以上才能运行。
-auto.root#
-[v4.1.0新增]
+
+light
光线传感器,参数(event, light)
:-
-
- <UiObject> +
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+light
<number> 环境光强度,单位lux
当前窗口的布局根元素。如果无障碍服务未启动或者WindowFilter均返回false,则会返回
-null
。如果不设置windowFilter,则当前窗口即为活跃的窗口(获取到焦点、正在触摸的窗口);如果设置了windowFilter,则获取的是过滤的窗口中的第一个窗口。
-如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素。
-auto.rootInActiveWindow#
-[v4.1.0新增]
+
+pressure
压力传感器,参数(event, p)
:-
-
- <UiObject> +
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+p
<number> 大气压,单位hPa
当前活跃的窗口(获取到焦点、正在触摸的窗口)的布局根元素。如果无障碍服务未启动则为
-null
。auto.setWindowFilter(filter)#
-[v4.1.0新增]
+
+proximity
距离传感器,参数(event, distance)
:-
-
filter
<Function> 参数为窗口(AccessibilityWindowInfo),返回值为Boolean的函数。
+event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+distance
<number> 一般指设备前置摄像头旁边的距离传感器到前方障碍物的距离,并且很多设备上这个值只有两种情况:当障碍物较近时该值为0,当障碍物较远或在范围内没有障碍物时该值为5
设置窗口过滤器。这个过滤器可以决定哪些窗口是目标窗口,并影响选择器的搜索。例如,如果想要选择器在所有窗口(包括状态栏、输入法等)中搜索,只需要使用以下代码:
-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#
-[v4.1.0新增]
+
+relative_humidity
湿度传感器,大部分设备并不支持,参数(event, rh)
:-
-
- <Array> +
event
SensorEvent 传感器事件,用于获取传感器数据变化时的所有信息
+rh
<number> 相对湿度,范围为0~100(百分比)
返回当前被WindowFilter过滤的窗口的布局根元素组成的数组。
-如果系统是Android5.0以下,则始终返回当前活跃的窗口的布局根元素的数组。
-SimpleActionAutomator#
-Stability: 2 - StableSimpleActionAutomator提供了一些模拟简单操作的函数,例如点击文字、模拟按键等。这些函数可以直接作为全局函数使用。
-click(text[, i])#
-返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。
-该函数可以点击大部分包含文字的按钮。例如微信主界面下方的"微信", "联系人", "发现", "我"的按钮。
-
通常与while同时使用以便点击按钮直至成功。例如:while(!click("扫一扫")); -
当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部点击成功。
-i是从0开始计算的, 也就是,
-click("啦啦啦", 0)
表示点击屏幕上第一个"啦啦啦",click("啦啦啦", 1)
表示点击屏幕上第二个"啦啦啦"。-
-文本所在区域指的是,从文本处向其父视图寻找,直至发现一个可点击的部件为止。
-click(left, top, bottom, right)#
+sensors.register(sensorName[, delay])#
-
-
left
<number> 要点击的长方形区域左边与屏幕左边的像素距离
-top
<number> 要点击的长方形区域上边与屏幕上边的像素距离
-bottom
<number> 要点击的长方形区域下边与屏幕下边的像素距离
-right
<number> 要点击的长方形区域右边与屏幕右边的像素距离
+sensorName
<string> 传感器名称,常用的传感器名称如上面所述
+delay
<number> 传感器数据更新频率,可选,默认为sensors.delay.normal
。可用的值如下:-
+
sensors.delay.normal
正常频率
+sensors.delay.ui
适合于用户界面的更新频率
+sensors.delay.game
适合于游戏的更新频率
+sensors.delay.fastest
最快的更新频率】
注意,该函数一般只用于录制的脚本中使用,在自己写的代码中使用该函数一般不要使用该函数。
-点击在指定区域的控件。当屏幕中并未包含与该区域严格匹配的区域,或者该区域不能点击时返回false,否则返回true。
-有些按钮或者部件是图标而不是文字(例如发送朋友圈的照相机图标以及QQ下方的消息、联系人、动态图标),这时不能通过
-click(text, i)
来点击,可以通过描述图标所在的区域来点击。left, bottom, top, right描述的就是点击的区域。至于要定位点击的区域,可以在悬浮窗使用布局分析工具查看控件的bounds属性。
-通过无障碍服务录制脚本会生成该语句。
-longClick(text[, i]))#
--
-
text
<string> 要长按的文本
-i
<number> 如果相同的文本在屏幕中出现多次,则i表示要长按第几个文本, i从0开始计算
+
+- 返回 SensorEventEmiiter
返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。
-当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部长按成功。
-scrollUp([i])#
+
i
<number> 要滑动的控件序号
+emiiter
SensorEventEmitter..args
<Any> 传感器参数- QQ的控件的id属性很多都是"name",也就是在QQ界面难以通过id来定位一个控件 -
- 列表中的控件,比如QQ联系人列表,微信联系人列表等 +
accuracy
<number> 表示传感器精度。为以下值之一:-
+
- -1 传感器未连接 +
- 0 传感器不可读 +
- 1 低精度 +
- 2 中精度 +
- 3 高精度
尽管id属性很方便,但也不总是最方便的,例如对于微信和网易云音乐,每次更新他的控件id都会变化,导致了相同代码对于不同版本的微信、网易云音乐并不兼容。
-除了这些属性外,主要还有以下几种属性:
--
-
className
类名。类名表示一个控件的类型,例如文本控件为"android.widget.TextView", 图片控件为"android.widget.ImageView"等。
-packageName
包名。包名表示控件所在的应用包名,例如QQ界面的控件的包名为"com.tencent.mobileqq"。
-bounds
控件在屏幕上的范围。
-drawingOrder
控件在父控件的绘制顺序。
-indexInParent
控件在父控件的位置。
-clickable
控件是否可点击。
-longClickable
控件是否可长按。
-checkable
控件是否可勾选。
-checked
控件是否可已勾选。
-scrollable
控件是否可滑动。
-selected
控件是否已选择。
-editable
控件是否可编辑。
-visibleToUser
控件是否可见。
-enabled
控件是否已启用。
-depth
控件的布局深度。
+
click()
点击。点击一个控件,前提是这个控件的clickable属性为true
-longClick()
长按。长按一个控件,前提是这个控件的longClickable属性为true
-setText()
设置文本,用于编辑框控件设置文本。
-scrollForward()
,scrollBackward()
滑动。滑动一个控件(列表等), 前提是这个控件的scrollable属性为true
-exits()
判断控件是否存在
-waitFor()
等待控件出现
+- 通过
java.lang.Runtime.exec
执行(shell, Tap, Home等函数)
+ - 通过内嵌终端模拟器执行(RootAutomator, Shell等对象)
algorithm
<string> 搜索算法,可选的值有:-
-
DFS
深度优先算法,选择器的默认算法
-BFS
广度优先算法
-
-
基于坐标的触摸模拟#
+安卓7.0以上的触摸和手势模拟#
注意以下命令只有Android7.0及以上才有效
-click(x, y)#
+click(x, y)#
click(x, y)#
+longClick(x, y)#
模拟长按坐标(x, y), 并返回是否成功。只有在长按执行完成(大约600毫秒)时脚本才会继续执行。
一般而言,只有长按过程中被其他事件中断(例如用户自行点击)才会长按失败。
-press(x, y, duration)#
+press(x, y, duration)#
press(x, y, duration)#
+swipe(x1, y1, x2, y2, duration)#
press(x, y, duration)#
+gesture(duration, [x1, y1], [x2, y2], ...)#
模拟手势操作。例如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], ...], ...)#
+gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [x3, y3], [x4, y4], ...], ...)#
同时模拟多个手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。
例如手指捏合:
gestures([0, 500, [800, 300], [500, 1000]],
[0, 500, [300, 1500], [500, 1000]]);
-
RootAutomator#
+RootAutomator#
RootAutomator是一个使用root权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。
一个脚本中最好只存在一个RootAutomator,并且保证脚本结束退出他。可以在exit事件中退出RootAutomator,例如:
var ra = new RootAutomator();
@@ -1600,7 +1791,7 @@ gestures([delay1, duration1, [x1, y1], [x2, y2], ...], [delay2, duration2, [
...
注意以下命令需要root权限
-RootAutomator.tap(x, y[, id])#
+RootAutomator.tap(x, y[, id])#
RootAutomator.tap(x, y[, id])#
+RootAutomator.swipe(x1, x2, y1, y2[, duration, id])#
模拟一次从(x1, y1)到(x2, y2)的时间为duration毫秒的滑动。
-RootAutomator.press(x, y, duration[, id])#
+RootAutomator.press(x, y, duration[, id])#
模拟按下位置(x, y),时长为duration毫秒。
-RootAutomator.longPress(x, y[\, id])#
+RootAutomator.longPress(x, y[\, id])#
RootAutomator.longPress(x, y[\, id])#
+RootAutomator.touchDown(x, y[, id])#
模拟手指按下位置(x, y)。
-RootAutomator.touchMove(x, y[, id])#
+RootAutomator.touchMove(x, y[, id])#
模拟移动手指到位置(x, y)。
-RootAutomator.touchUp([id])#
+RootAutomator.touchUp([id])#
模拟手指弹起。
-使用root权限点击和滑动的简单命令#
+使用root权限点击和滑动的简单命令#
注意:本章节的函数在后续版本很可能有改动!请勿过分依赖本章节函数的副作用。推荐使用RootAutomator
代替本章节的触摸函数。
以下函数均需要root权限,可以实现任意位置的点击、滑动等。
-
@@ -1683,19 +1874,19 @@
使用root权限点击和滑动的简单命令#
+Tap(x, y)#
点击位置(x, y), 您可以通过"开发者选项"开启指针位置来确定点击坐标。
-Swipe(x1, y1, x2, y2, [duration])#
+Swipe(x1, y1, x2, y2, [duration])#
滑动。从(x1, y1)位置滑动到(x2, y2)位置。 -
+Crypto#
@@ -4870,2601 +5061,2601 @@module (模块)#
-基于控件的操作指的是选择屏幕上的控件,获取其信息或对其进行操作。对于一般软件而言,基于控件的操作对不同机型有很好的兼容性;但是对于游戏而言,由于游戏界面并不是由控件构成,无法采用本章节的方法,也无法使用本章节的函数。有关游戏脚本的编写,请参考《基于坐标的操作》。
-基于控件的操作依赖于无障碍服务,因此最好在脚本开头使用auto()
函数来确保无障碍服务已经启用。如果运行到某个需要权限的语句无障碍服务并没启动,则会抛出异常并跳转到无障碍服务界面。这样的用户体验并不好,因为需要重新运行脚本,后续会加入等待无障碍服务启动并让脚本继续运行的函数。
您也可以在脚本开头使用"auto";
表示这个脚本需要无障碍服务,但是不推荐这种做法,因为这个标记必须在脚本的最开头(前面不能有注释或其他语句、空格等),我们推荐使用auto()
函数来确保无障碍服务已启用。
auto([mode])#
--
-
检查无障碍服务是否已经启用,如果没有启用则抛出异常并跳转到无障碍服务启用界面;同时设置无障碍模式为mode。mode的可选值为:
+ +Sensors#
+sensors模块提供了获取手机上的传感器的信息的支持,这些传感器包括距离传感器、光线光感器、重力传感器、方向传感器等。需要指出的是,脚本只能获取传感器的数据,不能模拟或伪造传感器的数据和事件,因此诸如模拟摇一摇的功能是无法实现的。
+要监听一个传感器时,需要使用sensors.register()
注册监听器,之后才能开始监听;不需要监听时则调用sensors.unregister()
注销监听器。在脚本结束时会自动注销所有的监听器。同时,这种监听会使脚本保持运行状态,如果不注销监听器,脚本会一直保持运行状态。
例如,监听光线传感器的代码为:
+//光线传感器监听
+sensors.register("light").on("change", (event, light)=>{
+ log("当前光强度为", light);
+});
+
要注意的是,每个传感器的数据并不相同,所以对他们调用on()
监听事件时的回调函数参数也不是相同,例如光线传感器参数为(event, light)
,加速度传感器参数为(event, ax, ay, az)
。甚至在某些设备上的传感器参数有所增加,例如华为手机的距离传感器为三个参数,一般手机只有一个参数。
常用的传感器及其事件参数如下表:
-
-
注册一个传感器监听并返回SensorEventEmitter。
+例如:
+console.show();
+//注册传感器监听
+var sensor = sensors.register("gravity");
+if(sensor == null){
+ toast("不支持重力传感器");
+ exit();
+}
+//监听数据
+sensor.on("change", (gx, gy, gz)=>{
+ log("重力加速度: %d, %d, %d", gx, gy, gz);
+});
+
可以通过delay参数来指定传感器数据的更新频率,例如:
+var sensor = sensors.register("gravity", sensors.delay.game);
+
另外,如果不支持sensorName
所指定的传感器,那么该函数将返回null
;但如果sensors.ignoresUnsupportedSensor
的值被设置为true
, 则该函数会返回一个不会分发任何传感器事件的SensorEventEmitter。
例如:
+sensors.ignoresUnsupportedSensor = true;
+//无需null判断
+sensors.register("gravity").on("change", (gx, gy, gz)=>{
+ log("重力加速度: %d, %d, %d", gx, gy, gz);
+});
+
更多信息,参见SensorEventEmitter和sensors.ignoresUnsupportedSensor。
+sensors.unregister(emitter)#
-
-
找到第i+1个可滑动控件上滑或左滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。
-另外不加参数时scrollUp()
会寻找面积最大的可滑动的控件上滑或左滑,例如微信消息列表等。
参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)
为滑动第一个可滑动控件。
scrollDown([i])#
+注销该传感器监听器。被注销的监听器将不再能监听传感器数据。
+//注册一个传感器监听器
+var sensor = sensors.register("gravity");
+if(sensor == null){
+ exit();
+}
+//2秒后注销该监听器
+setTimeout(()=> {
+ sensors.unregister(sensor);
+}, 2000);
+
sensors.unregisterAll()#
+注销所有传感器监听器。
+sensors.ignoresUnsupportedSensor#
找到第i+1个可滑动控件下滑或右滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。
-另外不加参数时scrollUp()
会寻找面积最大的可滑动的控件下滑或右滑。
参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)
为滑动第一个可滑动控件。
setText([i, ]text)#
+表示是否忽略不支持的传感器。如果该值被设置为true
,则函数sensors.register()
即使对不支持的传感器也会返回一个无任何数据的虚拟传感器监听,也就是sensors.register()
不会返回null
从而避免非空判断,并且此时会触发sensors
的"unsupported_sensor"事件。
//忽略不支持的传感器
+sensors.ignoresUnsupportedSensor = true;
+//监听有不支持的传感器时的事件
+sensors.on("unsupported_sensor", function(sensorName){
+ toastLog("不支持的传感器: " + sensorName);
+});
+//随便注册一个不存在的传感器。
+log(sensors.register("aaabbb"));
+
事件: 'unsupported_sensor'#
返回是否输入成功。当找不到对应的文本框时返回false。
-不加参数i则会把所有输入框的文本都置为text。例如setText("测试")
。
这里的输入文本的意思是,把输入框的文本置为text,而不是在原来的文本上追加。
-input([i, ]text)#
-当sensors.ignoresUnsupportedSensor
被设置为true
并且有不支持的传感器被注册时触发该事件。事件参数的传感器名称。
SensorEventEmitter#
+注册传感器返回的对象,其本身是一个EventEmmiter,用于监听传感器事件。
+事件: 'change'#
+-
+
返回是否输入成功。当找不到对应的文本框时返回false。
-不加参数i则会把所有输入框的文本追加内容text。例如input("测试")
。
UiSelector#
-UiSelector即选择器,用于通过各种条件选取屏幕上的控件,再对这些控件进行点击、长按等动作。这里需要先简单介绍一下控件和界面的相关知识。
-一般软件的界面是由一个个控件构成的,例如图片部分是一个图片控件(ImageView),文字部分是一个文字控件(TextView);同时,通过各种布局来决定各个控件的位置,例如,线性布局(LinearLayout)里面的控件都是按水平或垂直一次叠放的,列表布局(AbsListView)则是以列表的形式显示控件。
-控件有各种属性,包括文本(text), 描述(desc), 类名(className), id等等。我们通常用一个控件的属性来找到这个控件,例如,想要点击QQ聊天窗口的"发送"按钮,我们就可以通过他的文本属性为"发送"来找到这个控件并点击他,具体代码为:
-var sendButton = text("发送").findOne();
-sendButton.click();
-
在这个例子中, text("发送")
表示一个条件(文本属性为"发送"),findOne()
表示基于这个条件找到一个符合条件的控件,从而我们可以得到发送按钮sendButton,再执行sendButton.click()
即可点击"发送"按钮。
用文本属性来定位按钮控件、文本控件通常十分有效。但是,如果一个控件是图片控件,比如Auto.js主界面右上角的搜索图标,他没有文本属性,这时需要其他属性来定位他。我们如何查看他有什么属性呢?首先打开悬浮窗和无障碍服务,点击蓝色的图标(布局分析), 可以看到以下界面:
-之后我们点击搜索图标,可以看到他有以下属性:
-我们注意到这个图标的desc(描述)属性为"搜索",那么我们就可以通过desc属性来定位这个控件,得到点击搜索图标的代码为:
-desc("搜索").findOne().click();
-
可能心细的你可能注意到了,这个控件还有很多其他的属性,例如checked, className, clickable等等,为什么不用这些属性来定位搜索图标呢?答案是,其他控件也有这些值相同的属性、尝试一下你就可以发现很多其他控件的checked属性和搜索控件一样都是false
,如果我们用checked(false)
作为条件,将会找到很多控件,而无法确定哪一个是搜索图标。因此,要找到我们想要的那个控件,选择器的条件通常需要是可唯一确定控件的。我们通常用一个独一无二的属性来定位一个控件,例如这个例子中就没有其他控件的desc(描述)属性为"搜索"。
另外,对于这个搜索图标而言,id属性也是唯一的,我们也可以用id("action_search").findOne().click()
来点击这个控件。如果一个控件有id属性,那么这个属性很可能是唯一的,除了以下几种情况:
-
-
当传感器数据改变时触发该事件;该事件触发的最高频繁由sensors.register()
指定的delay参数决定。
事件参数根据传感器类型不同而不同,具体参见本章最前面的列表。
+一个监听光线传感器和加速度传感器并且每0.5秒获取一个数据并最终写入一个csv表格文件的例子如下:
+//csv文件路径
+cosnt csvPath = "/sdcard/sensors_data.csv";
+//记录光线传感器的数据
+var light = 0;
+//记录加速度传感器的数据
+var ax = 0;
+var ay = 0;
+var az = 0;
+//监听光线传感器
+sensors.register("light", sensors.delay.fastest)
+ .on("change", l => {
+ light = l;
+ });
+//监听加速度传感器
+sensors.register("accelerometer", sensors.delay.fastest)
+ .on("change", (ax0, ay0, az0) => {
+ ax = ax0;
+ ay = ay0;
+ az = az0;
+ });
+
+var file = open(csvPath, "w");
+//写csv表格头
+file.writeline("light,ax,ay,az")
+//每0.5秒获取一次数据并写入文件
+setInterval(()=>{
+ file.writeline(util.format("%d,%d,%d,%d", light, ax, ay, az));
+}, 500);
+//10秒后退出并打开文件
+setTimeout(()=>{
+ file.close();
+ sensors.unregsiterAll();
+ app.viewFile(csvPath);
+}, 10 * 1000);
+
+
事件: 'accuracy_change'#
+-
+
有时候只靠一个属性并不能唯一确定一个控件,这时需要通过属性的组合来完成定位,例如className("ImageView").depth(10).findOne().click()
,通过链式调用来组合条件。
通常用这些技巧便可以解决大部分问题,即使解决不了问题,也可以通过布局分析的"生成代码"功能来尝试生成一些选择器代码。接下来的问题便是对选取的控件进行操作,包括:
+当传感器精度改变时会触发的事件。比较少用。
+ + +shell即Unix Shell,在类Unix系统提供与操作系统交互的一系列命令。
+很多程序可以用来执行shell命令,例如终端模拟器。
+在Auto.js大致等同于用adb执行命令"adb shell"。其实现包括两种方式:
-
-
这些操作包含了绝大部分控件操作。根据这些我们可以很容易写出一个"刷屏"脚本(代码仅为示例,请不要在别人的群里测试,否则容易被踢):
-while(true){
- className("EditText").findOne().setText("刷屏...");
- text("发送").findOne().clicK();
-}
-
上面这段代码也可以写成:
-while(true){
- className("EditText").setText("刷屏...");
- text("发送").clicK();
-}
-
如果不加findOne()
而直接进行操作,则选择器会找出所有符合条件的控件并操作。
另外一个比较常用的操作的滑动。滑动操作的第一步是找到需要滑动的控件,例如要滑动QQ消息列表则在悬浮窗布局层次分析中找到AbsListView
,这个控件就是消息列表控件,如下图:
长按可查看控件信息,注意到其scrollable属性为true,并找出其id为"recent_chat_list",从而下滑QQ消息列表的代码为:
-id("recent_chat_list").className("AbsListView").findOne().scrollForward();
-
scrollForward()
为向前滑,包括下滑和右滑。
选择器的入门教程暂且要这里,更多信息可以查看下面的文档和选择器进阶。
-selector()#
+shell函数#
+shell(cmd[, root])#
创建一个新的选择器。但一般情况不需要使用该函数,因为可以直接用相应条件的语句创建选择器。
-由于历史遗留原因,本不应该这样设计(不应该让id()
, text()
等作为全局函数,而是应该用By.id()
, By.text()
),但为了后向兼容性只能保留这个设计。
这样的API设计会污染全局变量,后续可能会支持"去掉这些全局函数而使用By.***"的选项。
-UiSelector.algorithm(algorithm)#
-[v4.1.0新增]
+一次性执行命令cmd, 并返回命令的执行结果。返回对象的其属性如下:
-
-
指定选择器的搜索算法。例如:
-log(selector().text("文本").algorithm("BFS").find());
-
广度优先在控件所在层次较低时,或者布局的层次不多时,通常能更快找到控件。
-UiSelector.text(str)#
--
-
str
<string> 控件文本
-- 返回 <UiSelector> 返回选择器自身以便链式调用 -
为当前选择器附加控件"text等于字符串str"的筛选条件。
-控件的text(文本)属性是文本控件上的显示的文字,例如微信左上角的"微信"文本。
-UiSelector.textContains(str)#
-为当前选择器附加控件"text需要包含字符串str"的筛选条件。
-这是一个比较有用的条件,例如QQ动态页和微博发现页上方的"大家都在搜...."的控件可以用textContains("大家都在搜").findOne()
来获取。
UiSelector.textStartsWith(prefix)#
+示例(强制停止微信) :
+var result = shell("am force-stop com.tencent.mm", true);
+log(result);
+console.show();
+if(result.code == 0){
+ toast("执行成功");
+}else{
+ toast("执行失败!请到控制台查看错误信息");
+}
+
Shell#
+shell函数通过用来一次性执行单条命令并获取结果。如果有多条命令需要执行,用Shell对象的效率更高。这是因为,每次运行shell函数都会打开一个单独的shell进程并在运行结束后关闭他,这个过程需要一定的时间;而Shell对象自始至终使用同一个shell进程。
+new Shell(root)#
为当前选择器附加控件"text需要以prefix开头"的筛选条件。
-这也是一个比较有用的条件,例如要找出Auto.js脚本列表中名称以"QQ"开头的脚本的代码为textStartsWith("QQ").find()
。
UiSelector.textEndsWith(suffix)#
+Shell对象的"构造函数"。
+var sh = new Shell(true);
+//强制停止微信
+sh.exec("am force-stop com.tencent.mm");
+sh.exit();
+
Shell.exec(cmd)#
为当前选择器附加控件"text需要以suffix结束"的筛选条件。
-UiSelector.textMatches(reg)#
+执行命令cmd。该函数不会返回任何值。
+注意,命令执行是"异步"的、非阻塞的。也就是不会等待命令完成后才继续向下执行。
+尽管这样的设计使用起来有很多不便之处,但受限于终端模拟器,暂时没有解决方式;如果后续能找到解决方案,则将提供Shell.execAndWaitFor
函数。
Shell.exit()#
+直接退出shell。正在执行的命令会被强制退出。
+Shell.exitAndWaitFor()#
+执行"exit"命令并等待执行命令执行完成、退出shell。
+此函数会执行exit命令来正常退出shell。
+Shell.setCallback(callback)#
为当前选择器附加控件"text需要满足正则表达式reg"的条件。
-有关正则表达式,可以查看正则表达式 - 菜鸟教程。
-需要注意的是,如果正则表达式是字符串,则需要使用\\
来表达\
(也即Java正则表达式的形式),例如textMatches("\\d+")
匹配多位数字;但如果使用JavaScript语法的正则表达式则不需要,例如textMatches(/\d+/)
。但如果使用字符串的正则表达式则该字符串不能以"/"同时以"/"结束,也即不能写诸如textMatches("/\\d+/")
的表达式,否则会被开头的"/"和结尾的"/"会被忽略。
UiSelector.desc(str)#
--
-
str
<string> 控件文本
-- 返回 <UiSelector> 返回选择器自身以便链式调用 +
设置该Shell的回调函数,以便监听Shell的输出。可以包括以下属性:
+-
+
- onOutput <Function> 每当shell有新的输出时便会调用该函数。其参数是一个字符串。 +
- onNewLine <Function> 每当shell有新的一行输出时便会调用该函数。其参数是一个字符串(不包括最后的换行符)。
为当前选择器附加控件"desc等于字符串str"的筛选条件。
-控件的desc(描述,全称为Content-Description)属性是对一个控件的描述,例如网易云音乐右上角的放大镜图标的描述为搜索。要查看一个控件的描述,同样地可以借助悬浮窗查看。
-desc属性同样是定位控件的利器。
-UiSelector.descContains(str)#
--
-
str
<string> 要包含的字符串
+
例如:
+var sh = new Shell();
+sh.setCallback({
+ onNewLine: function(line){
+ //有新的一行输出时打印到控制台
+ log(line);
+ }
+})
+while(true){
+ //循环输入命令
+ var cmd = dialogs.rawInput("请输入要执行的命令,输入exit退出");
+ if(cmd == "exit"){
+ break;
+ }
+ //执行命令
+ sh.exec(cmd);
+}
+sh.exit();
+
附录: shell命令简介#
+以下关于shell命令的资料来自AndroidStudio用户指南:Shell命令。
+am命令#
+am命令即Activity Manager命令,用于管理应用程序活动、服务等。
+以下命令均以"am "开头,例如shell('am start -p com.tencent.mm');
(启动微信)
start [options] intent#
+启动 intent 指定的 Activity(应用程序活动)。
请参阅 intent 参数的规范。
选项包括:
+-
+
- -D:启用调试。 +
- -W:等待启动完成。 +
- --start-profiler file:启动分析器并将结果发送到 file。 +
- -P file:类似于 --start-profiler,但当应用进入空闲状态时分析停止。 +
- -R count:重复 Activity 启动 count 次数。在每次重复前,将完成顶部 Activity。 +
- -S:启动 Activity 前强行停止目标应用。 +
- --opengl-trace:启用 OpenGL 函数的跟踪。 +
- --user user_id | current:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
为当前选择器附加控件"desc需要包含字符串str"的筛选条件。
-UiSelector.descStartsWith(prefix)#
--
-
prefix
<string> 前缀
+- --user user_id | current:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
startservice [options] intent#
+启动 intent 指定的 Service(服务)。
请参阅 intent 参数的规范。
选项包括:
-
+
为当前选择器附加控件"desc需要以prefix开头"的筛选条件。
-UiSelector.descEndsWith(suffix)#
-为当前选择器附加控件"desc需要以suffix结束"的筛选条件。
-UiSelector.descMatches(reg)#
--
-
reg
<string> | <Regex> 要满足的正则表达式。
-
为当前选择器附加控件"desc需要满足正则表达式reg"的条件。
-有关正则表达式,可以查看正则表达式 - 菜鸟教程。
-需要注意的是,如果正则表达式是字符串,则需要使用\\
来表达\
(也即Java正则表达式的形式),例如textMatches("\\d+")
匹配多位数字;但如果使用JavaScript语法的正则表达式则不需要,例如textMatches(/\d+/)
。但如果使用字符串的正则表达式则该字符串不能以"/"同时以"/"结束,也即不能写诸如textMatches("/\\d+/")
的表达式,否则会被开头的"/"和结尾的"/"会被忽略。
UiSelector.id(resId)#
--
-
resId
<string> 控件的id,以"包名:id/"开头,例如"com.tencent.mm:id/send_btn"。也可以不指定包名,这时会以当前正在运行的应用的包名来补全id。例如id("send_btn"),在QQ界面想当于id("com.tencent.mobileqq:id/send_btn")。
-
为当前选择器附加"id等于resId"的筛选条件。
-控件的id属性通常是可以用来确定控件的唯一标识,如果一个控件有id,那么使用id来找到他是最好的方法。要查看屏幕上的控件的id,可以开启悬浮窗并使用界面工具,点击相应控件即可查看。若查看到的控件id为null, 表示该控件没有id。另外,在列表中会出现多个控件的id相同的情况。例如微信的联系人列表,每个头像的id都是一样的。此时不能用id来唯一确定控件。
-在QQ界面经常会出现多个id为"name"的控件,在微信上则每个版本的id都会变化。对于这些软件而言比较难用id定位控件。
-UiSelector.idContains(str)#
--
-
str
<string> id要包含的字符串
-
为当前选择器附加控件"id包含字符串str"的筛选条件。比较少用。
-UiSelector.idStartsWith(prefix)#
--
-
prefix
<string> id前缀
-
为当前选择器附加"id需要以prefix开头"的筛选条件。比较少用。
-UiSelector.idEndsWith(suffix)#
--
-
suffix
<string> id后缀
+- [--user user_id | all | current]:指定要发送到的用户;如果未指定,则发送到所有用户。
kill-all#
+终止所有后台进程。
+broadcast [options] intent#
+发出广播 intent。 +请参阅 intent 参数的规范。
+选项包括:
+-
+
为当前选择器附加"id需要以suffix结束"的筛选条件。比较少用。
-UiSelector.idMatches(reg)#
--
-
- reg <Regex> | <string> id要满足的正则表达式 +
- -r:输出原始结果(否则对 report_key_streamresult 进行解码)。与 [-e perf true] 结合使用以生成性能测量的原始输出。 +
- -e name value:将参数 name 设为 value。对于测试运行器,通用表单为 -e testrunner_flag value[,value...]。 +
- -p file:将分析数据写入 file。 +
- -w:先等待仪器完成,然后再返回。测试运行器需要使用此选项。 +
- --no-window-animation:运行时关闭窗口动画。 +
- --user user_id | current:指定仪器在哪个用户中运行;如果未指定,则在当前用户中运行。 +
- profile start process file 启动 process 的分析器,将结果写入 file。 +
- profile stop process 停止 process 的分析器。
instrument [options] component#
+使用 Instrumentation 实例启动监控。通常,目标 component 是表单 test_package/runner_class。
选项包括:
-
+
附加id需要满足正则表达式。
-需要注意的是,如果正则表达式是字符串,则需要使用\\
来表达\
(也即Java正则表达式的形式),例如textMatches("\\d+")
匹配多位数字;但如果使用JavaScript语法的正则表达式则不需要,例如textMatches(/\d+/)
。但如果使用字符串的正则表达式则该字符串不能以"/"同时以"/"结束,也即不能写诸如textMatches("/\\d+/")
的表达式,否则会被开头的"/"和结尾的"/"会被忽略。
idMatches("[a-zA-Z]+")
-
UiSelector.className(str)#
-为当前选择器附加控件"className等于字符串str"的筛选条件。
-控件的className(类名)表示一个控件的类别,例如文本控件的类名为android.widget.TextView。
-如果一个控件的类名以"android.widget."开头,则可以省略这部分,例如文本控件可以直接用className("TextView")
的选择器。
常见控件的类名如下:
+选项包括:
-
-
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
通常也是列表控件
+- -w:应用启动时等待调试程序。 +
- --persistent:保留此值。 +
- clear-debug-app 使用 set-debug-app 清除以前针对调试用途设置的软件包。
UiSelector.classNameContains(str)#
-为当前选择器附加控件"className需要包含字符串str"的筛选条件。
-UiSelector.classNameStartsWith(prefix)#
--
-
prefix
<string> 前缀
+
display-size [reset|widthxheight]#
+替换模拟器/设备显示尺寸。此命令对于在不同尺寸的屏幕上测试您的应用非常有用,它支持使用大屏设备模仿小屏幕分辨率(反之亦然)。
示例:
shell("am display-size 1280x800", true);
+
+
display-density dpi#
+替换模拟器/设备显示密度。此命令对于在不同密度的屏幕上测试您的应用非常有用,它支持使用低密度屏幕在高密度环境环境上进行测试(反之亦然)。
示例:
shell("am display-density 480", true);
+
to-uri intent#
+将给定的 intent 规范以 URI 的形式输出。 +请参阅 intent 参数的规范。
+to-intent-uri intent#
+将给定的 intent 规范以 intent:URI 的形式输出。 +请参阅 intent 参数的规范。
+intent参数的规范#
+对于采用 intent 参数的 am 命令,您可以使用以下选项指定 intent:
+-
+
- -a action
指定 intent 操作,如“android.intent.action.VIEW”。此指定只能声明一次。
+ - -d data_uri
指定 intent 数据 URI,如“content://contacts/people/1”。此指定只能声明一次。
+ - -t mime_type
指定 intent MIME 类型,如“image/png”。此指定只能声明一次。
+ - -c category
指定 intent 类别,如“android.intent.category.APP_CONTACTS”。
+ - -n component
指定带有软件包名称前缀的组件名称以创建显式 intent,如“com.example.app/.ExampleActivity”。
+ - -f flags
将标志添加到 setFlags() 支持的 intent。
+ - --esn extra_key
添加一个 null extra。URI intent 不支持此选项。
+ - -e|--es extra_key extra_string_value
添加字符串数据作为键值对。
+ - --ez extra_key extra_boolean_value
添加布尔型数据作为键值对。
+ - --ei extra_key extra_int_value
添加整数型数据作为键值对。
+ - --el extra_key extra_long_value
添加长整型数据作为键值对。
+ - --ef extra_key extra_float_value
添加浮点型数据作为键值对。
+ - --eu extra_key extra_uri_value
添加 URI 数据作为键值对。
+ - --ecn extra_key extra_component_name_value
添加组件名称,将其作为 ComponentName 对象进行转换和传递。
+ - --eia extra_key extra_int_value[,extra_int_value...]
添加整数数组。
+ - --ela extra_key extra_long_value[,extra_long_value...]
添加长整型数组。
+ - --efa extra_key extra_float_value[,extra_float_value...]
添加浮点型数组。
+ - --grant-read-uri-permission
包含标志 FLAG_GRANT_READ_URI_PERMISSION。
+ - --grant-write-uri-permission
包含标志 FLAG_GRANT_WRITE_URI_PERMISSION。
+ - --debug-log-resolution
包含标志 FLAG_DEBUG_LOG_RESOLUTION。
+ - --exclude-stopped-packages
包含标志 FLAG_EXCLUDE_STOPPED_PACKAGES。
+ - --include-stopped-packages
包含标志 FLAG_INCLUDE_STOPPED_PACKAGES。
+ - --activity-brought-to-front
包含标志 FLAG_ACTIVITY_BROUGHT_TO_FRONT。
+ - --activity-clear-top
包含标志 FLAG_ACTIVITY_CLEAR_TOP。
+ - --activity-clear-when-task-reset
包含标志 FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET。
+ - --activity-exclude-from-recents
包含标志 FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS。
+ - --activity-launched-from-history
包含标志 FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY。
+ - --activity-multiple-task
包含标志 FLAG_ACTIVITY_MULTIPLE_TASK。
+ - --activity-no-animation
包含标志 FLAG_ACTIVITY_NO_ANIMATION。
+ - --activity-no-history
包含标志 FLAG_ACTIVITY_NO_HISTORY。
+ - --activity-no-user-action
包含标志 FLAG_ACTIVITY_NO_USER_ACTION。
+ - --activity-previous-is-top
包含标志 FLAG_ACTIVITY_PREVIOUS_IS_TOP。
+ - --activity-reorder-to-front
包含标志 FLAG_ACTIVITY_REORDER_TO_FRONT。
+ - --activity-reset-task-if-needed
包含标志 FLAG_ACTIVITY_RESET_TASK_IF_NEEDED。
+ - --activity-single-top
包含标志 FLAG_ACTIVITY_SINGLE_TOP。
+ - --activity-clear-task
包含标志 FLAG_ACTIVITY_CLEAR_TASK。
+ - --activity-task-on-home
包含标志 FLAG_ACTIVITY_TASK_ON_HOME。
+ - --receiver-registered-only
包含标志 FLAG_RECEIVER_REGISTERED_ONLY。
+ - --receiver-replace-pending
包含标志 FLAG_RECEIVER_REPLACE_PENDING。
+ - --selector
需要使用 -d 和 -t 选项以设置 intent 数据和类型。URI component package#
+如果不受上述某一选项的限制,您可以直接指定 URI、软件包名称和组件名称。当参数不受限制时,如果参数包含一个“:”(冒号),则此工具假定参数是一个 URI;如果参数包含一个“/”(正斜杠),则此工具假定参数是一个组件名称;否则,此工具假定参数是一个软件包名称。
为当前选择器附加控件"className需要以prefix开头"的筛选条件。
-UiSelector.classNameEndsWith(suffix)#
--
-
suffix
<string> 后缀
+- -f:查看它们的关联文件。 +
- -d:进行过滤以仅显示已停用的软件包。 +
- -e:进行过滤以仅显示已启用的软件包。 +
- -s:进行过滤以仅显示系统软件包。 +
- -3:进行过滤以仅显示第三方软件包。 +
- -i:查看软件包的安装程序。 +
- -u:也包括卸载的软件包。 +
- --user user_id:要查询的用户空间。
应用包名#
+所谓应用包名,是唯一确定应用的标识。例如微信的包名是"com.tencent.mm", QQ的包名是"com.tencent.mobileqq"。
要获取一个应用的包名,可以通过函数getPackageName(appName)
获取。参见帮助->其他一般函数。
pm命令#
+pm命令用于管理应用程序,例如卸载应用、冻结应用等。
以下命令均以"pm "开头,例如"shell(\"pm disable com.tencent.mm\");"(冻结微信)
list packages [options] filter#
+输出所有软件包,或者,仅输出包名称包含 filter 中的文本的软件包。
选项:
-
+
为当前选择器附加控件"className需要以suffix结束"的筛选条件。
-UiSelector.classNameMatches(reg)#
-为当前选择器附加控件"className需要满足正则表达式reg"的条件。
-有关正则表达式,可以查看正则表达式 - 菜鸟教程。
-需要注意的是,如果正则表达式是字符串,则需要使用\\
来表达\
(也即Java正则表达式的形式),例如textMatches("\\d+")
匹配多位数字;但如果使用JavaScript语法的正则表达式则不需要,例如textMatches(/\d+/)
。但如果使用字符串的正则表达式则该字符串不能以"/"同时以"/"结束,也即不能写诸如textMatches("/\\d+/")
的表达式,否则会被开头的"/"和结尾的"/"会被忽略。
UiSelector.packageName(str)#
-为当前选择器附加控件"packageName等于字符串str"的筛选条件。
-控件的packageName表示控件所属界面的应用包名。例如微信的包名为"com.tencent.mm", 那么微信界面的控件的packageName为"com.tencent.mm"。
-要查看一个应用的包名,可以用函数app.getPackageName()
获取,例如toast(app.getPackageName("微信"))
。
UiSelector.packageNameContains(str)#
--
-
str
<string> 要包含的字符串
+- -l:安装具有转发锁定功能的软件包。 +
- -r:重新安装现有应用,保留其数据。 +
- -t:允许安装测试 APK。 +
- -i installer_package_name:指定安装程序软件包名称。 +
- -s:在共享的大容量存储(如 sdcard)上安装软件包。 +
- -f:在内部系统内存上安装软件包。 +
- -d:允许版本代码降级。 +
- -g:授予应用清单文件中列出的所有权限。
list features#
+输出系统的所有功能。
+list libraries#
+输出当前设备支持的所有库。
+list users#
+输出系统上的所有用户。
+path package#
+输出给定 package 的 APK 的路径。
+install [options] path#
+将软件包(通过 path 指定)安装到系统。
选项:
-
+
为当前选择器附加控件"packageName需要包含字符串str"的筛选条件。
-UiSelector.packageNameStartsWith(prefix)#
-为当前选择器附加控件"packageName需要以prefix开头"的筛选条件。
-UiSelector.packageNameEndsWith(suffix)#
--
-
suffix
<string> 后缀
+- --user user_id:要停用的用户。
grant package_name permission#
+向应用授予权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,可以是应用清单中声明的任何权限。在运行 Android 5.1(API 级别 22)和更低版本的设备上,必须是应用定义的可选权限。
enable package_or_component#
+启用给定软件包或组件(作为“package/class”写入)。
+disable package_or_component#
+停用给定软件包或组件(作为“package/class”写入)。
+disable-user [options] package_or_component#
+选项:
+-
+
为当前选择器附加控件"packageName需要以suffix结束"的筛选条件。
-UiSelector.packageNameMatches(reg)#
-为当前选择器附加控件"packageName需要满足正则表达式reg"的条件。
-有关正则表达式,可以查看正则表达式 - 菜鸟教程。
-UiSelector.bounds(left, top, right, buttom)#
-一个控件的bounds属性为这个控件在屏幕上显示的范围。我们可以用这个范围来定位这个控件。尽管用这个方法定位控件对于静态页面十分准确,却无法兼容不同分辨率的设备;同时对于列表页面等动态页面无法达到效果,因此使用不推荐该选择器。
-注意参数的这四个数字不能随意填写,必须精确的填写控件的四个边界才能找到该控件。例如,要点击QQ主界面的右上角加号,我们用布局分析查看该控件的属性,如下图:
-可以看到bounds属性为(951, 67, 1080, 196),此时使用代码bounds(951, 67, 1080, 196).clickable().click()
即可点击该控件。
UiSelector.boundsInside(left, top, right, buttom)#
-为当前选择器附加控件"bounds需要在left, top, right, buttom构成的范围里面"的条件。
-这个条件用于限制选择器在某一个区域选择控件。例如要在屏幕上半部分寻找文本控件TextView,代码为:
-var w = className("TextView").boundsInside(0, 0, device.width, device.height / 2).findOne();
-log(w.text());
-
其中我们使用了device.width
来获取屏幕宽度,device.height
来获取屏幕高度。
UiSelector.boundsContains(left, top, right, buttom)#
-为当前选择器附加控件"bounds需要包含left, top, right, buttom构成的范围"的条件。
-这个条件用于限制控件的范围必须包含所给定的范围。例如给定一个点(500, 300), 寻找在这个点上的可点击控件的代码为:
-var w = boundsContains(500, 300, 500, 300).clickable().findOne();
-w.click();
-
UiSelector.drawingOrder(order)#
--
-
- order <number> 控件在父视图中的绘制顺序 -
为当前选择器附加控件"drawingOrder等于order"的条件。
-drawingOrder为一个控件在父控件中的绘制顺序,通常可以用于区分同一层次的控件。
-但该属性在Android 7.0以上才能使用。
-UiSelector.clickable([b = true])#
--
-
b
<Boolean> 表示控件是否可点击
-
为当前选择器附加控件是否可点击的条件。但并非所有clickable为false的控件都真的不能点击,这取决于控件的实现。对于自定义控件(例如显示类名为android.view.View的控件)很多的clickable属性都为false都却能点击。
-需要注意的是,可以省略参数b
而表示选择那些可以点击的控件,例如className("ImageView").clickable()
表示可以点击的图片控件的条件,className("ImageView").clickable(false)
表示不可点击的图片控件的条件。
UiSelector.longClickable([b = true])#
--
-
b
<Boolean> 表示控件是否可长按
-
为当前选择器附加控件是否可长按的条件。
-UiSelector.checkable([b = true])#
--
-
b
<Boolean> 表示控件是否可勾选
-
为当前选择器附加控件是否可勾选的条件。勾选通常是对于勾选框而言的,例如图片多选时左上角通常有一个勾选框。
-UiSelector.selected([b = true])#
+set-permission-enforced permission [true|false]#
+指定是否应强制执行给定的权限。
+trim-caches desired_free_space#
+减少缓存文件以达到给定的可用空间。
+create-user user_name#
+使用给定的 user_name 创建新用户,输出新用户的标识符。
+remove-user user_id#
+移除具有给定的 user_id 的用户,删除与该用户关联的所有数据。
+get-max-users#
+输出设备支持的最大用户数。
+其他命令#
+进行屏幕截图#
+screencap 命令是一个用于对设备显示屏进行屏幕截图的 shell 实用程序。在 shell 中,此语法为:
+screencap filename
+
例如:
+$ shell("screencap /sdcard/screen.png");
+
列表文件#
+ls filepath
+
例如:
+log(shell("ls /system/bin").result);
+
+
+Storages#
+storages模块提供了保存简单数据、用户配置等的支持。保存的数据除非应用被卸载或者被主动删除,否则会一直保留。
+storages支持number
, boolean
, string
等数据类型以及把Object
, Array
用JSON.stringify
序列化存取。
storages保存的数据在脚本之间是共享的,任何脚本只要知道storage名称便可以获取到相应的数据,因此它不能用于敏感数据的储存。 +storages无法像Web开发中LocalStorage一样提供根据域名独立的存储,因为脚本的路径随时可能改变。
+storages.create(name)#
为当前选择器附加控件是否已选中的条件。被选中指的是,例如QQ聊天界面点击下方的"表情按钮"时,会出现自己收藏的表情,这时"表情按钮"便处于选中状态,其selected属性为true。
-