- Overview - 综述
- Q&A - 常见问题
- Globals - 一般全局函数
- WidgetsBasedAutomation - 基于控件的触摸模拟
- CoordinatesBasedAutomation - 基于坐标的触摸模拟
- Images - 图片与图色处理
- Console - 控制台
- Events - 事件与监听
- Timers - 定时器
- Shell - Shell命令
- UI - 用户界面
- Files - 文件系统
- Dialogs - 对话框
- Http - HTTP
- App - 应用
- Engines - 脚本引擎
- Modules - 模块
- Work with Java - 调用Java API
Auto.js 3.0.0 文档
目录
- 全局变量与函数
- sleep([n])
- launchPackage(packageName)
- launchApp(appName)
- currentPackage()
- currentActivity()
- getPackageName(appName)
- getAppName(packageName)
- openAppSetting(packageName)
- setClip(text)
- getClip()
- toast(message)
- toastLog(message)
- waitForActivity(activity[, period = 200])
- waitForPackage(package[, period = 200])
- exit()
- random(min, max)
- random()
- context
- SimpleActionAutomator
- UiSelector
- id(resId)
- idContains(str)
- idStartsWith(prefix)
- idEndsWith(suffix)
- idMatches(String)
- text(str)
- textContains(str)
- textStartsWith(prefix)
- textEndsWith(suffix)
- textMatches(str)
- desc(str)
- descContains(str)
- descStartsWith(prefix)
- descEndsWith(suffix)
- descMatches(str)
- className(str)
- classNameContains(str)
- classNameStartsWith(prefix)
- classNameEndsWith(suffix)
- classNameMatches(str)
- packageName(str)
- packageNameContains(str)
- packageNameStartsWith(prefix)
- packageNameEndsWith(suffix)
- packageNameMatches(str)
- bounds(l, t, r, b)
- boundsInside(l, t, r, b)
- boundsContains(l, t, r, b)
- drawingOrder(order)
- checkable([b = true])
- selected([b = true])
- clickable([b = true])
- longClickable([b = true])
- enabled([b = true])
- scrollable([b = true])
- editable([b = true])
- contentInvalid([b = true])
- contextClickable([b = true])
- multiLine([b = true])
- findOne()
- find()
- untilFind()
- exists()
- waitFor()
- click()
- longClick()
- copy()
- paste()
- select()
- cut()
- collapse()
- expand()
- show()
- scrollForward()
- scrollBackward()
- scrollUp()
- scrollDown()
- scrollLeft()
- scrollRight()
- contextClick()
- setSelection(start, end)
- setText(text)
- UiCollection
- UiCollection.size()
- UiCollection.get(i)
- UiCollection.each(func)
- empty()
- nonEmpty()
- UiCollection.filter(filter)
- UiCollection.find(selector)
- UiCollection.findOne(selector)
- UiCollection.click()
- UiCollection.longClick()
- UiCollection.copy()
- UiCollection.paste()
- UiCollection.select()
- UiCollection.cut()
- UiCollection.collapse()
- UiCollection.expand()
- UiCollection.show()
- UiCollection.scrollForward()
- UiCollection.scrollBackward()
- UiCollection.scrollUp()
- UiCollection.scrollDown()
- UiCollection.scrollLeft()
- UiCollection.scrollRight()
- UiCollection.contextClick()
- UiCollection.setSelection(start, end)
- UiCollection.setText(text)
- UiObject
- Rect
- Android7.0以上点按与手势模拟
- RootAutomator
- 使用root权限点击和滑动的简单命令
- Images
- images.requestScreenCapture([landscape])
- images.captureScreen()
- images.captureScreen(path)
- images.pixel(image, x, y)
- images.saveImage(image, path)
- images.read(path)
- images.load(url)
- images.findColor(image, color, options)
- images.findColorInRegion(img, color, x, y[, width, height, threshold])
- images.findColorEquals(img, color[, x, y, width, height])
- images.detectsColor(image, color, x, y[, threshold = 16, algorithm = "diff"])
- images.findImage(img, template[, options])
- images.findImageInRegion(img, template, x, y[, width, height, threshold])
- colors
- Image
- Point
- Console
- console.show()
- console.clear()
- console.log([data][, ...args])
- console.verbose([data][, ...args])
- console.info([data][, ...args])
- console.warn([data][, ...args])
- console.error([data][, ...args])
- console.assert(value, message)
- console.input(data[, ...args])
- console.rawInput(data[, ...args])
- print(text)
- Events
- events.emitter()
- events.observeKey()
- events.onKeyDown(keyName, listener)
- events.onKeyUp(keyName, listener)
- events.onceKeyDown(keyName, listener)
- events.onceKeyUp(keyName, listener)
- events.removeAllKeyDownListeners(keyName)
- events.removeAllKeyUpListeners(keyName)
- events.observeTouch()
- events.setTouchEventTimeout(timeout)
- events.getTouchEventTimeout()
- events.onTouch(listener)
- events.removeAllTouchListeners()
- 事件: 'key'
- 事件: 'key_down'
- 事件: 'key_up'
- obverseNotification()
- 事件: 'toast'
- 事件: 'notification'
- EventEmitter
- EventEmitter.defaultMaxListeners
- EventEmitter.addListener(eventName, listener)
- EventEmitter.emit(eventName[, ...args])
- EventEmitter.eventNames()
- EventEmitter.getMaxListeners()
- EventEmitter.listenerCount(eventName)
- EventEmitter.listeners(eventName)
- EventEmitter.on(eventName, listener)
- EventEmitter.once(eventName, listener)
- EventEmitter.prependListener(eventName, listener)
- EventEmitter.prependOnceListener(eventName, listener)
- EventEmitter.removeAllListeners([eventName])
- EventEmitter.removeListener(eventName, listener)
- EventEmitter.setMaxListeners(n)
- KeyEvent
- Keys
- Timers
- shell函数
- Shell
- 附录: shell命令简介
- am命令
- start [options] intent
- startservice [options] intent
- force-stop package
- kill [options] package
- kill-all
- broadcast [options] intent
- instrument [options] component
- dumpheap [options] process file
- monitor [options] 启动对崩溃或 ANR 的监控。
- screen-compat <on> | <off> package
- display-size [reset|widthxheight]
- display-density dpi
- to-uri intent
- to-intent-uri intent
- intent参数的规范
- 应用包名
- pm命令
- list packages [options] filter
- list permission-groups
- list permissions [options] group
- list instrumentation [options]
- list features
- list libraries
- list users
- path package
- install [options] path
- uninstall [options] package
- clear package
- enable package_or_component
- disable package_or_component
- disable-user [options] package_or_component
- grant package_name permission
- revoke package_name permission
- set-install-location location
- get-install-location
- set-permission-enforced permission [true|false]
- trim-caches desired_free_space
- create-user user_name
- remove-user user_id
- get-max-users
- 其他命令
- am命令
- Files
- files.isFile(path)
- files.isDir(path)
- files.isEmptyDir(path)
- files.join(parent, child)
- files.create(path)
- files.createIfNotExists(path)
- files.exists(path)
- files.ensureDir(path)
- files.read(path[, encoding = "utf-8"])
- files.write(path, text[, encoding = "utf-8"])
- files.copy(fromPath, toPath)
- files.move(fromPath, toPath)
- files.rename(path, newName)
- files.renameWithoutExtension(path, newName)
- files.getName(path)
- files.getNameWithoutExtension(path)
- files.getExtension(path)
- files.remove(path)
- files.removeDir(path)
- files.getSdcardPath()
- files.listDir(path[, filter])
- open(path[, mode = "r", encoding = "utf-8", bufferSize = 8192])
- ReadableTextFile
- PWritableTextFile
- App
- HTTP
- Response
- Dialogs
- Engines
- ScriptExecution
- ScriptEngine
- ScriptConfig
- ScriptSource
- module (模块)
全局变量与函数#
全局变量和函数在所有模块中均可使用。 但以下变量的作用域只在模块内,详见 module文档:
- exports
- module
- require() 以下的对象是特定于 Auto.js 的。 有些内置对象是 JavaScript 语言本身的一部分,它们也是全局的。
一些模块中的函数为了使用方便也可以直接全局使用,这些函数在此不再赘述。例如timers模块的setInterval等函数。
sleep([n])#
n<number> 毫秒数
暂停运行n毫秒的时间。1秒等于1000毫秒。
launchPackage(packageName)#
packageName<string> 应用包名
运行包名为packageName的应用主界面(Launcher)。例如,打开微信为:
launchPackage("com.tencent.mm");
如果存在多个应用包名相同的情况(如双开应用),如何处理取决于操作系统。在MIUI中会弹出多开应用的选择界面。
launchApp(appName)#
appName<String> 应用名称
运行应用名称为appName的应用主界面。当有应用名称相同时只运行其中某一个。
例如,打开微信为:
launchApp("微信");
currentPackage()#
返回最近一次监测到的正在运行的应用的包名,一般可以认为就是当前正在运行的应用的包名。
currentActivity()#
返回最近一次监测到的正在运行的Activity的名称,一般可以认为就是当前正在运行的Activity的名称。
getPackageName(appName)#
appName<string> 应用名称
获取应用的包名。例如getPackageName("QQ")为"com.tencent.mobileqq"。如果有相同名称的应用,只返回其中某一个的包名。如果不存在这个名称的应用,会返回null。
getAppName(packageName)#
packageName<string> 应用包名
返回对应包名的应用的名称。如果应用不存在,返回null。
openAppSetting(packageName)#
packageName<string> 应用包名
打开某个应用的应用详情页,也就是管理应用权限和可以停止其运行的页面。如果应用包名不存在,则返回false;否则返回true。
setClip(text)#
text<string> 文本
设置剪贴板内容。此剪贴板即系统剪贴板,在一般应用的输入框中"粘贴"既可使用。
getClip()#
返回系统剪贴板的内容。
toast(message)#
- message <string>> | <{Object> 要显示的信息
以气泡显示信息message几秒。(具体时间取决于安卓系统,一般都是2秒)
注意,信息的显示是"异步"执行的(不属于Looper循环),并且,不会等待信息消失程序才继续执行。如果在循环中执行该命令,可能出现脚本停止运行后仍然有不断的气泡信息出现的情况。 例如:
for(var i = 0; i < 100; i++){
toast(i);
}
运行这段程序以后,会很快执行完成,且不断弹出消息,在任务管理中关闭所有脚本也无法停止。 要保证气泡消息才继续执行可以用:
for(var i = 0; i < 100; i++){
toast(i);
sleep(2000);
}
或者修改toast函数:
var _toast_ = toast;
toast = function(message){
_toast_(message);
sleep(2000);
}
for(var i = 0; i < 100; i++){
toast(i);
sleep(2000);
}
toastLog(message)#
- message \
| \
相当于toast(message);log(message)。显示信息message并在控制台中输出。参见console.log。
waitForActivity(activity[, period = 200])#
activityActivity名称period轮询等待间隔(毫秒)
等待指定的Activity出现,period为检查Activity的间隔。
waitForPackage(package[, period = 200])#
package包名period轮询等待间隔(毫秒)
等待指定的应用出现。例如waitForPackage("com.tencent.mm")为等待当前界面为微信。
exit()#
立即停止脚本运行。
random(min, max)#
返回一个在[min...max]之间的随机数。例如random(0, 2)可能产生0, 1, 2.
random()#
返回在[0, 1)的随机浮点数。
context#
全局变量。一个android.content.Context对象。
注意该对象为ApplicationContext,因此不能用于界面、对话框等的创建。
SimpleActionAutomator#
SimpleActionAutomator提供了一些模拟简单操作的函数,例如点击文字、模拟按键等。这些函数可以直接作为全局函数使用。
click(text[, i])#
返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。
该函数可以点击大部分包含文字的按钮。例如微信主界面下方的"微信", "联系人", "发现", "我"的按钮。
通常与while同时使用以便点击按钮直至成功。例如:
while(!click("扫一扫"));
当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部点击成功。
i是从0开始计算的, 也就是, click("啦啦啦", 0)表示点击屏幕上第一个"啦啦啦", click("啦啦啦", 1)表示点击屏幕上第二个"啦啦啦"。
文本所在区域指的是,从文本处向其父视图寻找,直至发现一个可点击的部件为止。
click(left, top, bottom, right)#
注意,该函数一般只用于录制的脚本中使用,在自己写的代码中使用该函数一般不要使用该函数。
点击在指定区域的控件。当屏幕中并未包含与该区域严格匹配的区域,或者该区域不能点击时返回false,否则返回true。
有些按钮或者部件是图标而不是文字(例如发送朋友圈的照相机图标以及QQ下方的消息、联系人、动态图标),这时不能通过click(text, i)来点击,可以通过描述图标所在的区域来点击。left, bottom, top, right描述的就是点击的区域。
至于要定位点击的区域,可以在悬浮窗使用布局分析工具查看控件的bounds属性。
通过无障碍服务录制脚本会生成该语句。
longClick(text[, i]))#
返回是否点击成功。当屏幕中并未包含该文本,或者该文本所在区域不能点击时返回false,否则返回true。
当不指定参数i时则会尝试点击屏幕上出现的所有文字text并返回是否全部长按成功。
scrollUp([i])#
i<number> 要滑动的控件序号
找到第i+1个可滑动控件上滑或左滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。
另外不加参数时scrollUp()会寻找面积最大的可滑动的控件上滑或左滑,例如微信消息列表等。
参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)为滑动第一个可滑动控件。
scrollDown([i])#
i<number> 要滑动的控件序号
找到第i+1个可滑动控件下滑或右滑。返回是否操作成功。屏幕上没有可滑动的控件时返回false。
另外不加参数时scrollUp()会寻找面积最大的可滑动的控件下滑或右滑。
参数为一个整数i时会找到第i + 1个可滑动控件滑动。例如scrollUp(0)为滑动第一个可滑动控件。
setText([i, ]text)#
返回是否输入成功。当找不到对应的文本框时返回false。
不加参数i则会把所有输入框的文本都置为text。例如setText("测试")。
这里的输入文本的意思是,把输入框的文本置为text,而不是在原来的文本上追加。
input([i, ]text)#
返回是否输入成功。当找不到对应的文本框时返回false。
不加参数i则会把所有输入框的文本追加内容text。例如input("测试")。
UiSelector#
选择器(UiSelector)是稍微复杂的自动操作脚本所必须。使用选择器的一般步骤是:
- 用各种筛选条件找出想要的控件,如某个文本控件、列表控件、图片控件
- 对找出的控件执行想要的操作,如点击、滑动、设置文字、长按
问题的关键在于如何找出想要的控件。对于文本控件一般通过他的文字来定位他,图片控件则通过id或者图片描述(desc)。选择器所做的就是提供这些筛选条件并给出筛选结果。
选择器提供了更强大的定位界面控件与对其进行操作的功能,可以用他们完成更多的自动操作和提取界面信息。
选择器通过附加筛选条件,筛选出符合条件的控件或控件集合,之后可以对这些控件这些操作。
可供选择的筛选条件包括:
- id
- text 文本
- desc 描述(Content-Description)
- className 类名
- packageName 包名
- bounds 在屏幕上的范围
- drawingOrder 绘制顺序
- 各种属性,主要包括:
- clickable 可点击
- longClickable 可长按
- checkable 可勾选
- checked 被勾选
- scrollable 可滑动
- selected 被选择
- editable 可编辑
- visibleToUser 可见
- enabled 已启用
要对选择器所确定的筛选条件,对屏幕上的控件进行筛选,调用方法find(), findOne(), untilFind()。其中find(), untilFind()返回控件的集合,findOne()返回一个控件。untilFind和findOne函数会一直寻找直到屏幕上出现满足条件的控件为止。
一个完整的选择器示例如下:
var emoj = id("name").packageName("com.tencent.mobileqq").clickable()
.className("ImageView").drawingOrder(5).findOne();
emoj.click();
上述代码是找到QQ聊天界面下面的表情按钮(第5个按钮)并点击。也可以简化为:
id("name").packageName("com.tencent.mobileqq").clickable()
.className("ImageView").click();
这段代码意思是,找出id为"name", 包名为"com.tentcent.mobileqq",类名为ImageView的所有可点击控件,对他们执行点击动作。
最后的click()函数相当于untilFind().click()。也就是如果只需要在找到控件以后立即进行操作,只需要调用相应的操作函数,而不需要先调用find等函数等到控件再操作。
要获取屏幕上的控件的信息(例如id, text, desc, bounds等),可以开启悬浮窗,使用界面层次查看和界面范围查看。
选择器部分内容如果有安卓开发经验会更容易掌握。
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严格匹配筛选条件。
控件的id属性通常是可以用来确定控件的唯一标识,如果一个控件有id,那么使用id来找到他是最好的方法。要查看屏幕上的控件的id,可以开启悬浮窗并使用界面工具,点击相应控件即可查看。若查看到的控件id为null, 表示该控件没有id。另外,在列表中会出现多个控件的id相同的情况。例如微信的联系人列表,每个头像的id都是一样的。此时不能用id来唯一确定控件。
在QQ界面经常会出现多个id为"name"的控件,在微信上则每个版本的id都会变化。对于这些软件而言比较难用id定位控件。
idContains(str)#
- str <string> id要包含的字符串
附加控件id包含字符串str的筛选条件。
idStartsWith(prefix)#
- prefix <string> id前缀
附加id需要以prefix开头的筛选条件。
idEndsWith(suffix)#
- suffix <string> id后缀
附加id需要以suffix结束的筛选条件。
idMatches(String)#
- String <string> id要满足的正则表达式
附加id需要满足正则表达式。有关正则表达式,可以查看菜鸟教程。
这里的正则表达式是Java的正则表达式,不能直接使用JavaScript的正则表达式。
idMatches("[a-zA-Z]+")
text(str)#
- str <string> 控件文本
附加控件文本等于字符串str的筛选条件。
控件的text(文本)属性是控件上的显示的文字,例如微信左上角的"微信"文本。对于图片或者其他控件通常text属性为null。
textContains(str)#
- str <string> 要包含的字符串
附加控件文本需要以prefix开头的筛选条件。
textStartsWith(prefix)#
- prefix <string> 前缀
附加控件文本需要以prefix开头的筛选条件。
textEndsWith(suffix)#
- suffix <string> 后缀
附加控件文本需要以suffix结束的筛选条件。
textMatches(str)#
- String <string> 要满足的正则表达式
附加控件文本需要满足正则表达式的条件。
desc(str)#
- str <string> 控件描述
附加控件描述等于字符串str的筛选条件。
控件的desc(描述,全称为Content-Description)属性是对一个控件的描述,例如网易云音乐右上角的放大镜图标的描述为搜索。要查看一个控件的描述,同样地可以借助悬浮窗查看。
desc属性同样是定位控件的利器。
descContains(str)#
- str <string> 要包含的字符串
附加控件描述需要以prefix开头的筛选条件。
descStartsWith(prefix)#
- prefix <string> 前缀
附加控件描述需要以prefix开头的筛选条件。
descEndsWith(suffix)#
- suffix <string> 后缀
附加控件描述需要以suffix结束的筛选条件。
descMatches(str)#
- String <string> 要满足的正则表达式
附加控件描述需要满足正则表达式的条件。
className(str)#
- str <string> 控件类名
附加控件类名等于字符串str的筛选条件。
控件的className属性是一个控件的具体类型,例如图片控件通常为ImageView,文本控件通常为TextView, 输入框通常为EditText。(若一个控件是在android.widget包里的,那么android.widget可以省略。但除此之外的其他控件必须是类的全名,例如"com.stardust.theme.ThemeColorImageView")。
classNameContains(str)#
- str <string> 要包含的字符串
附加控件类名需要以prefix开头的筛选条件。
classNameStartsWith(prefix)#
- prefix <string> 前缀
附加控件类名需要以prefix开头的筛选条件。
classNameEndsWith(suffix)#
- suffix <string> 后缀
附加控件类名需要以suffix结束的筛选条件。
classNameMatches(str)#
- String <string> 要满足的正则表达式
附加控件类名需要满足正则表达式的条件。
packageName(str)#
- str <string> 包名
附加包名等于字符串str的筛选条件。
packageName属性也即控件所属的应用的包名(参见《shell命令:应用包名》),通常用来保证当前运行的应用是想要的应用。
packageNameContains(str)#
- str <string> 要包含的字符串
附加包名需要以prefix开头的筛选条件。
packageNameStartsWith(prefix)#
- prefix <string> 前缀
附加包名需要以prefix开头的筛选条件。
packageNameEndsWith(suffix)#
- suffix <string> 后缀
附加包名需要以suffix结束的筛选条件。
packageNameMatches(str)#
- String <string> 要满足的正则表达式
附加包名需要满足正则表达式的条件。
bounds(l, t, r, b)#
- l, t, r, b 用来定位控件在屏幕上的范围的四个整数
boundsInside(l, t, r, b)#
boundsContains(l, t, r, b)#
drawingOrder(order)#
- order <number> 控件在父视图中的绘制顺序,在一些
checkable([b = true])#
- b <Boolean> 表示控件是否可勾选, 默认为true
附加控件是否可勾选的条件。可勾选指的是,例如QQ和微信发送图片时图片的勾选。
selected([b = true])#
- b <Boolean> 表示控件是否被选中,默认为true
附加控件是否被选中的条件。被选中指的是,例如QQ聊天界面点击下方的表情按钮时,会出现自己收藏的表情,这时表情按钮便处于选中状态。
clickable([b = true])#
- b <Boolean> 表示控件是否可点击, 默认为true
附加控件是否可点击的条件。但并非所有clickable为false的控件都真的不能点击,这取决于控件的实现。因而要确定一个控件的clickable属性,可以开启悬浮窗工具。
longClickable([b = true])#
- b <Boolean> 表示控件是否可长按, 默认为true
附加控件是否可长按的条件。
enabled([b = true])#
- b <Boolean> 表示控件是否已启用, 默认为true
附加控件是否已启用的条件。大多数控件都是启用的状态,处于“禁用”状态通常是灰色并且不可点击。
scrollable([b = true])#
- b <Boolean> 表示控件是否可滑动, 默认为true
附加控件是否可滑动的条件。
editable([b = true])#
- b <Boolean> 表示控件是否可编辑, 默认为true
附加控件是否可编辑的条件。一般来说可编辑的控件为输入框(EditText)。
contentInvalid([b = true])#
- b <Boolean> 表示控件是否是contentInvalid, 默认为true
我也不知道是什么,下次再补充吧。
contextClickable([b = true])#
- b <Boolean> 表示控件是否是contextClickable, 默认为true
我也不知道是什么,下次再补充吧。
multiLine([b = true])#
- b <Boolean> 表示文本或输入框控件是否是多行显示的, 默认为true
附加控件是否文本或输入框控件是否是多行显示的条件。
findOne()#
根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到屏幕上出现满足条件的一个控件为止,并返回该控件。如果找不到控件,当屏幕内容发生变化时会重新寻找,直至找到。参见控件。
find()#
根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,找到所有满足条件的控件集合并返回。这个搜索只进行一次,并不保证一直会找到,因而会出现返回的控件集合为空的情况。参见控件集合。
可以通过empty()或nonEmpty()函数判断找到的是否为空。例如:
var c = className("AbsListView").find();
if(c.empty()){
toast("找到啦");
}else{
toast("没找到╭(╯^╰)╮");
}
untilFind()#
根据当前的选择器所确定的筛选条件,对屏幕上的控件进行搜索,直到找到至少一个满足条件的控件为止,并返回所有满足条件的控件集合。参见控件集合。
exists()#
判断屏幕上是否存在控件符合选择器所确定的条件。例如要判断某个文本出现就执行某个动作,可以用:
if(text("嘿嘿嘿").exists()){
//嘿嘿嘿
}
waitFor()#
等待屏幕上出现符合条件的控件。
text("嘿嘿嘿").waitFor();
click()#
找到所有符合条件的控件并点击。相当于untilFind().click()。参见click)。
longClick()#
找到所有符合条件的控件并长按。相当于untilFind().longClick()。参见longClick)。
copy()#
找到所有符合条件的控件并复制其内容,只对文本框或输入框控件有文字选中时有效。相当于untilFind().copy()。参见copy)。
paste()#
找到所有符合条件的控件并粘贴,只对输入框控件有效。相当于untilFind().paste()。参见paste)。
select()#
找到所有符合条件的控件并选中。相当于untilFind().select()。参见select)。
cut()#
找到所有符合条件的控件并剪切其内容,只对文本框或输入框控件有文字选中时有效。相当于untilFind().cut()。参见cut)。
collapse()#
找到所有符合条件的控件并折叠。相当于untilFind().collapse()。参见collapse)。
expand()#
找到所有符合条件的控件并展开。相当于untilFind().expand()。参见expand)。
show()#
找到所有符合条件的控件并使其出现在屏幕上。相当于untilFind().show()。参见show)。
scrollForward()#
找到所有符合条件的控件并向前滑。相当于untilFind().scrollForward()。参见scrollForward)。
向前滑指的是,对于左右滑动的控件向右滑,上下滑动的控件向下滑。
scrollBackward()#
找到所有符合条件的控件并向后滑。相当于untilFind().scrollBackward()。参见scrollBackward)。
向后滑指的是,对于左右滑动的控件向左滑,上下滑动的控件向上滑。
scrollUp()#
找到所有符合条件的控件并向上滑。相当于untilFind().scrollUp()。参见scrollUp)。
scrollDown()#
找到所有符合条件的控件并向下滑。相当于untilFind().scrollDown()。参见scrollDown)。
scrollLeft()#
找到所有符合条件的控件并向左滑。相当于untilFind().scrollLeft()。参见scrollLeft)。
scrollRight()#
找到所有符合条件的控件并向右滑。相当于untilFind().scrollRight()。参见scrollRight)。
contextClick()#
文档缺失
setSelection(start, end)#
找到所有符合条件的控件并设置文字选中区域,只对文本控件和输入框有效。相当于untilFind().setSelection()。参见setSelection。
setText(text)#
UiCollection#
UiCollection, 控件集合, 通过选择器的find(), untilFind()方法返回的对象。可以对其进行操作或者获取其信息。
UiCollection.size()#
返回集合中的控件数。
UiCollection.get(i)#
- i <number> 索引
返回集合中第i+1个控件(UiObject)。
UiCollection.each(func)#
- func \
遍历函数
遍历集合。例如:
var c = clickable();
c.each(function(o){
log(o.text());
});
empty()#
返回控件集合是否为空。
nonEmpty()#
返回控件集合是否非空。
UiCollection.filter(filter)#
- filter \
过滤函数。参数为UiObject,返回值为Boolean。
过滤出控件集合中符合条件的子控件。例如要过滤出所有子控件数目为1的控件为:
var newCollection = collection.filter(function(obj){
return obj.childCount() == 1;
});
UiCollection.find(selector)#
- selector \
选择器
根据selector所确定的条件在该控件集合的控件和子控件找到所有符合条件的控件并返回控件集合。
注意这会递归地遍历控件集合里所有的控件以及他们的子控件。和filter函数不同。
例如:
var names = id("name");
var clickableNames = names.find(clickable());
UiCollection.findOne(selector)#
- selector \
选择器
根据selector所确定的条件在该控件集合中找到一个符合条件的控件并返回控件。若找不到则返回null。
UiCollection.click()#
点击集合中所有控件,并返回是否全部点击成功。
UiCollection.longClick()#
长按集合中所有控件,并返回是否全部操作成功。
UiCollection.copy()#
对集合中所有控件执行复制操作,并返回是否全部操作成功。
UiCollection.paste()#
对集合中所有控件执行粘贴操作,并返回是否全部操作成功。
UiCollection.select()#
对集合中所有控件执行选中操作,并返回是否全部操作成功。
UiCollection.cut()#
对集合中所有控件执行剪切操作,并返回是否全部操作成功。
UiCollection.collapse()#
对集合中所有控件执行折叠操作,并返回是否全部操作成功。
UiCollection.expand()#
对集合中所有控件执行展开操作,并返回是否全部操作成功。
UiCollection.show()#
对集合中所有控件执行显示操作,并返回是否全部操作成功。
UiCollection.scrollForward()#
对集合中所有控件执行向前滑的操作,并返回是否全部操作成功。
UiCollection.scrollBackward()#
对集合中所有控件执行向后滑的操作,并返回是否全部操作成功。
UiCollection.scrollUp()#
对集合中所有控件执行向上滑的操作,并返回是否全部操作成功。
UiCollection.scrollDown()#
对集合中所有控件执行向下滑的操作,并返回是否全部操作成功。
UiCollection.scrollLeft()#
对集合中所有控件执行向左滑的操作,并返回是否全部操作成功。
UiCollection.scrollRight()#
对集合中所有控件执行向右滑的操作,并返回是否全部操作成功。
UiCollection.contextClick()#
UiCollection.setSelection(start, end)#
对集合中所有控件设置文字选中区域,并返回是否全部操作成功。
UiCollection.setText(text)#
- text <string> 要设置的文本 对集合中所有控件设置文本,并返回是否全部操作成功。
UiObject#
控件, 选择器的findOne方法返回的对象。和UiCollection有相似的方法,不再赘述。除此之外还有以下方法。
child(i)#
- i <number> 子控件索引
返回第i+1个子控件(UiObject)。
parent()#
返回父控件(UiObject)。
children()#
返回该控件的所有子控件组成的控件集合。
childCount()#
返回子控件数目。
bounds()#
返回控件在屏幕上的范围,其值是一个[Rect]对象。
boundsInParent()#
返回控件在父控件中的范围,其值是一个[Rect]对象。
drawingOrder()#
返回控件的绘制次序。
id()#
返回控件的id,可能为null。
text()#
返回控件的文本,如果控件没有文本,返回""。
findByText(text)#
- text <string> 文本
根据文本text在子控件中递归地寻找并返回文本或描述(desc)包含这段文本text的控件,返回它们组成的集合。。
find(selector)#
- selector \
选择器
根据选择器selector在子控件中递归地寻找符合条件的控件,返回它们组成的集合。
findOne#
find(selector)#
- selector \
选择器
根据选择器selector在子控件中递归地寻找一个符合条件的控件。找不到则返回null。
Rect#
UiObject.bounds(), UiObject.boundsInParent()返回的对象。表示一个长方形。
Rect.left#
长方形左边界的x坐标、
Rect.right#
长方形左边界的x坐标、
Rect.top#
长方形上边界的y坐标、
Rect.bottom#
长方形下边界的y坐标、
Rect.centerX()#
长方形中点x坐标。
Rect.centerY()#
长方形中点y坐标。
Rect.width()#
长方形宽度。通常可以作为控件宽度。
Rect.height()#
长方形高度。通常可以作为控件高度。
Rect.contains(r)#
- r \
返回是否包含另一个长方形r。
Rect.intersect(r)#
- r \
返回是否和另一个长方形相交。
Android7.0以上点按与手势模拟#
本章节介绍了一些适用于Android7.0以上、不需要root权限、依赖于无障碍服务的点按与手势模拟的全局函数。
注意以下命令只有Android7.0及以上才有效
click(x, y)#
模拟点击坐标(x, y),并返回是否点击成功。只有在点击执行完成后脚本才继续执行。
一般而言,只有点击过程(大约150毫秒)中被其他事件中断(例如用户自行点击)才会点击失败。
使用该函数模拟连续点击时可能有点击速度过慢的问题,这时可以用[press][]函数代替。
可以在开发者选项中启用指针位置来查看坐标
longClick(x, y)#
模拟长按坐标(x, y), 并 返回是否成功。只有在长按执行完成(大约600毫秒)时脚本才会继续执行。
一般而言,只有长按过程中被其他事件中断(例如用户自行点击)才会长按失败。
press(x, y, duration)#
模拟按住坐标(x, y), 并返回是否成功。只有按住操作执行完成时脚本才会继续执行。
如果按住时间过短,那么会被系统认为是点击;如果时长超过500毫秒,则认为是长按。
一般而言,只有按住过程中被其他事件中断才会操作失败。
swipe(x1, y1, x2, y2, duration)#
模拟从坐标(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。
例如手指捏合:
gestures([0, 500, [800, 300], [500, 1000]],
[0, 500, [300, 1500], [500, 1000]]);
setScreenMetrics(width, height)#
设置脚本坐标点击所适合的屏幕宽高。如果脚本运行时,屏幕宽度不一致会自动放缩坐标。
例如在1920*1080的设备中,某个操作的代码为
setScreenMetrics(1080, 1920);
click(800, 200);
longClick(300, 500);
那么在其他设备上AutoJs会自动放缩坐标以便脚本仍然有效。
RootAutomator#
RootAutomator是一个使用root权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。
注意以下命令需要root权限
var ra = new RootAutomator();
RootAutomator.tap(x, y[, id])#
点击位置(x, y)。其中id是一个整数值,用于区分多点触摸,不同的id表示不同的"手指",例如:
var ra = new RootAutomator();
//让"手指1"点击位置(100, 100)
ra.tap(100, 100, 1);
//让"手指2"点击位置(200, 200);
ra.tap(200, 200, 2);
ra.exit();
如果不需要多点触摸,则不需要id这个参数。 多点触摸通常用于手势或游戏操作,例如模拟双指捏合、双指上滑等。
RootAutomator.swipe(x1, x2, y1, y2[, duration, id])#
模拟一次从(x1, y1)到(x2, y2)的时间为duration毫秒的滑动。
RootAutomator.press(x, y, duration[, id])#
模拟按下位置(x, y),时长为duration毫秒。
使用该函数模拟连续点击时可能有点击速度过慢的问题,这时可以用[RootAutomator.press][]函数代替。
RootAutomator.longPress(x, y[\, id])#
模拟长按位置(x, y)。
以上为简单模拟触摸操作的函数。如果要模拟一些复杂的手势,需要更底层的函数。
RootAutomator.touchDown(x, y[\, id])#
模拟手指按下位置(x, y)。
RootAutomator.touchMove(x, y[\, id])#
模拟移动手指到位置(x, y)。
RootAutomator.touchUp([id])#
- id <number> 多点触摸id,可选,默认为1
模拟手指弹起。
使用root权限点击和滑动的简单命令#
注意:本章节的函数在后续版本很可能有改动!请勿过分依赖本章节函数的副作用。推荐使用[RootAutomator][]代替本章节的触摸函数。
以下函数均需要root权限,可以实现任意位置的点击、滑动等。
- 这些函数通常首字母大写以表示其特殊的权限。
- 这些函数均不返回任何值。
- 并且,这些函数的执行是异步的、非阻塞的,在不同机型上所用的时间不同。脚本不会等待动作执行完成才继续执行。因此最好在每个函数之后加上适当的sleep来达到期望的效果。
例如:
Tap(100, 100);
sleep(500);
注意,动作的执行可能无法被停止,例如:
for(var i = 0; i < 100; i++){
Tap(100, 100);
}
这段代码执行后可能会出现在任务管理中停止脚本后点击仍然继续的情况。 因此,强烈建议在每个动作后加上延时:
for(var i = 0; i < 100; i++){
Tap(100, 100);
sleep(500);
}
Tap(x, y)#
- x, y <number> 要点击的坐标。
点击位置(x, y), 您可以通过"开发者选项"开启指针位置来确定点击坐标。
Swipe(x1, y1, x2, y2, [duration])#
滑动。从(x1, y1)位置滑动到(x2, y2)位置。
Images#
images模块提供了一些手机设备中常见的图片处理函数,包括截图、读写图片、图片剪裁、找色、找图等。
images.requestScreenCapture([landscape])#
landscape<boolean> 布尔值, 表示将要执行的截屏是否为横屏。如果landscape为false, 则表示竖屏截图; true为横屏截图。
向系统申请屏幕截图权限,返回是否请求成功。
第一次使用该函数会弹出截图权限请求,建议选择“总是允许”。
这个函数只是申请截图权限,并不会真正执行截图,真正的截图函数是[captureScreen][]。
该函数在截图脚本中只需执行一次,而无需每次调用[captureScreen][]都调用一次。
如果不指定landscape值,则截图方向由当前设备屏幕方向决定,因此务必注意执行该函数时的屏幕方向。
建议在本软件界面运行该函数,在其他软件界面运行时容易出现一闪而过的黑屏现象。
示例:
//请求截图
if(!requestScreenCapture()){
toast("请求截图失败");
exit();
}
//连续截图10张图片(间隔1秒)并保存到存储卡目录
for(var i = 0; i < 10; i++){
captureScreen("/sdcard/screencapture" + i + ".png");
sleep(1000);
}
该函数也可以作为全局函数使用。
images.captureScreen()#
截取当前屏幕并返回一个Image对象。
没有截图权限时执行该函数会抛出SecurityException。
该函数不会返回null,两次调用可能返回相同的Image对象。这是因为设备截图的更新需要一定的时间,短时间内(一般来说是16ms)连续调用则会返回同一张截图。
截图需要转换为Bitmap格式,从而该函数执行需要一定的时间(0~20ms)。
另外在requestScreenCapture()执行成功后需要一定时间后才有截图可用,因此如果立即调用captureScreen(),会等待一定时间后(一般为几百ms)才返回截图。
例子:
//请求横屏截图
requestScreenCapture(true);
//截图
var img = captureScreen();
//获取在点(100, 100)的颜色值
var color = images.pixel(img, 100, 100);
//显示该颜色值
toast(colors.toString(color));
该函数也可以作为全局函数使用。
images.captureScreen(path)#
path<string> 截图保存路径
截取当前屏幕并以PNG格式保存到path中。如果文件不存在会被创建;文件存在会被覆盖。
该函数不会返回任何值。该函数也可以作为全局函数使用。
images.pixel(image, x, y)#
返回图片image在点(x, y)处的像素的ARGB值。
该值的格式为0xAARRGGBB,是一个"32位整数"(虽然JavaScript中并不区分整数类型和其他数值类型)。
坐标系以图片左上角为原点。以图片左侧边为y轴,上侧边为x轴。
images.saveImage(image, path)#
image<image> 图片path<string> 路劲
把图片image以PNG格式保存到path中。如果文件不存在会被创建;文件存在会被覆盖。
images.read(path)#
path<string> 图片路径
读取在路径path的图片文件并返回一个Image对象。如果文件不存在或者文件无法解码则返回null。
images.load(url)#
url<string> 图片URL地址
加载在地址URL的网络图片并返回一个Image对象。如果地址不存在或者图片无法解码则返回null。
images.findColor(image, color, options)#
在图片中寻找颜色color。找到时返回找到的点Point,找不到时返回null。
选项包括:
region<Array> 找色区域。是一个两个或四个元素的数组。(region[0], region[1])表示找色区域的左上角;region[2]*region[3]表示找色区域的宽高。如果只有region只有两个元素,则找色区域为(region[0], region[1])到屏幕右下角。如果不指定region选项,则找色区域为整张图片。threshold<number> 找色时颜色相似度的临界值,范围为0~255(越小越相似,0为颜色相等,255为任何颜色都能匹配)。默认为16。threshold和浮点数相似度(0.0~1.0)的换算为 similarity = (255 - threshold) / 255.
该函数也可以作为全局函数使用。
一个循环找色的例子如下:
requestScreenCapture();
//循环找色,找到红色(#ff0000)时停止并报告坐标
while(true){
var img = captureScreen();
var point = findColor(img, "#ff0000");
if(point){
toast("找到红色,坐标为(" + point.x + ", " + point.y + ")");
}
}
一个区域找色的例子如下:
//读取本地图片/sdcard/1.png
var img = images.read("/sdcard/1.png");
//判断图片是否加载成功
if(!img){
toast("没有该图片");
exit();
}
//在该图片中找色,指定找色区域为在位置(400, 500)的宽为300长为200的区域,指定找色临界值为4
var point = findColor(img, "#00ff00", {
region: [400, 500, 300, 200],
threshold: 4
});
if(point){
toast("找到啦:" + point);
}else{
toast("没找到");
}
images.findColorInRegion(img, color, x, y[, width, height, threshold])#
区域找色的简便方法。
相当于
images.findColor(img, color, {
region: [x, y, width, height],
threshold: threshold
});
该函数也可以作为全局函数使用。
images.findColorEquals(img, color[, x, y, width, height])#
严格找色的简便方法。找色时要求颜色完全相等才匹配。
相当于
images.findColor(img, color, {
region: [x, y, width, height],
threshold: 0
});
该函数也可以作为全局函数使用。
示例: (通过找QQ红点的颜色来判断是否有未读消息)
requestScreenCapture();
launchApp("QQ");
sleep(1200);
var p = findColorEquals(captureScreen(), "#f64d30");
if(p){
toast("有未读消息");
}else{
toast("没有未读消息");
}
images.detectsColor(image, color, x, y[, threshold = 16, algorithm = "diff"])#
image<Image> 图片color<number> | <string> 要检测的颜色x<number> 要检测的位置横坐标y<number> 要检测的位置纵坐标threshold<number> 颜色相似度临界值,默认为16。取值范围为0~255。algorithm<string> 颜色匹配算法,包括:- "equal": 相等匹配,只有与给定颜色color完全相等时才匹配。
- "diff": 差值匹配。与给定颜色的R、G、B差的绝对值之和小于threshold时匹配。
- "rgb": rgb欧拉距离相似度。与给定颜色color的rgb欧拉距离小于等于threshold时匹配。
- "rgb+": 加权rgb欧拉距离匹配(LAB Delta E)。
- "hs": hs欧拉距离匹配。hs为HSV空间的色调值。
返回图片image在位置(x, y)处是否匹配到颜色color。用于检测图片中某个位置是否是特定颜色。
一个判断微博客户端的某个微博是否被点赞过的例子:
requestScreenCapture();
//找到点赞控件
var like = id("ly_feed_like_icon").findOne();
//获取该控件中点坐标
var x = like.bounds().centerX();
var y = like.bounds().centerY();
//截图
var img = captureScreen();
//判断在该坐标的颜色是否为橙红色
if(images.detectsColor(img, "#fed9a8", x, y)){
//是的话则已经是点赞过的了,不做任何动作
}else{
//否则点击点赞按钮
like.click();
}
images.findImage(img, template[, options])#
img<Image> 大图片template<Image> 小图片(模板)options<Object> 找图选项
找图。在大图片img中查找小图片template的位置(模块匹配),找到时返回位置坐标(Point),找不到时返回null。
选项包括:
threshold<number> 图片相似度。取值范围为0~1的浮点数。默认值为0.9。region<Array> 找图区域。参见findColor函数关于region的说明。level<number> 一般而言不必修改此参数。不加此参数时该参数会根据图片大小自动调整。找图算法是采用图像金字塔进行的, level参数表示金字塔的层次, level越大可能带来越高的找图效率,但也可能造成找图失败(图片因过度缩小而无法分辨)或返回错误位置。因此,除非您清楚该参数的意义并需要进行性能调优,否则不需要用到该参数。
该函数也可以作为全局函数使用。
一个最简单的找图例子如下:
var img = images.read("/sdcard/大图.png");
var templ = images.read("/sdcard/小图.png");
var p = findImage(img, templ);
if(p){
toast("找到啦:" + p);
}else{
toast("没找到");
}
稍微复杂点的区域找图例子如下:
auto();
requestScreenCapture();
var wx = images.read("/sdcard/微信图标.png");
//返回桌面
home();
//截图并找图
var p = findImage(captureScreen(), wx, {
region: [0, 50],
threshold: 0.8
});
if(p){
toast("在桌面找到了微信图标啦: " + p);
}else{
toast("在桌面没有找到微信图标");
}
images.findImageInRegion(img, template, x, y[, width, height, threshold])#
区域找图的简便方法。相当于:
images.findImage(img, template, {
region: [x, y, width, height],
threshold: threshold
})
该函数也可以作为全局函数使用。
colors#
colors是颜色处理的工具对象。包含一些常用方法,包括android.graphics.Color的所有方法以及toString方法。
colors.toString(color)#
color<number> 整数RGB颜色值
返回颜色值的字符串,格式为 #AARRGGBB。
colors.red(color)#
color<number> 整数RGB颜色值
返回颜色color的R通道的值,范围0~255.
colors.green(color)#
color<number> 整数RGB颜色值
返回颜色color的G通道的值,范围0~255.
colors.blue(color)#
color<number> 整数RGB颜色值
返回颜色color的B通道的值,范围0~255.
colors.alpha(color)#
color<number> 整数RGB颜色值
返回颜色color的Alpha通道的值,范围0~255.
colors.rgb(red, green, blue)#
返回这些颜色通道构成的整数颜色值。Alpha通道将是255(不透明)。
colors.argb(alpha, red, green, blue)#
返回这些颜色通道构成的整数颜色值。
Image#
表示一张图片,可以是截图的图片,或者本地读取的图片,或者从网络获取的图片。
Image.getWidth()#
返回以像素为单位图片宽度。
Image.getHeight()#
返回以像素为单位的图片高度。
Image.saveTo(path)#
path<string> 路径
把图片保存到路径path。(如果文件存在则覆盖)
Image.pixel(x, y)#
返回图片image在点(x, y)处的像素的ARGB值。
该值的格式为0xAARRGGBB,是一个"32位整数"(虽然JavaScript中并不区分整数类型和其他数值类型)。
坐标系以图片左上角为原点。以图片左侧边为y轴,上侧边为x轴。
Point#
findColor, findImage返回的对象。表示一个点(坐标)。
Point.x#
横坐标。
Point.y#
纵坐标。
Console#
控制台模块提供了一个和Web浏览器中相似的用于调试的控制台。用于输出一些调试信息、中间结果等。 console模块中的一些函数也可以直接作为全局函数使用,例如log, print等。
console.show()#
显示控制台。这会显示一个控制台的悬浮窗(需要悬浮窗权限)。
console.clear()#
清空控制台。
console.log([data][, ...args])#
data...args
打印到控制台,并带上换行符。 可以传入多个参数,第一个参数作为主要信息,其他参数作为类似于 printf(3) 中的代替值(参数都会传给 util.format())。
const count = 5;
console.log('count: %d', count);
// 打印: count: 5 到 stdout
console.log('count:', count);
// 打印: count: 5 到 stdout
详见 util.format()。
console.verbose([data][, ...args])#
data...args
与console.log类似,但输出结果以灰色字体显示。输出优先级低于log,用于输出观察性质的信息。
console.info([data][, ...args])#
data...args
与console.log类似,但输出结果以绿色字体显示。输出优先级高于log, 用于输出重要信息。
console.warn([data][, ...args])#
data...args
与console.log类似,但输出结果以蓝色字体显示。输出优先级高于info, 用于输出警告信息。
console.error([data][, ...args])#
data...args
与console.log类似,但输出结果以红色字体显示。输出优先级高于warn, 用于输出错误信息。
console.assert(value, message)#
- value <any> 要断言的布尔值
- message <string> value为false时要输出的信息
断言。如果value为false则输出错误信息message并停止脚本运行。
console.input(data[, ...args])#
data...args
与console.log一样输出信息,并在控制台显示输入框等待输入。按控制台的确认按钮后会将输入的字符串用eval计算后返回。
部分机型可能会有控制台不显示输入框的情况,属于bug。
例如:
var n = console.input("请输入一个数字:");
//输入123之后:
toast(n + 1);
//显示124
console.rawInput(data[, ...args])#
data...args
与console.log一样输出信息,并在控制台显示输入框等待输入。按控制台的确认按钮后会将输入的字符串直接返回。
部分机型可能会有控制台不显示输入框的情况,属于bug。
例如:
var n = console.input("请输入一个数字:");
//输入123之后:
toast(n + 1);
//显示1231
print(text)#
在控制台中输出文本text。不会自动换行。
Events#
events模块提供了监听手机通知、按键、触摸的接口。您可以用他配合自动操作函数完成自动化工作。
events本身是一个EventEmiiter, 但内置了一些事件、包括按键事件、通知事件、Toast事件等。
events.emitter()#
返回一个新的[EventEmitter][]。这个EventEmitter没有内置任何事件。
events.observeKey()#
启用按键监听,例如音量键、Home键。此函数使用无障碍服务实现,因此此函数会调用auto()确保无障碍服务启用。
只有这个函数成功执行后, [onKeyDown][], [onKeyUp][]等按键事件的监听才有效。
该函数在安卓4.3以上才能使用。
events.onKeyDown(keyName, listener)#
keyName<string> 要监听的按键名称listener<Function> 按键监听器。参数为一个KeyEvent。
注册一个按键监听函数,当有keyName对应的按键被按下会调用该函数。可用的按键名称参见[Keys][]。
例如:
//启用按键监听
events.observeKey();
//监听音量上键按下
events.onKeyDown("volume_up", function(event){
toast("音量上键被按下了");
});
//监听菜单键按下
events.onKeyDown("menu", function(event){
toast("菜单键被按下了");
exit();
});
events.onKeyUp(keyName, listener)#
keyName<string> 要监听的按键名称listener<Function> 按键监听器。参数为一个KeyEvent。
注册一个按键监听函数,当有keyName对应的按键弹起会调用该函数。可用的按键名称参见Keys。
一次完整的按键动作包括了按键按下和弹起。按下事件会在手指按下一个按键的"瞬间"触发, 弹起事件则在手指放开这个按键时触发。
例如:
//启用按键监听
events.observeKey();
//监听音量下键弹起
events.onKeyDown("volume_down", function(event){
toast("音量上键弹起");
});
//监听Home键弹起
events.onKeyDown("home", function(event){
toast("Home键弹起");
exit();
});
events.onceKeyDown(keyName, listener)#
keyName<string> 要监听的按键名称listener<Function> 按键监听器。参数为一个KeyEvent
注册一个按键监听函数,当有keyName对应的按键被按下时会调用该函数,之后会注销该按键监听器。
也就是listener只有在onceKeyDown调用后的第一次按键事件被调用一次。
events.onceKeyUp(keyName, listener)#
keyName<string> 要监听的按键名称listener<Function> 按键监听器。参数为一个KeyEvent
注册一个按键监听函数,当有keyName对应的按键弹起时会调用该函数,之后会注销该按键监听器。
也就是listener只有在onceKeyUp调用后的第一次按键事件被调用一次。
events.removeAllKeyDownListeners(keyName)#
keyName<string> 按键名称
删除该按键的KeyDown(按下)事件的所有监听。
events.removeAllKeyUpListeners(keyName)#
keyName<string> 按键名称
删除该按键的KeyUp(弹起)事件的所有监听。
events.observeTouch()#
启用屏幕触摸监听。(需要root权限)
只有这个函数被成功执行后, 触摸事件的监听才有效。
没有root权限调用该函数则什么也不会发生。(注意: 这个行为未来可能会更改为抛出异常)
events.setTouchEventTimeout(timeout)#
timeout<number> 两个触摸事件的最小间隔。单位毫秒。默认为10毫秒。如果number小于0,视为0处理。
设置两个触摸事件分发的最小时间间隔。
例如间隔为10毫秒的话,前一个触摸事件发生并被注册的监听器处理后,至少要过10毫秒才能分发和处理下一个触摸事件,这10毫秒之间的触摸将会被忽略。
建议在满足需要的情况下尽量提高这个间隔。一个简单滑动动作可能会连续触发上百个触摸事件,如果timeout设置过低可能造成事件拥堵。强烈建议不要设置timeout为0。
events.getTouchEventTimeout()#
返回触摸事件的最小时间间隔。
events.onTouch(listener)#
listener<Function> 参数为[Point][]的函数
注册一个触摸监听函数。相当于on("touch", listener)。
例如:
//启用触摸监听
events.observeTouch();
//注册触摸监听器
events.onTouch(function(p){
//触摸事件发生时, 打印出触摸的点的坐标
log(p.x + ", " + p.y);
});
events.removeAllTouchListeners()#
删除所有事件监听函数。
事件: 'key'#
keyCode<number> 键值event<KeyEvent> 事件
当有按键被按下或弹起时会触发该事件。 例如:
auto();
events.observeKey();
events.on("key", function(keyCode, event){
//处理按键事件
});
其中监听器的参数KeyCode包括:
KeyEvent.KEYCODE_HOME主页键KeyEvent.KEYCODE_BACK返回键KeyEvent.KEYCODE_MENU菜单键KeyEvent.KEYCODE_VOLUMEUP音量上键KeyEvent.KEYCODE_VOLUMEDOWN音量下键
事件: 'key_down'#
keyCode<number> 键值event<KeyEvent> 事件
当有按键被按下时会触发该事件。
auto();
events.observeKey();
events.on("key_down", function(keyCode, event){
//处理按键按下事件
});
事件: 'key_up'#
keyCode<number> 键值event<KeyEvent> 事件
当有按键弹起时会触发该事件。
auto();
events.observeKey();
events.on("key_up", function(keyCode, event){
//处理按键弹起事件
});
obverseNotification()#
开启通知(包括Toast)监听。
通知与Toast监听依赖于无障碍服务,因此这个函数会调用auto()来确保无障碍服务启用。
例如:
events.obverseNotification();
events.onNotification(function(notification){
log(notification.getText());
});
events.onToast(function(toast){
log(toast.getText());
});
事件: 'toast'#
toast<Object>getText()获取Toast的文本内容getPackageName()获取发出Toast的应用包名
当有应用发出toast(气泡消息)时会触发该事件。但Auto.js软件本身的toast除外。 例如,要记录发出所有toast的应用:
events.obverseNotification();
events.onToast(function(toast){
log("Toast内容: " + toast.getText() + " 包名: " + toast.getPackageName());
});
事件: 'notification'#
notification<Object> 通知
当有应用发出通知时会触发该事件。
例如:
events.observeNotification();
events.on("notification", function(notification){
log(notification);
});
注意: 这是一个实验性功能。实测只有某些情况下的通知才能被正确捕捉。
EventEmitter#
EventEmitter.defaultMaxListeners#
每个事件默认可以注册最多 10 个监听器。 单个 EventEmitter 实例的限制可以使用 emitter.setMaxListeners(n) 方法改变。 所有 EventEmitter 实例的默认值可以使用 EventEmitter.defaultMaxListeners 属性改变。
设置 EventEmitter.defaultMaxListeners 要谨慎,因为会影响所有 EventEmitter 实例,包括之前创建的。 因而,调用 emitter.setMaxListeners(n) 优先于 EventEmitter.defaultMaxListeners。
注意,与Node.js不同,这是一个硬性限制。 EventEmitter 实例不允许添加更多的监听器,监听器超过最大数量时会抛出TooManyListenersException。
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// 做些操作
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
EventEmitter.addListener(eventName, listener)#
eventName<any>listener<Function>
emitter.on(eventName, listener) 的别名。
EventEmitter.emit(eventName[, ...args])#
eventName<any>args<any>
按监听器的注册顺序,同步地调用每个注册到名为 eventName 事件的监听器,并传入提供的参数。
如果事件有监听器,则返回 true ,否则返回 false。
EventEmitter.eventNames()#
返回一个列出触发器已注册监听器的事件的数组。 数组中的值为字符串或符号。
const myEE = events.emitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// 打印: [ 'foo', 'bar', Symbol(symbol) ]
EventEmitter.getMaxListeners()#
返回 EventEmitter 当前的最大监听器限制值,该值可以通过 emitter.setMaxListeners(n) 设置或默认为 EventEmitter.defaultMaxListeners。
EventEmitter.listenerCount(eventName)#
eventName<string> 正在被监听的事件名
返回正在监听名为 eventName 的事件的监听器的数量。
EventEmitter.listeners(eventName)#
eventName<string>
返回名为 eventName 的事件的监听器数组的副本。
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// 打印: [ [Function] ]
EventEmitter.on(eventName, listener)#
eventName<any> 事件名listener<Function> 回调函数
添加 listener 函数到名为 eventName 的事件的监听器数组的末尾。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。
server.on('connection', (stream) => {
console.log('有连接!');
});
返回一个 EventEmitter 引用,可以链式调用。
默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependListener() 方法可用于将事件监听器添加到监听器数组的开头。
const myEE = events.emitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// 打印:
// b
// a
EventEmitter.once(eventName, listener)#
eventName<any> 事件名listener<Function> 回调函数
添加一个单次 listener 函数到名为 eventName 的事件。 下次触发 eventName 事件时,监听器会被移除,然后调用。
server.once('connection', (stream) => {
console.log('首次调用!');
});
返回一个 EventEmitter 引用,可以链式调用。
默认情况下,事件监听器会按照添加的顺序依次调用。 emitter.prependOnceListener() 方法可用于将事件监听器添加到监听器数组的开头。
const myEE = events.emitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// 打印:
// b
// a
EventEmitter.prependListener(eventName, listener)#
eventName<any> 事件名listener<Function> 回调函数
添加 listener 函数到名为 eventName 的事件的监听器数组的开头。 不会检查 listener 是否已被添加。 多次调用并传入相同的 eventName 和 listener 会导致 listener 被添加与调用多次。
server.prependListener('connection', (stream) => {
console.log('有连接!');
});
返回一个 EventEmitter 引用,可以链式调用。
EventEmitter.prependOnceListener(eventName, listener)#
eventName<any> 事件名listener<Function> 回调函数
添加一个单次 listener 函数到名为 eventName 的事件的监听器数组的开头。 下次触发 eventName 事件时,监听器会被移除,然后调用。
server.prependOnceListener('connection', (stream) => {
console.log('首次调用!');
});
返回一个 EventEmitter 引用,可以链式调用。
EventEmitter.removeAllListeners([eventName])#
eventName<any>
移除全部或指定 eventName 的监听器。
注意,在代码中移除其他地方添加的监听器是一个不好的做法,尤其是当 EventEmitter 实例是其他组件或模块创建的。
返回一个 EventEmitter 引用,可以链式调用。
EventEmitter.removeListener(eventName, listener)#
eventName<any>listener<Function>
从名为 eventName 的事件的监听器数组中移除指定的 listener。
const callback = (stream) => {
console.log('有连接!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
removeListener 最多只会从监听器数组里移除一个监听器实例。 如果任何单一的监听器被多次添加到指定 eventName 的监听器数组中,则必须多次调用 removeListener 才能移除每个实例。
注意,一旦一个事件被触发,所有绑定到它的监听器都会按顺序依次触发。 这意味着,在事件触发后、最后一个监听器完成执行前,任何 removeListener() 或 removeAllListeners() 调用都不会从 emit() 中移除它们。 随后的事件会像预期的那样发生。
const myEmitter = events.emitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA 移除了监听器 callbackB,但它依然会被调用。
// 触发是内部的监听器数组为 [callbackA, callbackB]
myEmitter.emit('event');
// 打印:
// A
// B
// callbackB 被移除了。
// 内部监听器数组为 [callbackA]
myEmitter.emit('event');
// 打印:
// A
因为监听器是使用内部数组进行管理的,所以调用它会改变在监听器被移除后注册的任何监听器的位置索引。 虽然这不会影响监听器的调用顺序,但意味着由 emitter.listeners() 方法返回的监听器数组副本需要被重新创建。
返回一个 EventEmitter 引用,可以链式调用。
EventEmitter.setMaxListeners(n)#
n<number>
默认情况下,如果为特定事件添加了超过 10 个监听器,则 EventEmitter 会打印一个警告。 此限制有助于寻找内存泄露。 但是,并不是所有的事件都要被限为 10 个。 emitter.setMaxListeners() 方法允许修改指定的 EventEmitter 实例的限制。 值设为 Infinity(或 0)表明不限制监听器的数量。
返回一个 EventEmitter 引用,可以链式调用。
KeyEvent#
KeyEvent.getAction()#
返回事件的动作。包括:
KeyEvent.ACTION_DOWN按下事件KeyEvent.ACTION_UP弹起事件
KeyEvent.getKeyCode()#
返回按键的键值。包括:
KeyEvent.KEYCODE_HOME主页键KeyEvent.KEYCODE_BACK返回键KeyEvent.KEYCODE_MENU菜单键KeyEvent.KEYCODE_VOLUME_UP音量上键KeyEvent.KEYCODE_VOLUME_DOWN音量下键
KeyEvent.getEventTime()#
返回事件发生的时间戳。返回值的类型是number。
KeyEvent.getDownTime()#
返回最近一次按下事件的时间戳。如果本身是按下事件,则与getEventTime()相同。
KeyEvent.keyCodeToString(keyCode)#
把键值转换为字符串。例如KEYCODE_HOME转换为"KEYCODE_HOME"。
Keys#
按键事件中所有可用的按键名称为:
volume_up音量上键volume_down音量下键home主屏幕键back返回键menu菜单键
Timers#
timers 模块暴露了一个全局的 API,用于在某个未来时间段调用调度函数。 因为定时器函数是全局的,所以使用该 API 无需调用 timers.*
Auto.js 中的计时器函数实现了与 Web 浏览器提供的定时器类似的 API,除了它使用了一个不同的内部实现,它是基于 Android Looper-Handler消息循环机制构建的。其实现机制与Node.js比较相似。
setImmediate(callback[, ...args])#
callback<Function> 在Looper循环的当前回合结束时要调用的函数。...args<any> 当调用 callback 时要传入的可选参数。
预定立即执行的 callback,它是在 I/O 事件的回调之后被触发。 返回一个用于 clearImmediate() 的 id。
当多次调用 setImmediate() 时,callback 函数会按照它们被创建的顺序依次执行。 每次事件循环迭代都会处理整个回调队列。 如果一个立即定时器是被一个正在执行的回调排入队列的,则该定时器直到下一次事件循环迭代才会被触发。
setInterval(callback, delay[, ...args])#
callback<Function> 当定时器到点时要调用的函数。delay<number> 调用 callback 之前要等待的毫秒数。...args<any> 当调用 callback 时要传入的可选参数。
预定每隔 delay 毫秒重复执行的 callback。 返回一个用于 clearInterval() 的 id。
当 delay 小于 0 时,delay 会被设为 0。
setTimeout(callback, delay[, ...args])#
callback<Function> 当定时器到点时要调用的函数。delay<number> 调用 callback 之前要等待的毫秒数。...args<any> 当调用 callback 时要传入的可选参数。
预定在 delay 毫秒之后执行的单次 callback。 返回一个用于 clearTimeout() 的 id。
callback 可能不会精确地在 delay 毫秒被调用。 Auto.js 不能保证回调被触发的确切时间,也不能保证它们的顺序。 回调会在尽可能接近所指定的时间上调用。
当 delay 小于 0 时,delay 会被设为 0。
setImmediate()、setInterval() 和 setTimeout() 方法每次都会返回表示预定的计时器的id。 它们可用于取消定时器并防止触发。
clearImmediate(id)#
id<number> 一个 setImmediate() 返回的 id。
取消一个由 setImmediate() 创建的 Immediate 对象。
clearInterval(id)#
id<number> 一个 setInterval() 返回的 id。
取消一个由 setInterval() 创建的 Timeout 对象。
clearTimeout(id)#
id<number> 一个 setTimeout() 返回的 id。
取消一个由 setTimeout() 创建的 Timeout 对象。
shell即Unix Shell,在类Unix系统提供与操作系统交互的一系列命令。
很多程序可以用来执行shell命令,例如终端模拟器。
在Auto.js大致等同于用adb执行命令"adb shell"。其实现包括两种方式:
- 通过
java.lang.Runtime.exec执行(shell, Tap, Home等函数) - 通过内嵌终端模拟器执行(RootAutomator, Shell等对象)
shell函数#
shell(cmd[, root = false])#
返回运行一个对象表示命令的执行结果。其属性如下:
- code <number> 返回码。执行成功时为0,失败时为非0的数字。
- result <string> 运行结果(stdout输出结果)
- error \
运行的错误信息(stderr输出结果)。例如执行需要root权限的命令但没有授予root权限会返回错误信息"Permission denied"。
示例(强制停止微信) :
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进程。
Shell(root = false)#
- root <Boolean> 是否以root权限运行一个shell进程。这将会影响其后使用该Shell对象执行的命令的权限
Shell对象的"构造函数"。
var sh = new Shell(true);
sh.exec("am force-stop com.tencent.mm");
sh.exit();
Shell.exec(cmd)#
cmd<string> 要执行的命令
执行命令cmd。该函数不会返回任何值。
注意,命令执行是"异步"的、非阻塞的。也就是不会等待命令完成后才继续向下执行。
尽管这样的设计使用起来有很多不便之处,但受限于终端模拟器,暂时没有解决方式;如果后续能找到解决方案,则将提供Shell.execAndWaitFor函数。
Shell.exit()#
直接退出shell。这意味着正在执行的命令会被强制退出。
Shell.exitAndWaitFor()#
执行"exit"命令并等待执行命令执行完成、退出shell。
此函数会执行exit命令来正常退出shell。
Shell.setCallback(callback)#
- callback <Object> 回调函数
设置该Shell的回调函数,以便监听Shell的输出。可以包括以下属性:
- onOutput <function> 每当shell有新的输出时便会调用该函数。其参数是一个字符串。
- onNewLine <function> 每当shell有新的一行输出时便会调用该函数。其参数是一个字符串(不包括最后的换行符)。
例如:
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:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
startservice [options] intent#
启动 intent 指定的 Service(服务)。
请参阅 intent 参数的规范。
选项包括:
- --user user_id | current:指定要作为哪个用户运行;如果未指定,则作为当前用户运行。
force-stop package#
强行停止与 package(应用包名)关联的所有应用。
kill [options] package#
终止与 package(应用包名)关联的所有进程。此命令仅终止可安全终止且不会影响用户体验的进程。
选项包括:
- --user user_id | all | current:指定将终止其进程的用户;如果未指定,则终止所有用户的进程。
kill-all#
终止所有后台进程。
broadcast [options] intent#
发出广播 intent。 请参阅 intent 参数的规范。
选项包括:
- [--user user_id | all | current]:指定要发送到的用户;如果未指定,则发送到所有用户。
instrument [options] component#
使用 Instrumentation 实例启动监控。通常,目标 component 是表单 test_package/runner_class。
选项包括:
- -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 的分析器。
dumpheap [options] process file#
转储 process 的堆,写入 file。
选项包括:
- --user [user_id|current]:提供进程名称时,指定要转储的进程用户;如果未指定,则使用当前用户。
- -n:转储原生堆,而非托管堆。
- set-debug-app [options] package 将应用 package 设为调试。
选项包括:
- -w:应用启动时等待调试程序。
- --persistent:保留此值。
- clear-debug-app 使用 set-debug-app 清除以前针对调试用途设置的软件包。
monitor [options] 启动对崩溃或 ANR 的监控。#
选项包括:
- --gdb:在崩溃/ANR 时在给定端口上启动 gdbserv。
screen-compat <on> | <off> package#
控制 package 的屏幕兼容性模式。
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;如果参数包含一个“/”(正斜杠),则此工具假定参数是一个组件名称;否则,此工具假定参数是一个软件包名称。
应用包名#
所谓应用包名,是唯一确定应用的标识。例如微信的包名是"com.tencent.mm", QQ的包名是"com.tencent.mobileqq"。
要获取一个应用的包名,可以通过函数getPackageName(appName)获取。参见帮助->其他一般函数。
pm命令#
pm命令用于管理应用程序,例如卸载应用、冻结应用等。
以下命令均以"pm "开头,例如"shell(\"pm disable com.tencent.mm\");"(冻结微信)
list packages [options] filter#
输出所有软件包,或者,仅输出包名称包含 filter 中的文本的软件包。
选项:
- -f:查看它们的关联文件。
- -d:进行过滤以仅显示已停用的软件包。
- -e:进行过滤以仅显示已启用的软件包。
- -s:进行过滤以仅显示系统软件包。
- -3:进行过滤以仅显示第三方软件包。
- -i:查看软件包的安装程序。
- -u:也包括卸载的软件包。
- --user user_id:要查询的用户空间。
list permission-groups#
输出所有已知的权限组。
list permissions [options] group#
输出所有已知权限,或者,仅输出 group 中的权限。
选项:
- -g:按组加以组织。
- -f:输出所有信息。
- -s:简短摘要。
- -d:仅列出危险权限。
- -u:仅列出用户将看到的权限。
list instrumentation [options]#
列出所有测试软件包。
选项:
- -f:列出用于测试软件包的 APK 文件。
- target_package:列出仅用于此应用的测试软件包。
list features#
输出系统的所有功能。
list libraries#
输出当前设备支持的所有库。
list users#
输出系统上的所有用户。
path package#
输出给定 package 的 APK 的路径。
install [options] path#
将软件包(通过 path 指定)安装到系统。
选项:
- -l:安装具有转发锁定功能的软件包。
- -r:重新安装现有应用,保留其数据。
- -t:允许安装测试 APK。
- -i installer_package_name:指定安装程序软件包名称。
- -s:在共享的大容量存储(如 sdcard)上安装软件包。
- -f:在内部系统内存上安装软件包。
- -d:允许版本代码降级。
- -g:授予应用清单文件中列出的所有权限。
uninstall [options] package#
从系统中卸载软件包。
选项:
- -k:移除软件包后保留数据和缓存目录。
clear package#
删除与软件包关联的所有数据。
enable package_or_component#
启用给定软件包或组件(作为“package/class”写入)。
disable package_or_component#
停用给定软件包或组件(作为“package/class”写入)。
disable-user [options] package_or_component#
选项:
- --user user_id:要停用的用户。
grant package_name permission#
向应用授予权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,可以是应用清单中声明的任何权限。在运行 Android 5.1(API 级别 22)和更低版本的设备上,必须是应用定义的可选权限。
revoke package_name permission#
从应用中撤销权限。在运行 Android 6.0(API 级别 23)及更高版本的设备上,可以是应用清单中声明的任何权限。在运行 Android 5.1(API 级别 22)和更低版本的设备上,必须是应用定义的可选权限。
set-install-location location#
更改默认安装位置。位置值:
- 0:自动—让系统决定最佳位置。
- 1:内部—安装在内部设备存储上。
- 2:外部—安装在外部介质上。
注:此命令仅用于调试目的;使用此命令会导致应用中断和其他意外行为。
get-install-location#
返回当前安装位置。返回值:
- 0 [auto]:让系统决定最佳位置。
- 1 [internal]:安装在内部设备存储上
- 2 [external]:安装在外部介质上
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);
Files#
files模块提供了一些常见的文件处理,包括文件读写、移动、复制、删掉等。
files.isFile(path)#
path<string> 路径
返回路径path是否是文件。
files.isDir(path)#
path<string> 路径
返回路径path是否是文件夹。
files.isEmptyDir(path)#
path<string> 路径
返回文件夹path是否为空文件夹。如果该路径并非文件夹,则直接返回false。
files.join(parent, child)#
连接两个路径并返回,例如files.join("/sdcard/", "1.txt")返回"/sdcard/1.txt"。
files.create(path)#
path<string> 路径
创建一个文件并返回是否创建成功。
files.createIfNotExists(path)#
path<string> 路径
创建一个文件并返回是否创建成功。
files.exists(path)#
path<string> 路径
返回在路径path处的文件是否存在。
files.ensureDir(path)#
path<string> 路径
确保路径path所在的文件夹存在。
例如对于路径"/sdcard/Download/ABC/1.txt",如果/Download/文件夹不存在,则会先创建Download,再创建ABC文件夹。
files.read(path[, encoding = "utf-8"])#
读取文件path的所有内容并返回。
files.write(path, text[, encoding = "utf-8"])#
把text写入到文件path中。如果文件存在则覆盖,不存在则创建。
files.copy(fromPath, toPath)#
复制文件。例如files.copy("/sdcard/1.txt", "/sdcard/Download/1.txt")。
files.move(fromPath, toPath)#
移动文件,返回是否移动成功。例如files.move("/sdcard/1.txt", "/sdcard/Download/1.txt")会把1.txt文件从sd卡根目录移动到Download文件夹。
files.rename(path, newName)#
重命名文件,并返回是否重命名成功。例如files.rename("/sdcard/1.txt", "2.txt")。
files.renameWithoutExtension(path, newName)#
重命名文件,不包含拓展名,并返回是否重命名成功。例如files.rename("/sdcard/1.txt", "2")会把1.txt重命名为2.txt。
files.getName(path)#
path<string> 路径
返回文件的文件名。例如files.getName("/sdcard/1.txt")返回"1.txt"。
files.getNameWithoutExtension(path)#
path<string> 路径
返回不含拓展名的文件的文件名。例如files.getName("/sdcard/1.txt")返回"1"。
files.getExtension(path)#
path<string> 路径
返回文件的拓展名。例如files.getExtension("/sdcard/1.txt")返回"txt"。
files.remove(path)#
path<string> 路径
删除文件或空文件夹,返回是否删除成功。
files.removeDir(path)#
删除文件夹,如果文件夹不为空,则删除该文件夹的所有内容再删除该文件夹,返回是否全部删除成功。
files.getSdcardPath()#
返回SD卡路径。所谓SD卡,即外部存储器。
files.listDir(path[, filter])#
path<string> 路径filter<Function> 过滤函数,可选。接收一个String参数(文件名),返回一个Boolean值。
列出文件夹path下的满足条件的文件和文件夹的名称的数组。如果不加filter参数,则返回所有文件和文件夹。
例如,获取sdcard目录下的txt文件为
var txtFiles = files.listDir("/sdcard/", function(name){
return name.endsWith(".txt") && files.isFile("/sdcard/" + name);
});
open(path[, mode = "r", encoding = "utf-8", bufferSize = 8192])#
打开一个文件。根据打开模式返回不同的文件对象。包括:
- "r": 返回一个ReadableTextFile对象。
- "w", "a": 返回一个WritableTextFile对象。
对于"w"模式,如果文件并不存在,则会创建一个,已存在则会清空该文件内容;其他模式文件不存在会抛出FileNotFoundException。
ReadableTextFile#
可读文件对象。
ReadableTextFile.read()#
返回该文件剩余的所有内容的字符串。
ReadableTextFile.read(maxCount)#
maxCount<Number> 最大读取的字符数量
读取该文件接下来最长为maxCount的字符串并返回。即使文件剩余内容不足maxCount也不会出错。
ReadableTextFile.readline()#
读取一行并返回(不包含换行符)。
ReadableTextFile.readlines()#
读取剩余的所有行,并返回它们按顺序组成的字符串数组。
close()#
关闭该文件。
打开一个文件不再使用时务必关闭
PWritableTextFile#
可写文件对象。
PWritableTextFile.write(text)#
text<string> 文本
把文本内容text写入到文件中。
PWritableTextFile.writeline(line)#
text<string> 文本
把文本line写入到文件中并写入一个换行符。
PWritableTextFile.writelines(lines)#
lines<Array> 字符串数组
把很多行写入到文件中....
PWritableTextFile.flush()#
把缓冲区内容输出到文件中。
PWritableTextFile.close()#
关闭文件。同时会被缓冲区内容输出到文件。
打开一个文件写入后,不再使用时务必关闭,否则文件可能会丢失
App#
app模块提供一系列函数,用于与其他应用的交互。例如打开文件、拍照、发送邮件等。
同时提供了方便的基础函数startActivity和sendBroadcast,用他们可完成app模块没有内置的和其他应用的交互。
app.viewFile(path)#
- path <string> 文件路径
用其他应用查看文件。
app.editFile(path)#
- path <string> 文件路径
用其他应用编辑文件。
app.uninstall(packageName)#
- packageName <string> 应用包名
卸载应用。
app.openUrl(url)#
- url <string> 网站的Url
用浏览器打开网站url。
app.takePhoto(path)#
path<string> 照片保存路径
调用相机应用拍照,完成后保存到路径path。
app.sendEmail(options)#
根据选项options调用邮箱应用发送邮件。这些选项均是可选的。
app.intent(intent)#
- intent <Object> 一个表示Intent对象,其属性可以包括:
- action <string> 这个Intent的Action,比如"android.intent.action.SEND"
- type <string> 这个Intent的MimeType,比如"text/plain"
- data <string> 这个Intent的Data(Uri),可以是文件路径或者Url等。
- category \
这个Intent的Category的字符串数组。 - packageName <string> 目标包名
- className <string> 目标Activity或Service等组件的名称
- extras <Object> 以键值对构成的这个Intent的Extras。
返回用intent对象构造的android.content.Intent对象。
例如:
var i = app.intent({
action: "android.intent.action.VIEW",
type: "text/plain",
data: "file:///sdcard/1.txt",
});
如果你看了一脸懵逼,请百度安卓Intent。
app.startActivity(intent)#
- intent <Object> 与app.intent函数的参数一样的intent对象。
相当于context.startActivity(intent)。
app.sendBroadcast(intent)#
- intent <Object> 与app.intent函数的参数一样的intent对象。
相当于context.sendBroadcast(intent)。
HTTP#
http模块提供一些进行http请求的函数。
http.get(url[, options, callback])#
url<string> 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。options<Object> 请求选项。参见[http.request()][]。callback<Function> 回调函数,可选,其参数是一个[Response][]对象。如果不加回调函数,则该请求将阻塞、同步地执行。
对地址url进行一次HTTP GET 请求。如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。
最简单GET请求如下:
console.show();
var r = http.get("www.baidu.com");
log("code = " + r.statusCode);
log("html = " + r.body.string());
采用回调形式的GET请求如下:
console.show();
http.get("www.baidu.com", {}, function(res, err){
if(err){
console.error(err);
return;
}
log("code = " + r.statusCode);
log("html = " + r.body.string());
});
如果要增加HTTP头部信息,则在options参数中添加,例如:
console.show();
var r = http.get("www.baidu.com", {
headers: {
"Accept-Language": "zh-cn,zh;q=0.5",
"User-Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X
10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56
Safari/535.11"
}
});
log("code = " + r.statusCode);
log("html = " + r.body.string());
一个请求天气并解析返回的天气JSON结果的例子如下:
var city = "广州";
var res = http.get("http://www.sojson.com/open/api/weather/json.shtml?city=" + city);
if(res.statusCode != 200){
toast("请求失败: " + res.statusCode + " " + res.statusMessage);
}else{
var weather = res.body.json();
log(weather);
toast(util.format("温度: %s 湿度: %s 空气质量: %s", weather.data.wendu,
weather.data.shidu, weather.quality));
}
http.post(url, data[, options, callback])#
url<string> 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。data<string> | <Object> POST数据。options<Object> 请求选项。callback<Function> 回调,其参数是一个[Response][]对象。如果不加回调参数,则该请求将阻塞、同步地执行。
对地址url进行一次HTTP POST 请求。如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。
其中POST数据可以是字符串或键值对。具体含义取决于options.contentType的值。默认为"application/x-www-form-urlencoded"(表单提交), 这种方式是JQuery的ajax函数的默认方式。
一个模拟表单提交登录淘宝的例子如下:
var url = "https://login.taobao.com/member/login.jhtml";
var username = "你的用户名";
var password = "你的密码";
var res = http.post(url, {
"TPL_username": username,
"TPL_password": password
});
var html = res.body.string();
if(html.contains("页面跳转中")){
toast("登录成功");
}else{
toast("登录失败");
}
http.postJson(url[, data, options, callback])#
url<string> 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。data<Object> POST数据。options<Object> 请求选项。callback<Function> 回调,其参数是一个[Response][]对象。如果不加回调参数,则该请求将阻塞、同步地执行。
以JSON格式向目标Url发起POST请求。如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。
JSON格式指的是,将会调用JSON.stringify()把data对象转换为JSON字符串,并在HTTP头部信息中把"Content-Type"属性置为"application/json"。这种方式是AngularJS的ajax函数的默认方式。
一个调用图灵机器人接口的例子如下:
http.request(url[, options, callback])#
url<string> 请求的URL地址,需要以"http://"或"https://"开头。如果url没有以"http://"开头,则默认为"http://"。options<Object> 请求选项。参见[http.buildRequest()][]。callback<Function> 回调,其参数是一个[Response][]对象。如果不加回调参数,则该请求将阻塞、同步地执行。
对目标地址url发起一次HTTP请求。如果没有回调函数,则在请求完成或失败时返回此次请求的响应(参见[Response][])。
选项options可以包含以下属性:
headers<Object> 键值对形式的HTTP头部信息。有关HTTP头部信息,参见菜鸟教程:HTTP响应头信息。method<string> HTTP请求方法。包括"GET", "POST", "PUT", "DELET", "PATCH"。contentType<string> HTTP头部信息中的"Content-Type", 表示HTTP请求的内容类型。例如"text/plain", "application/json"。更多信息参见菜鸟教程:HTTP contentType。body<string> | <Array> | <Function> HTTP请求的内容。可以是一个字符串,也可以是一个字节数组;或者是一个以BufferedSink为参数的函数。
该函数是get, post, postJson等函数的基础函数。因此除非是PUT, DELET等请求,或者需要更高定制的HTTP请求,否则直接使用get, post, postJson等函数会更加方便。
Response#
HTTP请求的响应。
Response.statusCode#
当前响应的HTTP状态码。例如200(OK), 404(Not Found)等。
有关HTTP状态码的信息,参见菜鸟教程:HTTP状态码。
Response.statusMessage#
当前响应的HTTP状态信息。例如"OK", "Bad Request", "Forbidden"。
有关HTTP状态码的信息,参见菜鸟教程:HTTP状态码。
例子:
var res = http.get("www.baidu.com");
if(res.statusCode >= 200 && res.statusCode < 300){
toast("页面获取成功!");
}else if(res.statusCode == 404){
toast("页面没找到哦...");
}else{
toast("错误: " + res.statusCode + " " + res.statusMessage);
}
Response.headers#
当前响应的HTTP头部信息。该对象的键是响应头名称,值是各自的响应头值。 所有响应头名称都是小写的(吗)。
有关HTTP头部信息,参见菜鸟教程:HTTP响应头信息。
例子:
console.show();
var res = http.get("www.qq.com");
console.log("HTTP Headers:")
for(var headerName in res.headers){
console.log("%s: %s", headerName, res.headers[headerName]);
}
Response.body#
当前响应的内容。他有以下属性和函数:
- bytes() <Array> 以字节数组形式返回响应内容
- string() <string> 以字符串形式返回响应内容
- json() <Object> 把响应内容作为JSON格式的数据并调用JSON.parse,返回解析后的对象
- contentType <string> 当前响应的内容类型
Response.request#
- <Request> 当前响应所对应的请求。参见[Request][]。
Response.url#
- <number> 当前响应所对应的请求URL。
Response.method#
- <string> 当前响应所对应的HTTP请求的方法。例如"GET", "POST", "PUT"等。
Dialogs#
dialogs 模块允许用户通过对话框与脚本进行交互。
dialogs.rawInput(title[, default])#
显示一个包含输入框的对话框。如果指定了 default ,那么对话框显示时输入框的内容就为该值。
该函数也可通过 rawInput(title[, default]) 、 prompt(title[, default]) 或者 dialogs.prompt(title[, default]) 来调用。调用时脚本将阻塞直至对话框被关闭。如果用户输入内容并点击确定,函数将返回输入的内容;否则返回 null 。
dialogs.input(title[, default])#
等效于 eval(dialogs.rawInput(title, default))
dialogs.prompt(title[, default])#
见 dialogs.rawInput
dialogs.alert(title[, content])#
显示一个只包含“确定”按钮的提示对话框。
该函数也可通过 alert(title[, content]) 来调用。调用时脚本将阻塞直至对话框被关闭。该函数无返回值。
dialogs.confirm(title[, content])#
显示一个包含“确定”和“取消”按钮的提示对话框。
该函数也可通过 confirm(title[, content]) 来调用。调用时脚本将阻塞直至对话框被关闭。如果用户点击“确定”则返回 true ,否则返回 false 。
dialogs.select(title, items)#
显示一个带有选项列表的对话框。
该函数也可通过 dialogs.select(title, ...items) 来调用。
例如: dialogs.select("标题", ["A", "B", "C"]) 可以用 dialogs.select("标题", "A", "B", "C") 替代。
调用时脚本将阻塞直至对话框被关闭。如果用户点击了对话框中的某个选项,该函数会返回该选项的位置(选中第一个选项返回0,第二个选项返回1,以此类推),否则返回-1。
dialogs.singleChoice(title, items[, index])#
显示一个带有单选框选项列表的对话框。
调用时脚本将阻塞直至对话框被关闭。如果用户选中了对话框中的某个选项并点击“确定”,该函数会返回该选项的位置(选中第一个选项返回0,第二个选项返回1,以此类推),否则返回-1。
dialogs.multiChoice(title, items[, indexes])#
显示一个带有多选框选项列表的对话框。
调用时脚本将阻塞直至对话框被关闭。如果用户点击“确定”按钮,该函数会返回所有已选选项的位置组成的数组,否则返回空数组。
Engines#
engines模块包含了一些与脚本引擎有关的函数,包括运行其他脚本,关闭脚本等。
engines.execScript(name, script[, config])#
在新线程中运行脚本script。返回一个ScriptExectuion对象。
engines.execScriptFile(path[, config])#
path<string> 要运行的脚本路径。config\
在新线程中运行脚本文件path。返回一个ScriptExecution对象。
engines.execAutoFile(path[, config])#
path<string> 要运行的录制文件路径。config\
在新线程中运行录制文件path。返回一个ScriptExecution对象。
engines.stopAll()#
停止所有正在运行的脚本。包括当前脚本自身。
engines.stopAllAndToast()#
停止所有正在运行的脚本并显示停止的脚本数量。包括当前脚本自身。
engines.myEngine()#
返回当前脚本的脚本引擎对象(ScriptEngine)
ScriptExecution#
执行脚本时返回的对象,可以通过他获取执行的引擎、配置、源码等。
ScriptExecution.getEngine()#
返回执行该脚本的脚本引擎对象(ScriptEngine)
ScriptExecution.getConfig()#
返回该脚本的运行配置(ScriptConfig)
ScriptExecution.getSource()#
返回该脚本的源码对象(ScriptSource)
ScriptEngine#
ScriptEngine.forceStop()#
停止脚本引擎的执行。
ScriptEngine.getTag(tagName)#
tagName<string> 名称
返回对应于tagName的附加在该脚本引擎上的额外信息。tagName包括:
source该脚本引擎当前正在执行的源码(ScriptSource)execute_path该脚本引擎当前执行的路径
停止脚本引擎的执行。
ScriptConfig#
脚本执行时的配置。
delay#
延迟执行的毫秒数
interval#
循环运行时两次运行之间的时间间隔
loopTimes#
循环运行次数
getPath()#
返回一个字符串数组表示脚本运行时模块寻找的路径。
ScriptSource#
脚本执行时的源码对象。可以是字符串源码、文件源码等。
如果该源码是文件脚本,则可以通过toString()得到该文件的路径。
getName()#
返回该源码的名称。
getEngineName()#
返回执行该源码的脚本引擎的名称。
module (模块)#
Auto.js 有一个简单的模块加载系统。 在 Auto.js 中,文件和模块是一一对应的(每个文件被视为一个独立的模块)。
例子,假设有一个名为 foo.js 的文件:
const circle = require('./circle.js');
console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`);
在第一行中,foo.js 加载了同一目录下的 circle.js 模块。
circle.js 文件的内容为:
const { PI } = Math;
exports.area = (r) => PI * r ** 2;
exports.circumference = (r) => 2 * PI * r;
circle.js 模块导出了 area() 和 circumference() 两个函数。 通过在特殊的 exports 对象上指定额外的属性,函数和对象可以被添加到模块的根部。
模块内的本地变量是私有的,因为模块被 Node.js 包装在一个函数中(详见模块包装器)。 在这个例子中,变量 PI 是 circle.js 私有的。
module.exports属性可以被赋予一个新的值(例如函数或对象)。
如下,bar.js 会用到 square 模块,square 导出一个构造函数:
const square = require('./square.js');
const mySquare = square(2);
console.log(`正方形的面积是 ${mySquare.area()}`);
square 模块定义在 square.js 中:
// 赋值给 `exports` 不会修改模块,必须使用 `module.exports`
module.exports = function(width) {
return {
area: () => width ** 2
};
};