赞
踩
手游脚本开发课程--auto.js入门教程:https://www.bilibili.com/video/BV1Pr4y1H7R9
手游辅助教程:https://search.bilibili.com/all?keyword=手游辅助教程
AutomateIt、Automate、按键精灵、AutoJS…等Android自动化工具有什么特点?:https://www.zhihu.com/question/59503646
- Auto.js:是一个开源的自动化程序,因为多用在黑灰产,被某些资本警告,导致该工具无法对某些应用进行操作 ( 例如:微信、支付宝、抖音 等 )。4.1 版本是免费版的最后一个版本,可以在所有 app 上进行操作。 Auto.js 中文文档:https://pro.autojs.org/docs/
- autojs pro:是原作者在 autojs 上提供了一个付费的工具,拥有更强大的功能,但是同样无法操作某些软件。
- AutoX.js:是在 Auto.js4.1 版本基础上 fork而来,可操作所有软件,并拥有大量 autojs pro 的功能。 AutoX.js :http://doc.autoxjs.com/#/
- AutoJs6:https://github.com/SuperMonster003/AutoJs6
- 一触即发:http://www.yicuba.com/index.html
- 点击助手Pro:https://www.ghxi.com/djzs.html
- Hamibot:类似 autojs 的自动化工具,可以通过浏览器远程控制。适用于安卓系统的自动化工具,能全自动操控任意 APP。( 需要注册账号才能进行操作 )。 Hamibot :https://hamibot.com/
Hamibot 连接手机:https://www.i3zh.com/22556.html- 冰狐智能辅助 (类似 Autojs,比 autojs 简单,需要注册账号):https://aznfz.com/
- Ctrl.js 开发文档:https://ctrljs.ikaiwei.com/ctrljsapi/#/
Ctrl.js ( 类似auto.js ):http://www.feiyunjs.com/2266.html- EasyClick 和Auto.js区别:http://www.feiyunjs.com/2456.html
EasyClick 开发文档:http://ecdoc.laoleng.vip/docs/
关键字:类似 autojs 、autojs 综合实战
AutoJs Pro 7.0.4-1 实战教程---史上最全快手、抖音极速版
- :https://blog.csdn.net/zy0412326/article/details/107180887/
- :https://blog.csdn.net/zy0412326/article/details/107190828
示例:
- AutoJs 4.1.0 实战教程---终极福利Apk:https://blog.csdn.net/zy0412326/article/details/105120435
- 自动化篇 | 使用 AutoJS 自动领京豆:https://www.bianchengquan.com/article/589931.html
- 2021 Autojs 全网最全几十种小游戏和自阅合集 (含源码):脚本赚钱:https://blog.csdn.net/qq_29117491/article/details/118634537
- 最新热门脚本Autojs源码分享:https://www.jb51.net/article/212542.htm
资料:
- Auto.js 快速入门实战教:https://github.com/ErazerControl/2019double11
- Auto.js 从入门到精通( 95集 ):https://www.bilibili.com/video/BV1pQ4y1R7Us
- Auto.js(基础、速成、初中、高阶、终极、实战)
:https://www.songma.com/product/view338899.html
【autojs】中级进阶教程:https://www.bilibili.com/video/BV1eg411L7DDauto.js 安卓脚本游戏脚本( 37集 ):https://www.bilibili.com/video/BV1Po4y1Q7bE
- autojs 入门视频( 23集 ):https://www.bilibili.com/video/BV1g5411L7G6
- B站搜索的 autojs :https://search.bilibili.com/all?keyword=autojs
Autojs 从入门到放弃(AcFun 视频)
:https://www.acfun.cn/v/ac17943282
:https://zhuanlan.zhihu.com/p/156660560AutoJS4.1.0实战教程:https://blog.csdn.net/zy0412326/article/details/104767602/
Auto.js 是一个支持无障碍服务的 Android 平台上的 JavaScript IDE。Autojs 主要是基于安卓系统的无障碍服务,实现自动化操控和监控手机信息处理。
根据官方文档定义:Auto.js 是一款无需 root 权限的 JavaScript 自动化软件。如何理解它?
特性:
app: 应用。启动应用,卸载应用,使用应用查看、编辑文件、访问网页,发送应用间广播等。
console: 控制台。记录运行的日志、错误、信息等。
device: 设备。获取设备屏幕宽高、系统版本等信息,控制设备音量、亮度等。
engines: 脚本引擎。用于启动其他脚本。
events: 事件与监听。按键监听,通知监听,触摸监听等。
floaty: 悬浮窗。用于显示自定义的悬浮窗。
files: 文件系统。文件创建、获取信息、读写。
http: HTTP。发送HTTP请求,例如GET, POST等。
images, colors: 图片和图色处理。截图,剪切图片,找图找色,读取保存图片等。
keys: 按键模拟。比如音量键、Home键模拟等。
shell: Shell命令。
threads: 多线程支持。
ui: UI界面。用于显示自定义的UI界面,和用户交互。
除此之外,Auto.js 内置了对 Promise。
AutoX.js 使用 JavaScript 作为脚本语言,目前使用 Rhino 1.7.13 作为脚本引擎,支持 ES5 与部分 ES6 特性。
这里直接使用 VSCode 和 AutoX.js 插件进行开发。安装好 VSCode 和 AutoX.js 插件后,VSCode 打开 命令面板 ( Ctrl + shift + p ),输入 autoxjs 即可看到 插件支持的命令
找到 start server 点击即可启动服务。然后手机上打开悬浮窗并连接电脑。至此环境配置成功
上面插件安装成功后,就可以在vscode上编写并运行,手机就会相应执行脚本
也可以直接在手机的 Auto.js 应用中直接码代码,不过那酸爽谁用谁知道。。。
示例脚本:
// 购物车按钮的id
const carId = id('com.yaya.zone:id/rl_car_layout');
// 控制台与手机弹窗输出 toastLog autox.js 全局函数,请查看官方文档
//控件是否存在
toastLog('控件是否存在:'+carId.exists())
//搜索到唯一元素并点击
carId.findOnce().click()
使用如下代码可以直接跳转到APP内的某个页面
// 这样启动没有广告,有点android开发经验,贼爽
app.startActivity({
action: "android.intent.action.VIEW",
className: "com.yaya.zone.home.HomeActivity",
packageName: "com.yaya.zone",
});
className 与 packageName 查看方法:MT管理器 -> 左上角菜单->Activity记录
使用 autox.js 打包成 app,打包的软件报毒
这个问题是因为打包后的app用了 autojs 作为包名,需要用MT管理器把apk 的xml中的autojs字符串换成任意其他值就可以了。
autojs打包的软件报毒:https://zhuanlan.zhihu.com/p/425140138
示例:申请截图代码
if (!requestScreenCapture()) {
toastLog("请求截图权限 失败");
} else {
toastLog("请求截图权限 成功");
}
执行以上代码后, 正常应该弹出一个框, 让用户选择是否允许截图。但是有的时候, 不会弹出这个界面,这个时候就要去 设置-->应用管理-->AutoJsPro-->权限管理-->后台弹出界面-->允许
悬浮窗权限。
判断是否有悬浮窗权限的代码
floaty.checkPermission();
返回一个布尔值, true就是有权限, false就是没有权限
如果app没有悬浮窗权限,提示用户,然后跳转悬浮窗权限设置界面, 方便用户勾选
跳转悬浮窗权限设置界面代码
app.startActivity({
packageName: "com.android.settings",
className: "com.android.settings.Settings$AppDrawOverlaySettingsActivity",
data: "package:" + context.getPackageName(),
});
后台自启权限,跳转启动管理页面的代码
let intent = new Intent();
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
let pkg = "com.huawei.systemmanager";
let cls = "com.huawei.systemmanager.startupmgr.ui.StartupNormalAppListActivity";
let componentName = new android.content.ComponentName(pkg, cls);
intent.setComponent(componentName);
context.startActivity(intent);
AutoX.js 基于 Auto.js4.1 版本,使用的是 Rhino(第一代API):https://pro.autojs.org/docs/zh/v8/
由于官方4.1.1文档 经常会打不开,所以这里重新copy了一份
auto.js文档:https://easydoc.net/doc/84873548/LvEnNZ0d/VuWWeK5N
Node.js(第二代API)对比 Rhino(第一代API)的优势是:
Node.js(第二代API)对比 Rhino(第一代API)的劣势是:
如果你是:
那么建议你使用Rhino引擎和第一代API,上手较快。你无需特别配置,代码默认都以该引擎执行。
如果你是:
那么建议你使用Node.js引擎和第二代API,对Rhino引擎和第一代API了解即可。
引擎的选择并非绝对,可以一边使用Rhino引擎一边使用Node.js引擎,或者在学习一段时间后再看另一个引擎/API。
为了编写脚本简单,淘宝预先打开喵铺主页
- auto.waitFor()
- let app_name = "微信";
- launchApp(app_name);
- sleep(10000);
- // 根据 "文字信息" 寻找按钮, 并点击
- let btn_1 = text("用短信验证码登录").findOnce();
- if (btn_1) {
- toast("定位到 微信");
- btn_1.click();
- sleep(1000);
- text("获取验证码").findOnce().click();
- }
- else {
- toast("未检测到验证码按钮");
- //中止脚本
- exit();
- }

