# 易玩脚本 **Repository Path**: easyscript/EasyCriptsDemo ## Basic Information - **Project Name**: 易玩脚本 - **Description**: 教程同步代码 - **Primary Language**: JavaScript - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 27 - **Forks**: 14 - **Created**: 2020-04-21 - **Last Updated**: 2025-02-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 基于Autojs的免Root安卓脚本开发实战 #### 一、各个脚本平台对比 ##### 1、常见的脚本平台 1.1.按键精灵 优点 :主要是图色功能 缺点:安卓机需要Root权限,ios+安卓,不能全分辨率--Lua 1.2.触动精灵 优点:主要在ios上面比较出色--ios需要越狱 安卓不如按键--Lua 1.3.基于节点开发的平台 1.3.1 Autojs --基于无障碍 适用安卓系统7.0-10 5.0-6.0不完全支持,打包即用,需要无障碍权限 1.3.2 jsdroid--支持5.0-9.0 对root的机型比较友好,缺点:目前功能还不如Autojs丰富 手机没有Root则需要激活--grovvy 1.3.3节点精灵--支持安卓7.0-9.0 基于无障碍及Lua语言,适合开发免root 游戏脚本 ##### 2、技术交流、分享、解答 ```java Author: QQ:486675857 脚本交流群:1009722787 ``` #### 二、教程目录 ![脚本](C:\Users\Administrator\Desktop\脚本.png) #### 三、正式课程 ##### 1.准备工作 ###### 1.1.Git ----代码 ---https://blog.csdn.net/qq_39387475/article/details/84996173 ###### 1.2.码云 --https://gitee.com/ ###### 1.3.脚本开发工具下载 ---https://code.visualstudio.com/ -vscode ###### 1.4.代码地址:https://gitee.com/easyscript/EasyCriptsDemo.git ##### 2、开发环境 VsCode --- 步骤: 打开Vscode carl +shirt +x 安装antojs扩展 Autojs手机端 4.1.0版本 AutojsPro 7.4.1 安装好autojs扩展后 启动服务 ```java 按 Ctrl+Shift+P 或点击"查看"->"命令面板"可调出命令面板,输入 Auto.js 可以看到几个命令: Start Server: 启动插件服务。之后在确保手机和电脑在同一区域网的情况下,在Auto.js的侧拉菜单中使用连接电脑功能连接。 Stop Server: 停止插件服务。 Run 运行当前编辑器的脚本。如果有多个设备连接,则在所有设备运行。 Rerun 停止当前文件对应的脚本并重新运行。如果有多个设备连接,则在所有设备重新运行。 Stop 停止当前文件对应的脚本。如果有多个设备连接,则在所有设备停止。 StopAll 停止所有正在运行的脚本。如果有多个设备连接,则在所有设备运行所有脚本。 Save 保存当前文件到手机的脚本默认目录(文件名会加上前缀remote)。如果有多个设备连接,则在所有设备保存。 RunOnDevice: 弹出设备菜单并在指定设备运行脚本。 SaveToDevice: 弹出设备菜单并在指定设备保存脚本。 New Project(新建项目):选择一个空文件夹(或者在文件管理器中新建一个空文件夹),将会自动创建一个项目 Run Project(运行项目):运行一个项目,需要Auto.js 4.0.4Alpha5以上支持 Save Project(保存项目):保存一个项目,需要Auto.js 4.0.4Alpha5以上支持 以上命令一些有对应的快捷键,参照命令后面的说明即可。 ``` Autojs安装好后 打开无障碍权限 输入ip连接服务器 查看本机ip cmd --> ipconfig IPv4 地址 . . . . . . . . . . . . : 192.168.1.108 ###### #### 正式开发 开发文档----https://hyb1996.github.io/AutoJs-Docs/#/ ##### 一、js基础 ```javascript Autojs三种输出方式: 1.log() ,console.log(),toastLog log(i) console.log(字符串) toastLog(字符串) //相当于 log(字符串) + toast(字符串) /*log(字符串) toast(字符串) toastLog(字符串) ``` ###### 1.1 js变量定义 ```javascript var i=0; //定义一个Number var 字符串=""; //字符串 var 数组=[]; //定义数组 var 对象={}; //定义对象 var flaf=true; //定义一个布尔型的变量 ``` ###### 1.2js常见的字符串函数操作~ ```javascript //字符串的分割 字符串.split("以什么分割") 返回类型为数组 var 数据="123456789---qwe123" var 分割后=数据.split("---"); console.log("账号:"+分割后[0]+"密码:"+分割后[1]) //字符串的截取 字符串.substring(起始下标,终止下标) 返回类型为字符串 var 字符串="hello AutoJs"; log("截取前:"+字符串) var 字符串=字符串.substring(0,7) log("截取后"+字符串) //字符串的包含 字符串.indexOf("包含的字符串") 返回-1||0 -1代表不包含 0代表包含 var 字符串="hello AutoJs"; log(字符串.indexOf("hello"))//输出0 //字符串的替换 replace(str1,str2) 返回值 字符串类型 var 字符串="hello AutoJs"; var 替换后=字符串.replace("hello","你好") console.log(替换后) ``` ###### 1.3 数组及对象 ```javascript 一、数组操作 //1.添加 数组.push("要添加的内容") var 数组 = []; //定义数组 数组.push(1) 数组.push(2) 数组.push("3") log(数组) //数组遍历 数组.forEach(item=>{ log(item) }) //循环输出 for(var i=0;i<数组.length;i++){ log(数组[i]) } //其他的参照博客:https://www.jianshu.com/p/22a4c0b514fa 二、对象操作 var 对象 = {}; //定义对象 var flaf = true; //定义一个布尔型的变 //Js数组操作 1.数组添加 遍历 删除 过滤 排序 var 对象数组=[]; //案例 各种手机信息的集合 for(var i=0;i<10;i++){ var phone={};//定义一个手机 属性有: 品牌 价格 颜色 操作系统 phone.pinpai="小米"+i; phone.price="3000" phone.color="blue"; phone.os="android 1"+i 对象数组.push(phone) } log(对象数组) ``` ###### 1.4常用Js流程控制 ```javascript //流程控制 while for swith if //1.for循环 for (var i = 0; i < 10; i++) { if (i > 5) { console.log(i) break;//跳出循环 } else if (i % 3 == 0) { console.log(i) } } //while var i = 0; while (true) { i = i + 1; if (i > 5) { console.log(i) break;//跳出循环 } } //swith var i = 1; switch (i) { case "0": console.log("0") break; case 1: console.log("1") break; } ``` 1.5常用Js函数定义、传值等 ```javascript //函数的定义与调用 hello() function hello(){ toastLog("你好") } //函数传值的类型 可以为number string array obj //1.传数字 传值函数(1,"2") function 传值函数(a,b){ var b=parseInt(b)//将字符类型的变量转数字 log(a+b) } //传字符 传值函数1("hello","Autojs") function 传值函数1(a,b){ // var b=parseInt(b)//将字符类型的变量转数字 log(a+"--"+b) } //传数组 arrSort([1,2,3]) function arrSort(array){ array.forEach(element => { console.log(element) }); } //传对象 var obj={}; obj.title="传对象"; objTest(obj) function objTest(data){ console.log(data.title) } ``` ##### 二、常用设备函数 ```javascript console.log(device) /* Device{width=720, height=1280, buildId='LMY47I', buildDisplay='LMY47I', product='sm-g531h', board='sm-g531h', brand='samsung', device='aosp', model='sm-g531h', bootloader='unknown', hardware='android_x86', fingerprint='asus/android_x86/x86:5.1.1/LMY47I/8.3.19:user/release-keys', sdkInt=22, incremental='8.3.19', release='5.1.1', baseOS='null', securityPatch='null', serial='00dc3b3c'} */ console.log(device.getIMEI())//返回设备的IMEI. console.log(device.getAndroidId())//返回设备的Android ID。 //一直保持屏幕常亮 device.keepScreenOn() ``` ##### 三、节点操作 ​ UiSelector即选择器,用于通过各种条件选取屏幕上的控件,再对这些控件进行点击、长按等动作。这里需要先简单介绍一下控件和界面的相关知识。 一般软件的界面是由一个个控件构成的,例如图片部分是一个图片控件(ImageView),文字部分是一个文字控件(TextView);同时,通过各种布局来决定各个控件的位置,例如,线性布局(LinearLayout)里面的控件都是按水平或垂直一次叠放的,列表布局(AbsListView)则是以列表的形式显示控件。 控件有各种属性,包括文本(text), 描述(desc), 类名(className), id等等。我们通常用一个控件的属性来找到这个控件,例如,想要点击QQ聊天窗口的"发送"按钮,我们就可以通过他的文本属性为"发送"来找到这个控件并点击他,具体代 ```javascript com.stardust.automator.UiObject@800bdcff; boundsInParent: Rect(0, 0 - 288, 36); boundsInScreen: Rect(360, 1149 - 648, 1185); packageName: org.autojs.autojs; className: android.widget.TextView; text: 用户名:; contentDescription: null; viewId: org.autojs.autojs:id/value; checkable: false; checked: false; focusable: false; focused: false; selected: false; clickable: false; longClickable: false; enabled: true; password: false; scrollable: false; [ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY, ACTION_SET_SELECTION] ``` ###### 1.常用组合查找控件 ```javascript //控件组合查找 className + text +id +desc / //id("button4").findOne() //findOnce var btn=className("Button").text("登录").id("button4").findOne() if(btn){ log(btn) } /*控件三种点击方法 1.直接点击坐标 click(130,700) 2.通过控件属性: 要求 clickable:true 3.通过控件的bounds()取控件的范围 再取中间值 */ var btn=className("Button").text("登录").id("button4").findOne() if(btn){ var point=btn.bounds(); console.log(point) console.log(point.centerX(),point.centerY()) // click(point.centerX(),point.centerY()) 用在控件的clickable属性为false 但是可以点击 } //输入框控件 var et = className("EditText").id("user_edit").findOne(); if(et){ et.setText("486675857") } */ var check=className("checkBox").id("checkBox").findOne() if(check){ console.log(check.checked()) } var check=className("Switch").id("switch1").findOne() if(check){ console.log(check.checked()) } ``` ###### 2.案例模拟账号密码登入 ```javascript 输入用户名() function 输入用户名() { var user = className("EditText").id("user_edit").findOne() if (user) { console.log("开始输入") user.setText("486675857"); sleep(1000) 输入密码() } else { } } function 输入密码() { var pwd = className("EditText").id("pw_edit").findOne() if (pwd) { console.log("开始输入密码") pwd.setText("123456"); sleep(1000) 选中性别() } } function 选中性别() { var check = classNameEndsWith("CheckBox").id("checkBox").findOne() if (check) { console.log("选中性别") check.click() sleep(1000) 记住密码() } } function 记住密码() { var check = className("Switch").id("switch1").findOne() if (check) { console.log(" 记住密码") check.click() sleep(1000) 登录() } } function 登录() { var btn = textContains("登").findOne() if (btn) { console.log(" deng") btn.click() } } ``` ##### 四、图色篇 ```javascript //请求横屏截图 if(!requestScreenCapture()){ toast("请求截图失败"); exit(); } //连续截图10张图片(间隔1秒)并保存到存储卡目录 captureScreen("/sdcard/index.png"); var img= images.read("/sdcard/index.png") var clip = images.clip(img, 100, 100, 400, 400); images.save(clip, "/sdcard/clip.png"); ``` ##### 五、文件操作 ###### 1、文件读取操作 ```javascript //创建一个文件 var path = "/sdcard/1.txt"; log(files.exists(path))//判断文件是否存在 if (!files.exists(path)) { console.log("文件不存在,开始创建") files.create(path); } else { console.log("文件存在") } writeLine(path, "123456582", 2) function readLine(path, line) { if (!files.exists(path)) { console.log(path) return ""; } var file = files.open(path, mode = "r", encoding = "utf-8") var fileList = file.readlines();//获取文件数组 //console.log(fileList) if (fileList.length < line) { log("超出了~") file.close(); return ""; } line = line - 1; file.close(); return fileList[line] } function writeLine(path, text, line) { if (!files.exists(path)) { console.log(path) return ""; } var file = files.open(path, mode = "r", encoding = "utf-8") var newArr = []; var fileList = file.readlines();//获取文件数组 console.log(fileList) file.close; var wfile = files.open(path, mode = "w", encoding = "utf-8") if (fileList.length == 0) { wfile.writeline(text) wfile.close() return; } if (fileList.length >= line) { for (var i = 0; i < fileList.length; i++) { var str = ""; if ((line - 1) == i) { str = text; } else { str = fileList[i] } newArr.push(str) } wfile.writelines(newArr) wfile.close() } else { for (var j = 0; j < fileList.length; j++) { newArr.push(fileList[j]) } newArr.push(text) wfile.writelines(newArr) wfile.close() } } var file = files.open(path, mode = "r", encoding = "utf-8") var fileList = file.readlines();//获取文件数组 console.log(fileList ) file.close()//创建一个文件 var path = "/sdcard/1.txt"; log(files.exists(path))//判断文件是否存在 if (!files.exists(path)) { console.log("文件不存在,开始创建") files.create(path); } else { console.log("文件存在") } writeLine(path, "123456582", 2) function readLine(path, line) { if (!files.exists(path)) { console.log(path) return ""; } var file = files.open(path, mode = "r", encoding = "utf-8") var fileList = file.readlines();//获取文件数组 //console.log(fileList) if (fileList.length < line) { log("超出了~") file.close(); return ""; } line = line - 1; file.close(); return fileList[line] } function writeLine(path, text, line) { if (!files.exists(path)) { console.log(path) return ""; } var file = files.open(path, mode = "r", encoding = "utf-8") var newArr = []; var fileList = file.readlines();//获取文件数组 console.log(fileList) file.close; var wfile = files.open(path, mode = "w", encoding = "utf-8") if (fileList.length == 0) { wfile.writeline(text) wfile.close() return; } if (fileList.length >= line) { for (var i = 0; i < fileList.length; i++) { var str = ""; if ((line - 1) == i) { str = text; } else { str = fileList[i] } newArr.push(str) } wfile.writelines(newArr) wfile.close() } else { for (var j = 0; j < fileList.length; j++) { newArr.push(fileList[j]) } newArr.push(text) wfile.writelines(newArr) wfile.close() } } var file = files.open(path, mode = "r", encoding = "utf-8") var fileList = file.readlines();//获取文件数组 console.log(fileList ) file.close()//按行读取 function readLine(path, line) { if (!files.exists(path)) { console.log(path) return ""; } var file = files.open(path, mode = "r", encoding = "utf-8") var fileList = file.readlines();//获取文件数组 if (fileList.length < line) { log("超出了~") file.close(); return ""; } line = line - 1; file.close(); return fileList[line] } ``` ###### 2、文件写入操作 ```javascript 传入参数path, text, line function writeLine(path, text, line) { if (!files.exists(path)) { console.log(path) return ""; } var file = files.open(path, mode = "r", encoding = "utf-8") var newArr = []; var fileList = file.readlines();//获取文件数组 console.log(fileList) file.close; var wfile = files.open(path, mode = "w", encoding = "utf-8") if (fileList.length == 0) { wfile.writeline(text) wfile.close() return; } if (fileList.length >= line) { for (var i = 0; i < fileList.length; i++) { var str = ""; if ((line - 1) == i) { str = text; } else { str = fileList[i] } newArr.push(str) } wfile.writelines(newArr) wfile.close() } else { for (var j = 0; j < fileList.length; j++) { newArr.push(fileList[j]) } newArr.push(text) wfile.writelines(newArr) wfile.close() } } ``` ###### 3、文件遍历 ```javascript //遍历sd中所有的文件夹 var dirArr = [], fileArr = []; //遍历sd中所有的文件夹 function getDirs(path) { var arr = files.listDir(path); arr.forEach(item => { var dir1 = path + item; if (files.isDir(dir1)) { dirArr.push(dir1 + "/") return getFiles(dir1 + "/") } }); } //遍历sd卡中的所有文件 function getFiles(path) { // files.isFile(path) var arr = files.listDir(path); arr.forEach(item => { var dir1 = path + item; if (files.isFile(dir1)) { fileArr.push(dir1) } if (files.isDir(dir1)) { // dirArr.push(dir1 + "/") return getFiles(dir1 + "/") } }) console.log(fileArr) } ``` ##### 六、ui设计 ###### 1.常用布局 ```javascript "ui"; ui.layout(