ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

auto.js实战指南:从环境搭建到稳定运行Android自动化脚本

auto.js实战指南:从环境搭建到稳定运行Android自动化脚本 “基于auto.js脚本2”——这个标题看着朴实但懂的人一眼就知道这是要聊 Android 自动化里最趁手的一类工具。做开发、做测试、或者平时被手机上各种重复操作烦到的人多半都动过“把这些点来点去的事交给机器做”的念头。auto.js 就是干这个的它基于 Android 的无障碍服务用 JavaScript 写脚本能模拟点击、滑动、长按、输入文本还能读取屏幕上的界面元素实现“让手机自己操作手机”。这篇文章我不打算写成文档翻译而是围绕我实际用 auto.js 踩坑、调优、做自动化任务的过程把从环境搭建到实战脚本、再到问题排查的完整链路捋一遍。无论你是刚听说 auto.js想拿它解决工作里的报表、打卡、群发这类琐事还是已经写过几段脚本但总觉得不够稳这篇文章应该都能给你一些能直接照着用的东西。1. auto.js 到底是什么先搞清楚原理再动手1.1 它和普通“脚本”的本质区别热词列表里能看到 shell 脚本、Python 脚本、PowerShell 脚本一类的东西那些大多是跑在电脑系统里的命令行程序。auto.js 不一样它跑在 Android 系统里工作对象是“屏幕上看得见的界面”。它背后的核心是 Android 的无障碍服务AccessibilityService。这个服务本来是给视力障碍人士辅助操作手机用的系统允许它读取当前界面的节点信息、模拟手势。auto.js 把这套能力封装成了 JavaScript API于是你可以这样做事先通过文本、ID、描述这些属性找到某个按钮再对它执行点击整个过程就是脚本在代替你的手指。很多初学者不理解“无障碍”和“自动化”的关系总觉得要靠 root 权限或者什么底层协议。实际上 auto.js 走的是系统公开接口不需要 root这是它最大的优势之一。当然它也带来限制无障碍服务能拿到的信息有时候不完整比如某些 App 的界面是 Canvas 自绘的系统看到的就是一块画布没有具体节点这种情况下面专门讲。1.2 auto.js 能解决什么问题有什么不能做我这些年用 auto.js 做过的事情大概可以分三类你可以对照看自己属于哪种场景高频重复操作比如每天到公司打开钉钉/企业微信打卡比如每天填写固定的日报模板比如把手机里的文件按规则批量重命名。定时自动化配合 auto.js 的定时任务功能让脚本在指定时间自动执行比如早上九点自动打开某个应用签到。测试辅助做 App 测试的同学可以用它做冒烟测试的快速回归不用每次手动点几十步流程。但有几点必须提前说清楚。第一auto.js 不是万能的如果某个界面使用自定义绘制、WebView 内嵌复杂页面节点信息可能读不全。第二无障碍服务在某些定制 ROM 上会被系统“省电优化”杀掉这是日常维护里最头疼的问题。第三不要拿它去做破坏公平性的东西比如抢购、外挂、自动刷排名一方面道德上讲不过去另一方面这类操作很容易被后台风控识别账号受限是常有的事。2. 环境准备从装好应用到跑通第一个脚本2.1 手机端安装与权限配置auto.js 的安装包虽然流传版本比较多但使用逻辑基本一致。安装完成后第一件事不是写代码而是把权限配好。进入系统设置找到“无障碍”或“辅助功能”在服务列表里找到 Auto.js打开开关。这里要注意有些 ROM 把无障碍入口藏在“更多设置”或者“已下载的服务”里找不到就让我行搜索“无障碍”。同时建议开启自动脚本需要用到的高悬浮窗权限不然脚本运行时的悬浮控制台显示不出来调试会很不方便。权限配好之后先做一个最简单的验证直接在 App 自带的编辑页里写一行console.log(hello auto.js)点击运行看控制台是否输出。这一步是为了确认无障碍服务真正生效了而不是等后面脚本跑不动才怀疑环境问题。我见过不少新手脚本点了“运行”之后没有任何反应查了很久发现其实是服务开关没打开。2.2 PC 端开发环境为什么推荐 VS Code 插件在手机上敲代码确实难受所以团队开发基本都会用电脑。推荐的组合是 VS Code 加 Auto.js-VSCode 插件手机和电脑连同一个局域网电脑端写好代码直接推送到手机运行还能看日志。配置流程不复杂电脑装 VS Code扩展市场搜 Auto.js 装好手机和电脑连同一个 Wi-Fi手机端打开 Auto.js 的“连接电脑”服务界面抄下显示的 IP 和端口在 VS Code 里按 CtrlShiftP输入Auto.js相关命令填上手机 IP 和端口连接成功后在编辑器里右键就能“运行”当前脚本。这个环境搭建环节值得花时间弄好因为后面调试脚本的效率高很多。很多从手机直接“保存-运行”的人会反复改一行代码就要在手机上操作半天其实完全可以交给 VS Code 统一管理。补充一句新版本有些同学会自己编译如果只是用现成功能直接装打包好的版本就行没必要上来就折腾源码。3. 核心 API 与实操用代码把“点屏幕”这件事说清楚3.1 选择器是怎么工作的定位元素的正确姿势auto.js 最核心的概念是 UiSelector也就是“选择器”。它的作用是从当前屏幕的界面节点树里找到你想操作的那个元素。最常用的匹配方式有这几种text(打卡)按文本内容精确匹配。textContains(打卡)包含“打卡”的文本。desc(按钮描述)按内容描述匹配很多图片按钮没有文本但会有 desc。id(xxx)按资源 ID 匹配这个通常最稳定。className(android.widget.Button)按控件类型匹配。我个人的使用经验是优先用 id其次用 desc最后才用 text。原因很简单文本经常变今天“打卡”明天“签到”而且同一屏可能有多个相同文本ID 是开发在布局里写死的只要 App 不大版本重构基本稳定。选择器拿到的是一组候选节点怎么从候选里挑出真正要的那个可以用findOnce()拿第一个或者用find()拿到数组后自己再加条件过滤。这里有个常见误操作新手喜欢直接text(确定).click()当屏幕上有多个“确定”时会出问题。更稳的写法是var confirmBtn text(确定).findOnce(); if (confirmBtn) { confirm(); // 点击 } else { log(没找到确定按钮); }3.2 点击、滑动、输入三个最常用的动作点击看起来简单但实现方式有讲究。直接用click(x, y)是“坐标点击”属于物理层操作不用关心屏幕上有啥用text(确定).click()是“节点点击”会先找到按钮再点它的中心点。两者各有利弊节点点击更智能界面如果滚动了位置也能点到坐标点击在节点信息拿不到的时候是兜底方案。滑动的 API 是swipe(x1, y1, x2, y2, duration)五个参数分别是起点、终点坐标和滑动耗时。注意它用的是屏幕坐标不是节点坐标。如果想滑动某个控件可以先拿到节点的 bounds()再计算中心点这样写出来的脚本对不同屏幕尺寸的适配性更好。输入的 API 有两类setText(index, text)和input(text)。setText 是对当前聚焦的输入框直接设置文本速度很快但部分输入法下会不触发某些监听input 是模拟键盘逐个字符输入更接近真人操作但速度慢一些。我建议优先 setText如果遇到 App 对输入做了特殊校验比如金额输入框不能直接设置过长数字再换 input 试试。来看一个完整的小例子这个场景很常见打开某个需要登录的应用自动填入账号密码并点击登录按钮。// 等待“账号输入框”出现最多等10秒 var accountEdit className(android.widget.EditText).findOnce(); if (accountEdit) { accountEdit.click(); setText(0, my_account); } // 切到密码输入框一般EditText会多出几个 var editList className(android.widget.EditText).find(); if (editList.length 1) { editList[1].click(); setText(1, my_password); } // 点击登录 text(登录).click();这段代码里没有写死坐标所以换不同分辨率的手机理论上也能跑。这就是“基于节点操作”相比“坐标脚本”的最大优势。3.3 不要硬点等待与轮询的思维新手最常见的脚本问题是界面还没加载完就急着去点结果找不到元素直接报错。解决办法是“等待条件满足再操作”。auto.js 里简单粗暴的做法是sleep(2000)但固定延时不可控网络稍微慢一点就白等了。更合理的是轮询写个 while 循环不停检查目标是否存在超时后自动退出。function waitFor(selector, timeout) { var t timeout || 5000; var start new Date().getTime(); while (new Date().getTime() - start t) { var target selector.findOnce(); if (target) return target; sleep(500); } return null; } var btn waitFor(text(立即打卡), 10000); if (btn) { btn.click(); } else { log(10秒内没等到打卡按钮退出); }这段代码的核心价值是把“等”和“操作”分离了。往后所有脚本里涉及界面跳转、网络请求后的操作都应该走这种等元素再点击的模式而不是无脑 sleep。4. 实战案例拆解自动打卡与批量处理这样写才稳4.1 案例一每天早上自动打开应用打卡需求很简单打开 App点击底部“工作台”进入考勤页面点“打卡”按钮最后截图确认。难点在于每一步的定位。我第一次写的时候直接照抄别人文章的text(打卡).click()结果跑了三天后失效了。后来发现App 更新之后按钮的文本由“打卡”变成了“立即打卡”而且页面上有两个类似的入口。正确做法是先手动 dump 当前界面的节点信息确认目标按钮的独特属性再写选择器。完整脚本可以长这样// 1. 拉起App launch(com.example.kaoqin); // 2. 等待工作台Tab出现并点击 var tabWork waitFor(text(工作台), 10000); if (tabWork) tabWork.click(); // 3. 等待考勤入口出现 var attendance waitFor(desc(考勤打卡), 10000); if (attendance) attendance.click(); // 4. 在考勤页内等待按钮可以点击 var punchBtn waitFor(text(立即打卡), 10000); if (punchBtn) { punchBtn.click(); log(打卡操作完成); } else { log(没有找到打卡按钮可能不在考勤时间或已经打过卡); }这里我特意把每个等待都做了超时处理目的是脚本失败时能知道具体卡在哪一步。实际运行中如果某一天页面弹了个广告第一个等待可能一直不满足10秒后自动退出日志会提示第一步就失败了。这种定位问题的速度比脚本直接挂掉强非常多。4.2 案例二批量处理通知或重复弹窗另一个高频场景是处理弹窗。很多工具类应用每天第一次打开都会弹“今日推荐”“隐私协议”“更新提示”这些弹窗关掉之后界面才能正常操作。我写过一个小函数用它统一处理“关闭按钮”function closePopup() { var closeBtns [text(关闭), desc(关闭), id(close_btn), text(知道了), text(以后再说)]; closeBtns.forEach(function (s) { try { var btn s.findOnce(); if (btn) { btn.click(); log(已关闭弹窗: s.toString()); sleep(800); } } catch (e) { // 节点不存在时不用慌继续下一个 } }); }这个函数的思路是把所有可能出现的弹窗关闭文案都试一遍遇到哪个点哪个。不要小看这种“粗鲁”的写法在节点解析不完整的场景下枚举比精确匹配更实际。4.3 稳定性优化日志、异常与线程脚本写多了以后你会发现真正花时间的不是“实现功能”而是“让它稳定跑一个月”。我踩过的几个坑希望你不要再踩。第一个是崩溃问题。节点不存在时直接.click()会抛异常所以所有可能不存在的节点操作都要 try-catch 或者先判空。我不建议每个方法都包一层 try-catch但整体脚本会放在一个大的异常捕获里出错时把错误信息写到文件try { main(); } catch (e) { var msg e.toString() \n e.stack; files.write(/sdcard/auto_error.log, msg); log(脚本异常: msg); }第二个是线程问题。auto.js 支持threads模块创建新线程配合setInterval可以做一些并行任务但新手很容易写出多个线程同时点击导致界面混乱。我建议初期保持单线程思维所有操作线性执行。真要用多线程至少给要操作的界面元素加锁确保同一时间只有一个线程在动屏幕。第三个是日志。跑自动化脚本最怕“跑了但不知道跑没跑对”。我在关键步骤后都会加log()并且把日志同时写入文件。这样第二天对账时能快速看到脚本执行到哪一步是不是某一次弹窗卡住了。5. 常见问题与排查技巧实录5.1 无障碍服务自动失效定制 ROM 的宿命这大概是所有 auto.js 使用者反馈最多的问题。明明脚本昨天还好好的今天一点运行就提示无障碍服务未开启。去设置里一看服务开关确实被关了。原因大多不是 auto.js 自己崩了而是系统省电策略把它“优化”了。解决方案是到系统的“电池优化”里把 Auto.js 设为“不优化”在“自启动管理”里允许它后台运行锁屏清理设置中把它加入“白名单”。不同 ROM 的设置路径差异很大建议直接用系统设置的搜索功能搜“自启动”“电池优化”这些关键词逐个排查。还有一点尽量不要在脚本运行过程中手动重启手机重启后服务重新注册的几秒钟内脚本如果被调起来可能也会出问题。5.2 选择器匹配不准或者根本匹配不到如果你确定节点存在但脚本找不到大概率是下面几种情况。一是界面是 Flutter、Unity 这类自绘引擎渲染的系统 UI 节点信息很少很可能只有一个根节点内部子元素全都不可见。这种场景下别死磕节点改用坐标通过截屏分析、或者直接观察真实设备人工获取关键位置保存成配置。二是节点在屏幕外比如列表底部的内容要先 scrollDown() 滚动后再找。三是 WebView 里的界面用text()直接匹配不一定有效可以尝试className(android.view.View)一级一级往下遍历但不建议在 WebView 里做太复杂的定位成本太高。5.3 脚本运行到一半卡住卡住的本质是某个等待条件永远不满足。排查思路其实很简单在每一步关键操作前打印日志运行一遍看最后一条日志是什么就知道卡在哪个函数里。然后针对那一步单独做超时控制。我习惯把 5.3 节里的waitFor封装成基础函数后面所有脚本都复用它这样就不会出现无限等待。另外如果脚本里用了while(true)注意加退出条件。我见过有同学写“直到成功”的循环结果某天界面状态异常这个循环就变成死循环把手机电量耗到关机。最安全的写法是给循环加最大尝试次数比如 20 次之后仍然失败就主动退出。5.4 排查速查表平时帮人看脚本问题我总结了一张速查表新手遇到问题先照这个排查现象先检查什么可能的解决办法点击无反应无障碍服务是否开启重新开启服务进设置检查自启动和电池策略提示元素找不到目标界面是否已加载完成加等待轮询检查选择器属性和文本大小写部分机型点击偏移是否用了坐标点击改用节点点击或按屏幕宽高比例换算坐标定时任务不执行应用是否被杀或锁屏被清理加白名单关闭省电策略检查定时表达式脚本偶尔崩溃是否存在空指针调用所有 findOnce() 结果判空外层加 try-catch界面无法读取App 是否使用自绘引擎放弃节点方案改用坐标和 OCR 辅助这张表我建议直接截图存到手机里排查问题的时候对照着看比自己瞎猜快得多。6. 关于 auto.js 脚本的一些个人体会如果让我总结一句实操心得那就是auto.js 脚本的重心不在“怎么写代码”而在“怎么描述操作”。很多人一上来就抠语法结果写着写着自己先晕了。我习惯先把要自动化操作的步骤用文字列出来比如“打开App - 等首页加载 - 点击我的 - 点击设置 - 关闭消息推送”每一步都想清楚“界面状态是怎样的、怎么确认这步成功了”然后再翻译成 API 调用。这样出错的概率会低很多而且后面接手的人也能看懂。还有一个小技巧无论脚本多简单都建议把日志落盘并保留最近几天的日志文件。自动化任务最怕的是“它动了但你不知道它动了什么”。有日志第二天就能快速复盘没日志一切都只能靠猜排查效率天差地别。最后再说一点可扩展的方向。如果你已经能把界面操作脚本写得比较稳可以把它跟 HTTP 请求结合比如从远端拉取当天的工作安排根据安排自动执行不同流程或者把 OCR 能力引进来解决那些拿不到节点信息的自绘界面。auto.js 本身的能力边界很清晰但把这些边界以外的能力组合起来你能做的自动化会远远超出“点两下屏幕”的范畴。希望这篇文章对你有点用。如果你也在折腾 auto.js 自动化回去按上面的框架整理一下你已有的脚本把等待和异常处理补上再用日志武装一遍体验会好非常多的。
返回列表