详解:
- //开始执行任务
- execTask();
- function execTask() {
- while(true) {
- var target = text("去进店").findOnce() || text("去浏览").findOnce();
- if (target == null) {
- toast("任务完成");
- break;
- }
- target.click();
- sleep(3000);
- //浏览网页20s
- viewWeb(20);
- back();
- sleep(1000);
- }
- }

viewWeb 是一会要写的函数,目的是模拟浏览网页20s的操作,虽说淘宝要求15s就行了,但是可能部分手机加载耗时比较多,所以多写了5s。当判断任务栏有"去进店"、"去浏览"的组件时,点击跳转至浏览广告,浏览完毕后,返回至任务栏页面,循环执行该操作直到找不到"去进店"、"去浏览"的组件结束(任务完成后按钮文字会变成"已完成")。
- function viewWeb(time) {
- gesture(1000, [300, 600], [300, 300]);
- var cnt = 1;
- while(true) {
- var finish = desc("任务完成").exists() || textStartsWith("已获得").exists();
- if (finish || cnt > time) {
- break;
- }
- sleep(1000);
- cnt += 1;
- }
- //模拟返回键,返回到任务栏页面
- back();
- }
函数的参数为当前页面的最大停留时间(防止意外而一直停留该页面)。
浏览广告完成的标志:
gesture 是指屏幕滑动操作,这是本文唯一涉及屏幕像素的语句。gesture(duration, [x1, y1], [x2, y2]表示用duration的时间,从(x1,y1)点滑到(x2,y2)点,代码中表示如图用1s从黄点滑向红点,故是上滑操作浏览广告。
本次淘宝的活动最开始滑动一次,之后等着时间够了即可,故代码中没有再额外滑动。在浏览广告完毕后back()模拟返回键返回值任务栏页面。
这段代码定位组件用到了desc(),之所于用desc是因为该控件的desc信息是"任务完成",还记得如何查看控件信息吧?总之,想定位控件,就先去查它的控件信息。
代码终于写完了,将脚本发到手机中,在Auto.js应用点击右下角的+号,选择导入,在文件目中寻找对应的脚本加载。
将淘宝打开至喵铺主页,返回 Auto.js,点击运行即可执行脚本,在日志处可以查看脚本运行日志,我还没提到日志?在脚本中你可以使用 log() 函数记录日志,这等同于 print,常用于调试或记录日志信息。
编写完代码,将代码打包成一个独立的 apk。
示例代码:
-
- function print_lian_xi_ren(){
- /* 找控件 */
- log(text("通讯录").findOne().parent().parent());
- /* 当找到的控件 的 "点击属性" 是 false 时,可能是这个控件本身嵌套在另一个控件中,
- 外层控件是内层控件的父控件,查看父控件是否可点击,
- 如果父控件 的 "点击属性" 仍然是 false 时,继续查找父控件,
- 直到找到 "点击属性" 是 true 时,即可 点击
- */
- var btn_txl = text("通讯录").findOne().parent().parent();
- btn_txl.click();
- sleep(1000)
-
- /* 打印联系人 */
- var lxr = id("com.tencent.mm:id/ft6").find()
- lxr.forEach(element => {
- people_name = element.text();
- log(people_name);
- click(people_name);
- sleep(1000);
- back();
- sleep(1000);
- });
- }
-
- function cha_kan_peng_you_quan(){
- /* 控件坐标 */
- var bounds = text("发现").findOne().bounds()
- var x = bounds.centerX();
- var y = bounds.centerY();
- click(x,y);
- sleep(3000)
-
- var btn_pyq = text("朋友圈").findOne();
- x = btn_pyq.bounds().centerX();
- y = btn_pyq.bounds().centerY();
- click(x,y);
- sleep(1000);
-
- var android_widget = className("android.widget.ListView")
- while(true){
- /* 滚动浏览朋友圈 */
- android_widget.scrollDown();
- sleep(1000);
- }
- }
-
- auto.waitFor();
- // home();
- var app_name = "微信"
- app.launchApp(app_name);
- sleep(1000)
-
- print_lian_xi_ren();
- cha_kan_peng_you_quan()

搜索和定位对象之前,需要先了解下安卓的布局、组件、以及组件属性
Android 常用布局
Tables | Are |
---|---|
线性布局 | linearLayout |
表格布局 | TableLayout |
相对布局 | RelativelLayout |
帧布局 | FrameLayout |
网格布局 | GridLayout |
绝对布局 | AbsoluteLayout |
Android 常用组件
文本框、编辑框、按钮、单选按钮、复选框、状态开关按钮、拖动条 等等
Android 组件的属性
属性值 | 值类型 | 例子 |
---|---|---|
index | int | 0 |
instance | int | 5 |
class | String | android.widget.TextView |
package | String | com.jian.test |
Content desc | String | string |
checkable | boolean | false |
clecked | boolean | false |
clickable | boolean | true |
enabled | boolean | false |
focusable | boolean | false |
focused | boolean | false |
Scrollable | boolean | false |
Long-clickable | boolean | false |
password | boolean | false |
selected | boolean | false |
bounds | Rect | [366,999][708,1197] |
确定要控件(唯一性),以下三个方法基本可满足日常:
UiSelector 选择器:https://easydoc.net/doc/84873548/LvEnNZ0d/6SafZjmz
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属性,那么这个属性很可能是唯一的,除了以下几种情况:
尽管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()
,通过链式调用来组合条件。
通常用这些技巧便可以解决大部分问题,即使解决不了问题,也可以通过布局分析的"生成代码"功能来尝试生成一些选择器代码。接下来的问题便是对选取的控件进行操作,包括:
click()
点击。点击一个控件,前提是这个控件的clickable属性为truelongClick()
长按。长按一个控件,前提是这个控件的longClickable属性为truesetText()
设置文本,用于编辑框控件设置文本。scrollForward()
, scrollBackward()
滑动。滑动一个控件(列表等), 前提是这个控件的scrollable属性为trueexits()
判断控件是否存在waitFor()
等待控件出现这些操作包含了绝大部分控件操作。根据这些我们可以很容易写出一个"刷屏"脚本(代码仅为示例,请不要在别人的群里测试,否则容易被踢):
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()
为向前滑,包括下滑和右滑。
选择器的入门教程暂且要这里,更多信息可以查看 UiSelector 和 选择器进阶。
定位选择器:findOnce() 表示找到第一个满足条件的控件,找不到返回null;另外还有findOne(),findOne(time)等方法,具体的可以看文档,这里有一个坑,findOne() 如果没找到匹配的组件会一直找,直至所描述的控件出现为止,故该函数不会返回null,找不到可能会卡在这里,所以谨慎使用。
click():当定位的元素的clickable属性为true时,才可以点击,如果你查看某控件的clickable为false,那说明此控件不能点!!你可能是想点击它的子/父控件。
通过 "文本属性" 定位对象
返回值 | API | 说明 |
---|---|---|
UiSelector | text(String text) | 文本 |
UiSelector | textContains(String text) | 文本包含 |
UiSelector | textMatches(String regex) | 文本正则 |
UiSelector | textStartsWith(String text) | 文本起始匹配 |
通过 "描述属性" 定位对象
返回值 | API | 说明 |
---|---|---|
UiSelector | description(String desc) | 描述 |
UiSelector | descriptionContains(String desc) | 描述包含 |
UiSelector | descriptionMatches(String regex) | 描述正则 |
UiSelector | descriptionStartsWith(String desc) | 描述开始字符匹配 |
通过 "类名、包名" 定位对象
返回值 | API | 说明 |
---|---|---|
UiSelector | className(String className) | 类名 |
UiSelector | classNameMatches(String regex) | 正则类名 |
包名属性定位
回值 | API | 说明 |
---|---|---|
UiSelector | packageName(String name) | 包名 |
UiSelector | packageNameMatches(String regex) | 包名正则 |
通过 "特殊属性与节点" 定位对象
返回值 | API | 说明 |
---|---|---|
UiSelector | checked(booleean val) | 选择属性 |
UiSelector | clickable(boolean val) | 可点击属性 |
UiSelector | enabled(boolean val) | enabled属性 |
UiSelector | focusable(boolean val) | 焦点属性 |
UiSelector | focused(boolean val) | 当前焦点属性 |
UiSelector | longClickable(boolean val) | 长按属性 |
UiSelector | scrollable(boolean val) | 滚动属性 |
UiSelector | selected(boolean val) | 背景选择属性 |
通过 "id" 定位对象 ( 推荐使用 )
每一个组件都会有编号,也就是ID
From ( 事件与监听 - Events详细讲解 QQ消息、微信消息 通知服务 ):https://www.bilibili.com/video/BV14g4y1q7mr
/*等待界面出现的三种方法*/
//方法 1
while(true){
if(text("控件上的文字").exists()){
break;
}
}//方法2
text("控件上的文字").waitFor();//方法3
text("控件上的文字").findOne();
示例:
// 启用按键监听
evenntsevents.observeKey();// 监听音量 上键 按下
events.onKeyDown("volume_up", function(event){
toast("音量上键被按下");
});events.onKeyDown('volume_down', function(){
toast("菜单键被按下");
exit();
});
events.on("key", function(key_code, event){
if(key_code == keys.volume_up && envets.getAction() == event.ACTION_UP){
toast("菜单键被按下");
}
});
events.observeNotification();
events.onNotification(function(notification){
printNotification(notification)
});function printNotification(notification){
log("应用包名:" + notification.getPackageName());
log("通知文本:" + notification.getText());
log("通知优先级:" + notification.priority);
log("通知目录:" + notification.category);
log("通知时间:" + new Date(notification.when));
log("通知数:" + notification.number);
log("通知摘要:" + notification.tickerText);
}
事件与监听 - Events
用其他按键强行停止脚本
events.onKeyDown("home", function (event) {//按home停止
toast("程序结束")
console.hide()
threads.shutDownAll()
})
events.onKeyDown("volume_down", function (event) {//按音量下停止
toast("程序结束")
console.hide()
threads.shutDownAll()
})
Auto.js 从入门到精通:https://www.bilibili.com/video/av715713093/
images 模块提供了一些手机设备中常见的图片处理函数,包括截图、读写图片、图片剪裁、旋转、二值化、找色找图等。
:https://hyb1996.github.io/AutoJs-Docs/#/images?id=images
该模块分为两个部分:
示例代码:
- 颜色转换方法
- /*
- // 返回颜色值得字符串,格式为 "#AARRGGBB"
- colors.toString(colorNum)
- colors.red(Num | str) // 返回颜色 color 的 R 通道的值,范围 0~255
- colors.green(Num | str) // 返回颜色 color 的 G 通道的值,范围 0~255
- colors.blue(Num | str) // 返回颜色 color 的 B 通道的值,范围 0~255
- colors.alpha(Num | str) // 返回颜色 color 的 alpha (透明度) 的值,范围 0~255
- // 返回 redNum, greenNum, blueNum 构成的颜色值,alpha为255,即不透明
- colors.rgb(redNum, greenNum, blueNum)
- colors.argb(alpha, redNum, greenNum, blueNum)
- // 返回颜色的整数值
- colors.parseColor(colorStr)
- */
- 判断颜色是否相似或者相等
-
- if(!requestScreenCapture()) {
- toast("请求截图权限失败");
- exit();
- }
- toast("请求截图权限成功")
- sleep(5000);
-
- function getImg(x1, y1, x2, y2, imgSavePath){
- var screen = images.captureScreen();
- var img = images.clip(screen, x1, y1, x2-x1, y2-y1);
- img.saveTo(imgSavePath);
- img.recycle();
- }
-
- // 保存路径的目录必须存在
- getImg(0,0,100,500,"/sdcard/Download/test.png");
-
- // 使用线程
- // thread.start(function(){
- // // 在新线程中执行的代码
- // while(true){
- // if(text("立即执行").findOne()){
- // text("立即执行").findOne().click();
- // }else{
- // sleep(3000);
- // }
- // }
- // })

images 中的 requestScreenCapture、captureScreen 这两个函数是可以当做全局函数来使用的。注意:captureScreen 返回的图片,不需要进行回收。。。
示例代码:
- // images.findColor(image, color, options)
- // findColor(image, color, options) // 全局函数
-
- // 循环找色示例
- images.requestScreenCapture();
- // 循环找色,找打红色 (#ff0000) 时停止,并返回坐标
- while(true){
- var img = images.captureScreen();
- var point = images.findColor(img, "#ff0000");
- if(point){
- toast("找到 '红色',坐标为(" + point.x + "," + point.y + ")")
- break
- }
- sleep(500);
- }
-
- //区域找色示例
- //读取本地图片 /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("没有找到");
- }

区域找色 --- 简单方法
- findColorInRegion(img, color, x, y, width, height, threshold);
- // 或者
- images.findColorInRegion(img, color, x, y, width, height, threshold);
示例:Auto.js
images.findColorEquals(img, color[, x, y, width, height])
img
{Image} 图片color
{number} | {string} 要寻找的颜色x
{number} 找色区域的左上角横坐标y
{number} 找色区域的左上角纵坐标width
{number} 找色区域的宽度height
{number} 找色区域的高度在图片img指定区域中找到颜色和color完全相等的某个点,并返回该点的左边;如果没有找到,则返回null
。
找色区域通过x
, y
, width
, height
指定,如果不指定找色区域,则在整张图片中寻找。
该函数也可以作为全局函数使用。
示例: (通过找QQ红点的颜色来判断是否有未读消息)
示例代码:
- requestScreenCapture();
- launchApp("QQ");
- sleep(1200);
- var p = findColorEquals(captureScreen(), "#f64d30");
- if(p){
- toast("有未读消息");
- }else{
- toast("没有未读消息");
- }
images.findMultiColors(img, firstColor, colors[, options])
img
{Image} 要找色的图片firstColor
{number} | {string} 第一个点的颜色colors
{Array} 表示剩下的点相对于第一个点的位置和颜色的数组,数组的每个元素为[x, y, color]options
{Object} 选项,包括:
region
{Array} 找色区域。是一个两个或四个元素的数组。(region[0], region[1])表示找色区域的左上角;region[2]*region[3]表示找色区域的宽高。如果只有region只有两个元素,则找色区域为(region[0], region[1])到屏幕右下角。如果不指定region选项,则找色区域为整张图片。threshold
{number} 找色时颜色相似度的临界值,范围为0~255(越小越相似,0为颜色相等,255为任何颜色都能匹配)。默认为4。threshold和浮点数相似度(0.0~1.0)的换算为 similarity = (255 - threshold) / 255.多点找色,类似于按键精灵的多点找色,其过程如下:
null
例如,对于代码images.findMultiColors(img, "#123456", [[10, 20, "#ffffff"], [30, 40, "#000000"]])
,假设图片在(100, 200)的位置的颜色为#123456, 这时如果(110, 220)的位置的颜色为#fffff且(130, 240)的位置的颜色为#000000,则函数返回点(100, 200)。
如果要指定找色区域,则在options中指定,例如:
- var p = images.findMultiColors(img, "#123456", [[10, 20, "#ffffff"], [30, 40, "#000000"]], {
- region: [0, 960, 1080, 960]
- });
示例代码:
- /*
- images.findMultiColors(img, firstColor, [color_1, color_2, ...], options);
- 示例:
- images.findMultiColors(img, "#123456", [[10,20,"#ffffff"], [30,40,"#000000"]], options);
- images.findMultiColors(img, "#123456", [[5,10,"#ffffff"], [15,20,"#123456"]], {threshold:0});
- */
-
- if(!images.requestScreenCapture()){
- toast("请求截图权限失败");
- exit();
- }
-
- text("微信").waitFor();
- sleep(1500);
-
- var img = images.captureScreen();
- sleep(500);
- // 获取图片中某一点的颜色
- var color_1 = img.pixel(100, 200);
- log(colors.toString(color_1));
-
- var color_point = images.findMultiColors(
- img, "#0d0e22",
- [[10,20, "#ffffff"], [30,40, "#000000"] ]
- );
-
- // 打印找到的颜色点的坐标
- log(color_point);

images.detectsColor(image, color, x, y[, threshold = 16, algorithm = "diff"]):Auto.js
image
{Image} 图片color
{number} | {string} 要检测的颜色x
{number} 要检测的位置横坐标y
{number} 要检测的位置纵坐标threshold
{number} 颜色相似度临界值,默认为16。取值范围为0~255。algorithm
{string} 颜色匹配算法,包括:
"rgb": rgb欧拉距离相似度。与给定颜色color的rgb欧拉距离小于等于threshold时匹配。
"rgb+": 加权rgb欧拉距离匹配(LAB Delta E)。
返回图片image在位置(x, y)处是否匹配到颜色color。用于检测图片中某个位置是否是特定颜色。
一个判断微博客户端的某个微博是否被点赞过的例子:
- if(!requestScreenCapture()){
- toast("请求截图权限失败");
- exit();
- }
-
- text("排行榜").waitFor();
- sleep(1000);
-
- //找到点赞控件。
- // find() 不会阻塞操作,
- // findOne() 会阻塞操作,直到找到一个在继续后续流程
- var like = id("com.tencent.mm:id/bo_").find();
- //获取该控件中点坐标
- var x = like.bounds().centerX();
- var y = like.bounds().centerY();
- //截图
- var img = captureScreen();
- //判断在该坐标的颜色是否为橙红色
- if(images.detectsColor(img, "#fed9a8", x, y)){
- //是的话则已经是点赞过的了,不做任何动作
- }else{
- //否则点击点赞按钮
- like.click();
- }

打开应用的详情页(设置页)。如果找不到该应用,返回false; 否则返回true。该函数也可以作为全局函数使用。
options
{Object} 发送邮件的参数。包括:
email
{string} | {Array} 收件人的邮件地址。如果有多个收件人,则用字符串数组表示cc
{string} | {Array} 抄送收件人的邮件地址。如果有多个抄送收件人,则用字符串数组表示bcc
{string} | {Array} 密送收件人的邮件地址。如果有多个密送收件人,则用字符串数组表示subject
{string} 邮件主题(标题)text
{string} 邮件正文attachment
{string} 附件的路径。根据选项 options 调用邮箱应用发送邮件。这些选项均是可选的。如果没有安装邮箱应用,则抛出ActivityNotException
。
- //发送邮件给10086@qq.com和10001@qq.com。
- app.sendEmail({
- email: ["10086@qq.com", "10001@qq.com"],
- subject: "这是一个邮件标题",
- text: "这是邮件正文"
- });
示例代码:
- // app.openAppSetting(app.getPackageName("微信"));
- // sleep(1000)
- // app.openAppSetting(app.getPackageName("QQ"));
- // sleep(1000)
-
- app.startActivity("console");
- sleep(1000)
- app.startActivity("settings")
-
- //app.openUrl("https://www.baidu.com")
- //sleep(1000)
floaty 模块提供了悬浮窗的相关函数,可以在屏幕上显示自定义悬浮窗,控制悬浮窗大小、位置等。悬浮窗在脚本停止运行时会自动关闭,因此,要保持悬浮窗不被关闭,可以用一个空的setInterval 来实现,例如:setInterval(()=>{}, 1000);
创建和关闭悬浮窗( ui 界面设置 ):Auto.js从入门到精通_哔哩哔哩_bilibili
layout
{xml} | {View} 悬浮窗界面的XML或者View指定悬浮窗的布局,创建并显示一个悬浮窗,返回一个FloatyWindow
对象。
该悬浮窗自带关闭、调整大小、调整位置按键,可根据需要调用setAdjustEnabled()
函数来显示或隐藏。其中layout参数可以是xml布局或者一个View,更多信息参见ui模块的说明。例子:
- var w = floaty.window(
- <frame gravity="center">
- <text id="text">悬浮文字</text>
- </frame>
- );
- setTimeout(()=>{
- w.close();
- }, 2000);
这段代码运行后将会在屏幕上显示悬浮文字,并在两秒后消失。另外,因为脚本运行的线程不是UI线程,而所有对控件的修改操作需要在UI线程执行,此时需要用ui.run
,例如:
- ui.run(function(){
- w.text.setText("文本");
- });
完整示例:
- // frame 是一个重叠布局,如果再添加 一个 button,则两个会重叠到一块
- // 更多布局,可以参看:https://hyb1996.github.io/AutoJs-Docs/#/ui?id=垂直布局-vertical
- var w = floaty.window(
- <frame gravity="center">
- <text id="text">悬浮文字</text>
- </frame>
- );
- // setTimeout(()=>{
- // w.close();
- // }, 2000);
-
- setInterval(()=>{}, 1000); // 保持悬浮窗不被关闭
-
- ui.run(function(){
- w.text.setText("文本");
- });

简单使用 "垂直布局" 示例:
更多布局,可以参看:https://hyb1996.github.io/AutoJs-Docs/#/ui?id=垂直布局-vertical
- var xuanfu_window = floaty.window(
- <vertical h="100dp">
- <text id="text_1">悬浮文字 text_1</text>
- <text id="text_2">悬浮文字 text_2</text>
- <text layout_weight="1" text="控件1" bg="#ff0000"/>
- <text layout_weight="1" text="控件2" bg="#00ff00"/>
- <text layout_weight="1" text="控件3" bg="#0000ff"/>
- <button>按钮_1</button>
- </vertical>
- );
-
- setInterval(()=>{}, 1000);
-
- ui.run(function(){
- xuanfu_window.text_1.setText("text_1_text_1_text_1");
- xuanfu_window.text_2.setText("text_2_text_2_text_2");
- });

layout
{xml} | {View} 悬浮窗界面的XML或者View指定悬浮窗的布局,创建并显示一个原始悬浮窗,返回一个FloatyRawWindow
对象。与floaty.window()
函数不同的是,该悬浮窗不会增加任何额外设施(例如调整大小、位置按钮),您可以根据自己需要编写任何布局。而且,该悬浮窗支持完全全屏,可以覆盖状态栏,因此可以做护眼模式之类的应用。 示例代码:
- var xfc_1 = floaty.rawWindow(
- <frame gravity="center">
- <text id="text">悬浮文字</text>
- </frame>
- );
- var xfc_2 = floaty.rawWindow(
- <frame gravity="center">
- <text id="text">悬浮文字</text>
- </frame>
- );
- setInterval(()=>{}, 1000);
- xfc_2.setPosition(500, 500);
-
悬浮窗对象,可通过 FloatyWindow.{id}
获取悬浮窗界面上的元素。例如, 悬浮窗 window 上一个控件的 id 为 aaa, 那么 window.aaa
即可获取到该控件,类似于 ui。
下面的 window 都是指 FloatyWindow 对象,而不是 FloatyRawWindow
enabled
{boolean} 是否启用悬浮窗调整(大小、位置)。如果 enabled 为 true,则在悬浮窗左上角、右上角显示可供位置、大小调整的标示,就像控制台一样; 如果 enabled 为 false,则隐藏上述标示。- var xfc_1 = floaty.window(
- <frame gravity="center">
- <text id="text">悬浮文字</text>
- </frame>
- );
-
- xfc_1.setAdjustEnabled(true);
-
- // xfc_1.setSize(-1, -1); // -1 表示按最大值计算,占满整个屏幕
- xfc_1.setSize(500, 500);
-
- setInterval(()=>{}, 1000);
设置悬浮窗位置。
返回悬浮窗位置的X坐标。
返回悬浮窗位置的Y坐标。
设置悬浮窗宽高。
返回悬浮窗宽度。
返回悬浮窗高度。
关闭悬浮窗。如果悬浮窗已经是关闭状态,则此函数将不执行任何操作。
使悬浮窗被关闭时自动结束脚本运行。
原始悬浮窗对象,可通过window.{id}
获取悬浮窗界面上的元素。例如, 悬浮窗window上一个控件的id为aaa, 那么window.aaa
即可获取到该控件,类似于ui。
touchable
{Boolean} 是否可触摸设置悬浮窗是否可触摸,如果为true, 则悬浮窗将接收到触摸、点击等事件并且无法继续传递到悬浮窗下面;如果为false, 悬浮窗上的触摸、点击等事件将被直接传递到悬浮窗下面。处于安全考虑,被悬浮窗接收的触摸事情无法再继续传递到下层。
可以用此特性来制作护眼模式脚本,示例代码:
- var w = floaty.rawWindow(
- <frame gravity="center" bg="#44ffcc00"/>
- );
-
- w.setSize(-1, -1); // -1 表示按最大值计算,占满整个屏幕
- w.setTouchable(false);
-
- setTimeout(()=>{
- w.close();
- }, 4000);
name
{string} 要运行的脚本名称。这个名称和文件名称无关,只是在任务管理中显示的名称。script
{string} 要运行的脚本内容。config
{Object} 运行配置项
delay
{number} 延迟执行的毫秒数,默认为0loopTimes
{number} 循环运行次数,默认为1。0为无限循环。interval
{number} 循环运行时两次运行之间的时间间隔,默认为0path
{Array} | {string} 指定脚本运行的目录。这些路径会用于require时寻找模块文件。在新的脚本环境中运行脚本script。返回一个ScriptExectuion对象。
所谓新的脚本环境,指定是,脚本中的变量和原脚本的变量是不共享的,并且,脚本会在新的线程中运行。
最简单的例子如下:engines.execScript("hello world", "toast('hello world')");
如果要循环运行,则:
- //每隔3秒运行一次脚本,循环10次
- engines.execScript("hello world", "toast('hello world')", {
- loopTimes: 10,
- interval: 3000
- });
用字符串来编写脚本非常不方便,可以结合 Function.toString()
的方法来执行特定函数:
- function helloWorld(){
- //注意,这里的变量和脚本主体的变量并不共享
- toast("hello world");
- }
- engines.execScript("hello world", "helloWorld();\n" + helloWorld.toString());
如果要传递变量,则可以把这些封装成一个函数:
- function exec(action, args){
- args = args || {};
- engines.execScript(action.name, action + "(" + JSON.stringify(args) + ");\n" + action.toString());
- }
-
- //要执行的函数,是一个简单的加法
- function add(args){
- toast(args.a + args.b);
- }
-
- //在新的脚本环境中执行 1 + 2
- exec(add, {a: 1, b:2});
综合示例代码:
-
- // toast("脚本引擎示例")
-
- // // 示例 1
- // engines.execScript("js_engines_test", 'toast("示例 1");home();', {
- // delay: 2000,
- // loopTimes: 3,
- // interval: 2000
- // });
-
- // // 示例 2
-
- // function func_test(){
- // toast("示例 2");
- // }
- // engines.execScript("js_test", func_test.toString() + "func_test();")
-
- // 示例 3
-
- function func_aaa(args){
- toast(args.a + args.b);
- }
-
- function func_exec(func, args){
- console.log(func.toString());
- console.log(args.toString());
-
- args = args || {};
- var func_to_string = func.toString();
- var re_string = /function\s*(\w*)/i;
- var result_list = re_string.exec(func_to_string);
- var func_name = result_list[1];
- engines.execScript(func_name, func.toString()+func_name+"("+JSON.stringify(args)+");")
- }
- func_exec(func_aaa, {a:10, b:20});

path
{string} 要运行的脚本路径。config
{Object} 运行配置项
delay
{number} 延迟执行的毫秒数,默认为0loopTimes
{number} 循环运行次数,默认为1。0为无限循环。interval
{number} 循环运行时两次运行之间的时间间隔,默认为0path
{Array} | {string} 指定脚本运行的目录。这些路径会用于require时寻找模块文件。在新的脚本环境中运行脚本文件path。返回一个ScriptExecution对象。
engines.execScriptFile("/sdcard/脚本/1.js");
path
{string} 要运行的录制文件路径。config
{Object} 运行配置项
delay
{number} 延迟执行的毫秒数,默认为0loopTimes
{number} 循环运行次数,默认为1。0为无限循环。interval
{number} 循环运行时两次运行之间的时间间隔,默认为0path
{Array} | {string} 指定脚本运行的目录。这些路径会用于require时寻找模块文件。在新的脚本环境中运行录制文件path。返回一个ScriptExecution对象。
engines.execAutoFile("/sdcard/脚本/1.auto");
停止所有正在运行的脚本。包括当前脚本自身。
停止所有正在运行的脚本并显示停止的脚本数量。包括当前脚本自身。
-
- engines.execScript("test_test", "sleep(10000);");
- sleep(3000);
- engines.stopAllAndToast();
返回当前脚本的脚本引擎对象(ScriptEngine)
[v4.1.0新增] 特别的,该对象可以通过execArgv
来获取他的运行参数,包括外部参数、intent等。例如:
log(engines.myEngine().execArgv);
普通脚本的运行参数通常为空,通过定时任务的广播启动的则可以获取到启动的intent。
返回当前所有正在运行的脚本的脚本引擎ScriptEngine的数组。
log(engines.all());
执行字符串 js 或者 文件 js 时,返回的对象,就是 ScriptExecution 对象
脚本执行对象:Auto.js
执行脚本时返回的对象,可以通过他获取执行的引擎、配置等,也可以停止这个执行。
要停止这个脚本的执行,使用exectuion.getEngine().forceStop()
.
返回执行该脚本的脚本引擎对象(ScriptEngine)
返回该脚本的运行配置(ScriptConfig)
脚本执行的过程中,会返回一个 js 引擎,即 js 的执行环境,就是 脚本引擎对象
脚本引擎对象。
停止脚本引擎的执行。
返回脚本执行的路径。对于一个脚本文件而言为这个脚本所在的文件夹;对于其他脚本,例如字符串脚本,则为null
或者执行时的设置值。
返回当前脚本引擎正在执行的脚本对象。
log(engines.myEngine().getSource());
示例代码:
- var script_execution_obj = engines.execScriptFile("/sdcard/脚本/demo.js");
-
- sleep(1000);
-
- var script_engine = script_execution_obj.getEngine()
- log("脚本引擎对象 ---> " + script_engine);
-
- var script_config = script_execution_obj.getConfig()
- log("脚本运行配置 ---> " + script_config);
-
- log("执行路径 ---> " + script_engine.cwd());
- log("脚本源码 ---> " + script_engine.getSource());
- script_engine.forceStop()
eventName
{string} 事件名称...args
{any} 事件参数向该脚本引擎发送一个事件,该事件可以在该脚本引擎对应的脚本的events模块监听到并在脚本主线程执行事件处理。
例如脚本receiver.js的内容如下:
- //监听say事件
- events.on("say", function(words){
- toastLog(words);
- });
- //保持脚本运行
- setInterval(()=>{}, 1000);
同一目录另一脚本可以启动他并发送该事件:
- //运行脚本
- var e = engines.execScriptFile("./receiver.js");
- //等待脚本启动
- sleep(2000);
- //向该脚本发送事件
- e.getEngine().emit("say", "你好");
脚本执行时的配置。
延迟执行的毫秒数
循环运行时两次运行之间的时间间隔
循环运行次数
返回一个字符串数组表示脚本运行时模块寻找的路径。
From:https://www.bilibili.com/video/BV1pQ4y1R7Us?p=61
Auto.js教程(第十四期)-界面UI教程(全网最全最详细):https://www.bilibili.com/video/BV1cy4y117iY
界面设计类似 HTML
ui 模块提供了编写用户界面的支持。带有 ui 的脚本的的最前面必须使用 "ui";
指定 ui 模式,否则脚本将不会以 ui 模式运行。正确示范:
- "ui";
-
- //脚本的其他代码
字符串 "ui" 的前面可以有注释、空行和空格[v4.1.0新增],但是不能有其他代码。
界面 是由 视图(View) 组成的。View 分成两种:
我们使用 xml 来编写界面,并通过 ui.layout()
函数指定界面的布局 xml。举个例子:
- "ui";
- ui.layout(
- <vertical>
- <button text="第一个按钮"/>
- <button text="第二个按钮"/>
- </vertical>
- );
垂直布局(vertical) 改成 水平布局(horizontal)
- "ui";
- ui.layout(
- <horizontal>
- <button text="第一个按钮"/>
- <button text="第二个按钮"/>
- </horizontal>
- );
一个控件可以指定多个属性(甚至可以不指定任何属性),用空格隔开即可;布局同样也可以指定属性,例如:
- "ui";
- ui.layout(
- <vertical bg="#ff0000">
- <button text="第一个按钮" textSize="20sp"/>
- <button text="第二个按钮"/>
- </vertical>
- );
第三行bg="#ff0000"
指定了垂直布局的背景色(bg)为"#ff0000",这是一个RGB颜色,表示红色(有关RGB的相关知识参见RGB颜色对照表)。第四行的textSize="20sp"
则指定了按钮控件的字体大小(textSize)为"20sp",sp是一个字体单位,暂时不用深入理会。
一个界面便由一些布局和控件组成。
更多 view 的属性:https://hyb1996.github.io/AutoJs-Docs/#/ui?id=视图-view
视频教程:Auto.js从入门到精通_哔哩哔哩_bilibili
如图所示:
全局变量和函数在所有模块中均可使用。 但以下变量的作用域只在模块内,详见 module:
一些模块中的函数为了使用方便也可以直接全局使用,这些函数在此不再赘述。例如timers模块的setInterval, setTimeout等函数。
示例代码:
- var _toast = toast;
-
- toast = function(msg){
- _toast(msg);
- sleep(2000);
- }
-
- toast("123");
- toast("456");
- toast("789");
-
- // text("微信").waitFor();
- // sleep(1000);
-
- // 没有出现等待的页面时,则一直等待
- // waitForActivity("com.tencent.mm.plugin.sns.ui.SnsTimeLineUI");
- // toast("已经到达微信界面");
-
- waitForPackage("com.tencent.mm");
- toast("已经到了某个应用");
-
- var 控件集合 = id("com.miui.home:id/icon_icon").findOne();
- var 控件数量 = 控件数量.size();
- var r = random(0, 控件数量-1);
- var 控件坐标 = 控件集合.get(r).bounds();
- click(控件坐标.centerX(), 控件坐标.centerY())

控制台出现的悬浮窗,进行模拟点击等操作是无法进行穿透操作后面的内容的。。。
控制台模块提供了一个和 Web 浏览器中相似的用于调试的控制台。用于输出一些调试信息、中间结果等。 console 模块中的一些函数也可以直接作为全局函数使用,例如 log, print 等。
清空控制台。
data
{any}...args
{any}打印到控制台,并带上换行符。 可以传入多个参数,第一个参数作为主要信息,其他参数作为类似于 printf(3) 中的代替值(参数都会传给 util.format())。
- const count = 5;
- console.log('count: %d', count);
- // 打印: count: 5 到 stdout
- console.log('count:', count);
- // 打印: count: 5 到 stdout
详见 util.format()。该函数也可以作为全局函数使用。
相当于log(text)
。
[v4.1.0新增]
data
{any}...args
{any}与 console.log 类似,同时会打印出调用这个函数所在的调用栈信息(即当前运行的文件、行数等信息)。
- console.trace('Show me');
- // 打印: (堆栈跟踪会根据被调用的跟踪的位置而变化)
- // Show me
- // at <test>:7
data
{any}...args
{any}与 console.log 类似,但输出结果以灰色字体显示。输出优先级低于log,用于输出观察性质的信息。
data
{any}...args
{any}与console.log类似,但输出结果以绿色字体显示。输出优先级高于log, 用于输出重要信息。
data
{any}...args
{any}与console.log类似,但输出结果以蓝色字体显示。输出优先级高于info, 用于输出警告信息。
data
{any}...args
{any}与console.log类似,但输出结果以红色字体显示。输出优先级高于warn, 用于输出错误信息。
断言。如果value为false则输出错误信息message并停止脚本运行。
- var a = 1 + 1;
- console.assert(a == 2, "加法出错啦");
[v4.1.0新增]
label
{String} 计时器标签,可省略启动一个定时器,用以计算一个操作的持续时间。 定时器由一个唯一的 label
标识。 当调用 console.timeEnd()
时,可以使用相同的 label
来停止定时器,并以毫秒为单位将持续时间输出到控制台。 重复启动同一个标签的定时器会覆盖之前启动同一标签的定时器。
[v4.1.0新增]
label
{String} 计时器标签停止之前通过调用 console.time()
启动的定时器,并打印结果到控制台。 调用 console.timeEnd()
后定时器会被删除。如果不存在标签指定的定时器则会打印 NaNms
。
- console.time('求和');
- var sum = 0;
- for(let i = 0; i < 100000; i++){
- sum += i;
- }
- console.timeEnd('求和');
- // 打印 求和: xxx ms
data
{any}...args
{any}与console.log一样输出信息,并在控制台显示输入框等待输入。按控制台的确认按钮后会将输入的字符串用eval计算后返回。
部分机型可能会有控制台不显示输入框的情况,属于bug。
例如:
- var n = console.input("请输入一个数字:");
- //输入123之后:
- toast(n + 1);
- //显示124
data
{any}...args
{any}与console.log一样输出信息,并在控制台显示输入框等待输入。按控制台的确认按钮后会将输入的字符串直接返回。
部分机型可能会有控制台不显示输入框的情况,属于bug。
例如:
- var n = console.rawInput("请输入一个数字:");
- //输入123之后:
- toast(n + 1);
- //显示1231
w
{number} 宽度h
{number} 高度设置控制台的大小,单位像素。
- console.show();
- sleep(2000);
- console.setSize(device.width/2, device.height/2)
x
{number} 横坐标y
{number} 纵坐标设置控制台的位置,单位像素。
- console.show();
- console.setPosition(100, 100);
[v4.1.0新增]
config
{Object} 日志配置,可选的项有:
file
{string} 日志文件路径,将会把日志写入该文件中maxFileSize
{number} 最大文件大小,单位字节,默认为512 * 1024 (512KB)rootLevel
{string} 写入的日志级别,默认为"ALL"(所有日志),可以为"OFF"(关闭), "DEBUG", "INFO", "WARN", "ERROR", "FATAL"等。maxBackupSize
{number} 日志备份文件最大数量,默认为5filePattern
{string} 日志写入格式,参见PatternLayout设置日志保存的路径和配置。例如把日志保存到"/sdcard/1.txt":
- console.setGlobalLogConfig({
- "file": "/sdcard/1.txt"
- });
注意该函数会影响所有脚本的日志记录。
:https://pro.autojs.org/docs/#/zh-cn/coordinatesBasedAutomation?id=安卓70以上的触摸和手势模拟
x
{number} 要点击的坐标的x值y
{number} 要点击的坐标的y值模拟点击坐标(x, y),并返回是否点击成功。只有在点击执行完成后脚本才继续执行。
一般而言,只有点击过程 ( 大约 150ms ) 中被其他事件中断 ( 例如 用户自行点击 ) 才会点击失败。
使用该函数模拟连续点击时,可能有点击速度过慢的问题,这时可以用 press() 函数代替
x
{number} 要长按的坐标的x值y
{number} 要长按的坐标的y值模拟长按坐标(x, y), 并返回是否成功。只有在长按执行完成(大约600毫秒)时脚本才会继续执行。一般而言,只有长按过程中被其他事件中断(例如用户自行点击)才会长按失败。
x
{number} 要按住的坐标的x值y
{number} 要按住的坐标的y值duration
{number} 按住时长,单位毫秒模拟按住坐标(x, y), 并返回是否成功。只有按住操作执行完成时脚本才会继续执行。
如果按住时间过短,那么会被系统认为是点击;如果时长超过500毫秒,则认为是长按。
一般而言,只有按住过程中被其他事件中断才会操作失败。
一个连点器的例子如下:
- //循环100次
- for(var i = 0; i < 100; i++){
- //点击位置(500, 1000), 每次用时1毫秒
- press(500, 1000, 1);
- }
x1
{number} 滑动的起始坐标的x值y1
{number} 滑动的起始坐标的y值x2
{number} 滑动的结束坐标的x值y2
{number} 滑动的结束坐标的y值duration
{number} 滑动时长,单位毫秒模拟从坐标(x1, y1)滑动到坐标(x2, y2),并返回是否成功。只有滑动操作执行完成时脚本才会继续执行。一般而言,只有滑动过程中被其他事件中断才会滑动失败。
duration
{number} 手势的时长模拟手势操作。例如gesture(1000, [0, 0], [500, 500], [500, 1000])
为模拟一个从(0, 0)到(500, 500)到(500, 100)的手势操作,时长为2秒。
同时模拟多个手势。每个手势的参数为[delay, duration, 坐标], delay为延迟多久(毫秒)才执行该手势;duration为手势执行时长;坐标为手势经过的点的坐标。其中delay参数可以省略,默认为0。
例如手指捏合:
- gestures(
- [0, 500, [100, 500], [100, 1000]],
- [0, 500, [300, 500], [300, 1000]],
- [0, 500, [500, 500], [500, 1000]]
- );
RootAutomator 是一个使用 root 权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。一个脚本中最好只存在一个RootAutomator,并且保证脚本结束退出他。可以在exit事件中退出RootAutomator,例如:
- var ra = new RootAutomator();
- events.on('exit', function(){
- ra.exit();
- });
- //执行一些点击操作
- ...
注意:以下命令需要root权限
RootAutomator是一个使用root权限来模拟触摸的对象,用它可以完成触摸与多点触摸,并且这些动作的执行没有延迟。
一个脚本中最好只存在一个RootAutomator,并且保证脚本结束退出他。可以在exit事件中退出RootAutomator,例如:
- var ra = new RootAutomator();
- events.on('exit', function(){
- ra.exit();
- });
- //执行一些点击操作
- ...
注意以下命令需要root权限
x
{number} 横坐标y
{number} 纵坐标id
{number} 多点触摸id,可选,默认为1,可以通过setDefaultId指定。点击位置(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这个参数。 多点触摸通常用于手势或游戏操作,例如模拟双指捏合、双指上滑等。
某些情况下可能存在tap点击无反应的情况,这时可以用RootAutomator.press()
函数代替。
x1
{number} 滑动起点横坐标y1
{number} 滑动起点纵坐标x2
{number} 滑动终点横坐标y2
{number} 滑动终点纵坐标duration
{number} 滑动时长,单位毫秒,默认值为300id
{number} 多点触摸id,可选,默认为1模拟一次从(x1, y1)到(x2, y2)的时间为duration毫秒的滑动。
x
{number} 横坐标y
{number} 纵坐标duration
{number} 按下时长id
{number} 多点触摸id,可选,默认为1模拟按下位置(x, y),时长为duration毫秒。
x
{number} 横坐标y
{number} 纵坐标duration
{number} 按下时长id
{number} 多点触摸id,可选,默认为1模拟长按位置(x, y)。
以上为简单模拟触摸操作的函数。如果要模拟一些复杂的手势,需要更底层的函数。
x
{number} 横坐标y
{number} 纵坐标id
{number} 多点触摸id,可选,默认为1模拟手指按下位置(x, y)。
x
{number} 横坐标y
{number} 纵坐标id
{number} 多点触摸id,可选,默认为1模拟移动手指到位置(x, y)。
id
{number} 多点触摸id,可选,默认为1模拟手指弹起。
下面的函数在后续版本很可能有改动!请勿过分依赖。推荐使用 RootAutomator
代替本章节的触摸函数。
以下函数均需要root权限,可以实现任意位置的点击、滑动等。
例如:
- 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);
- }
点击位置(x, y), 您可以通过"开发者选项"开启指针位置来确定点击坐标。
滑动。从(x1, y1)位置滑动到(x2, y2)位置。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。