1. MIUI上跑Auto.js先把这几项系统设置改掉先说个结论Auto.js跑自动化真正劝退新手的不是JavaScript语法而是系统环境。同样是解锁手机、自动阅读这套流程在原生Android上可能十分钟就通了到了MIUI上会遇到无障碍服务被系统回收、省电策略把脚本进程冻结、锁屏唤醒失败等一系列问题。这篇我按自己的实操顺序把解锁到自动阅读的完整流程拆开讲同时把MIUI上踩过的坑一个个标出来。如果你是第一次接触Auto.js建议先把系统设置这一步做完再写代码。否则后面每次脚本跑一半断掉你都会怀疑是代码写错了实际上问题往往出在MIUI的后台管理策略上。1.1 Auto.js版本怎么选以及安装时被MIUI安全中心拦住怎么办Auto.js的版本选择我建议直接用4.x系列。4.1.1 Alpha2是网上流传比较广的免费版API稳定社区里的示例脚本也基本都是这套写法。Pro版功能更多比如加密、云控但个人自用完全没必要。二次开发的版本我不太推荐因为不知道作者在源码里塞了什么APK签名也未必能对上官方包。安装阶段就会遇到第一个MIUI拦路虎安全中心。MIUI开启纯净模式后非应用商店来源的APK会被直接拦截装Auto.js这类需要无障碍权限的工具尤其明显。解决办法去设置-应用设置-纯净模式里关掉或者在安装确认弹窗里选择“仍然安装”。如果你用的是MIUI开发版安全中心扫描第三方APK时会提示“高风险”这里选“了解风险”继续即可。装完后先别急着写脚本打开Auto.js把无障碍服务开起来。路径是设置-更多设置-无障碍-已下载的服务-Auto.js-开启。如果没有这一步后续所有控件查找、模拟点击都跑不起来这是整个自动化链路的地基。1.2 无障碍服务和“深度睡眠”权限是命门MIUI最让人头疼的一点就是用着用着无障碍服务自己就关了。我排查过几次发现原因通常是省电策略把Auto.js的进程冻结了服务被系统回收。这个问题的规避要在应用详情里做三件事省电策略改成“无限制”不要用默认的“智能限制”否则锁屏一段时间后进程可能被冻结自启动设为允许不然开机后Auto.js不自动起服务通知权限保持开启Auto.js的通知通道别关系统会把“没有通知的应用”当作低活跃应用优先清理。另外还有一个权限特别容易被忽略“后台弹出界面”。在设置-应用-Auto.js-其他权限里找到“后台弹出界面”并允许。如果没有这个权限脚本里调用app.launch()打开阅读App时会偶发失败表现是日志正常但App没有跳出来。补齐这些权限后再看Auto.js主界面服务状态那一栏应该是绿色的。如果是灰色说明无障碍服务没起来点击去系统设置里重新打开。1.3 后台限制省电策略、自启动、最近任务加锁就算上面三项权限都给了MIUI还是会想尽办法清理后台进程。我的做法是再加一道保险把Auto.js从最近任务列表里锁住。操作步骤切换到最近任务界面把Auto.js的卡片往下拉直到左上角出现一把锁。这样即使你手动点“一键清理”Auto.js也不会被杀掉。这一步在MIUI 12、13、14上通用HyperOS上也一样。还有开发者选项里的一个设置要检查设置-更多设置-开发者选项-后台进程限制确保它是“标准限制”。如果之前手动调成“不得超过1个进程”或“不得超过2个进程”Auto.js的后台服务很容易被挤掉。这个限制对MIUI整个多任务调度都有影响不只是Auto.js。1.4 不同MIUI版本的设置路径差异系统设置在不同MIUI版本里的入口名称会变特别是从MIUI切换到HyperOS之后。这里列一下我试过的对应关系设置项MIUI 12/13MIUI 14 开发版HyperOS省电策略应用详情-省电策略应用信息-省电策略应用详情-省电策略自启动应用详情-自启动应用信息-自启动应用详情-其他权限-自启动后台弹出界面应用详情-其他权限应用信息-其他权限应用详情-其他权限纯净模式设置-应用设置-纯净模式设置-应用设置-纯净模式设置-安全-纯净模式如果找不到直接在设置页顶部搜索框输入“省电策略”或“自启动”能跳到对应模块。把环境配置好整个流程才算真正开始。2. “解锁手机”这一步为什么是整套流程最容易翻车的地方很多人以为自动阅读最难的是翻页逻辑实际跑起来才发现光是“从锁屏到桌面”这一步就能让你怀疑人生。Auto.js本身提供了device.wakeUp()这类接口但MIUI锁屏界面的行为跟原生Android有差异稍不留神就卡在解锁环节。2.1 先界定范围这里的解锁不是解BL锁也不是解账户锁网上搜“解锁手机”容易搜出一堆BL解锁教程、小米账户锁移除工具那些跟我们要做的完全是两回事。在自动化脚本语境里“解锁手机”指的是把设备从锁屏状态唤醒执行上滑/输密码/画图案操作最终进入桌面。整个过程靠Auto.js的无障碍服务注入手势事件完成不涉及Bootloader也不涉及账户体系。想明白这一点很重要否则方向就跑偏了。我见过有人为了做阅读辅助先去解了BL锁还刷了Magisk模块配置成本直接拉满。如果只是个人自用完全不需要走到那一步。2.2 亮屏唤醒的正确写法与Android限制屏幕唤醒的标准写法很简单if (!device.isScreenOn()) { device.wakeUp(); sleep(800); }device.isScreenOn()判断当前是否亮屏device.wakeUp()尝试唤醒。在MIUI上这个接口依赖Auto.js的辅助功能服务大部分机型是能正常用的。但有个细节如果系统开启了“息屏显示”AOD亮屏后可能还会停留在AOD界面而不是锁屏界面需要在唤醒后再加一次上滑操作或者多等一轮。实测中发现某些MIUI版本对wakeUp()的响应不够快需要把后面的sleep()加大到1000毫秒以上否则紧接着的滑动操作会落在屏幕还没完全亮起来的时间点直接丢失手势事件。这里的经验是宁可多等不要急躁。2.3 不同锁屏方式下的解锁策略滑动、图案、密码锁屏方式决定了解锁逻辑我把常见情况分开说明。滑动锁屏无密码最省事。let w device.width(); let h device.height(); swipe(w / 2, h * 0.8, w / 2, h * 0.3, 300);图案锁用gesture()绘制轨迹。关键是要算准九宫格坐标。不同手机的图案锁区域大小不一样我习惯用一个gap变量来校准function unlockByPattern() { let w device.width(); let h device.height(); let gap Math.round(w * 0.1); // 根据自己屏幕微调 let cx w / 2; let topY Math.round(h * 0.35); // 从左下角开始画一个Z形 gesture(800, [cx - gap, topY gap * 2], [cx, topY gap * 2], [cx gap, topY gap * 2], [cx gap, topY], [cx - gap, topY] ); }gap的校准方法打开开发者选项里的“指针位置”在锁屏界面看着触摸坐标记录图案锁各点的真实坐标再换算出合适的比例。不同机型的图案锁绘制区域高度不同直接用固定像素写死很容易在某些设备上失手。数字密码这里很坑。MIUI的PIN输入键盘并不是标准的EditText控件Auto.js的setText()在锁屏密码框上经常无效。我试过用坐标逐个点击数字键也有设备差异因为数字键盘的位置和间距在不同机型上不一样。后来我放弃了在锁屏界面输密码的方案直接改成滑动锁。这是我的一个建议如果你的目标是做个人自动化脚本锁屏方式尽量选择“滑动锁屏”或“无锁屏”。为了保证安全又不想牺牲自动化的便利可以设置锁屏后一段时间自动锁定但运行自动化脚本的那个时段把锁屏临时关掉。很多人担心安全问题实际上手机在自己手里配合智能锁/蓝牙手环解锁安全性和便利性可以兼顾。2.4 MIUI锁屏界面的“误触陷阱”MIUI的锁屏界面有一些“隐藏雷区”。最典型的是上滑手势起点位置不对容易触发锁屏相机或手电筒。锁屏界面的相机入口在屏幕右下角手电筒在左下角如果你的滑动起点过于靠近两侧屏幕边缘系统会把这次滑动识别为打开相机而不是解锁。正确的做法是滑动起点选在屏幕水平中线的位置起点Y坐标在75%到85%区间终点Y在30%到40%区间。动作干脆一点不要拖泥带水。另一个陷阱是通知栏。MIUI 12以后锁屏界面下拉会展开通知栏如果脚本的滑动轨迹被识别成“下拉”而非“上滑”操作就会直接卡住。规避方式同样是控制起点和终点的坐标范围避免从屏幕顶部开始滑动。还有一个很容易被忽略的点有密码的锁屏和无密码的锁屏上滑后的结果完全不同。无密码时上滑直接进桌面有密码时上滑只是打开密码键盘还需要再执行一步输入操作。所以在写解锁函数时必须知道自己设备的锁屏状态否则脚本会“看起来在动”但永远进不了桌面。3. 自动阅读的核心逻辑拆解从启动App到翻页循环解锁搞定后剩下的就是自动阅读流水线打开阅读App、进入阅读界面、循环翻页、控制阅读时长。这一节我把整个流程拆开讲包含具体的代码思路和MIUI环境下的细节处理。3.1 打开App与进入阅读界面的控件选择启动App用app.launch(packageName)或app.launchApp(应用名)。这里更推荐用包名因为应用名匹配可能会因为本地化名称差别而失败。获取包名最简单的方法设置-应用管理-选择目标App拉到最下面查看“版本”旁边的包名信息或者用adb命令adb shell pm list packages | grep xxx。app.launch(com.example.reader); sleep(2000); // 等待启动动画结束等待时间是第一个坑。MIUI对冷启动速度的影响挺明显同样是2秒在旗舰机上可能已经进了首页在千元机上可能还在启动页。更稳妥的做法是配合控件查找找到阅读首页的某个特征元素再往下走。let homeLoaded text(推荐).findOne(8000); if (!homeLoaded) { // 首页没加载出来可能被弹窗挡住了 closePopup(); }然后进入正文页。不同App的入口不同有的是直接打开第一章有的需要点击“开始阅读”“继续阅读”按钮。这些控件的所属关系需要在Auto.js的布局分析里自己看一遍。3.2 翻页/滚动实现的三种方式对比自动阅读的核心动作是“翻页”但翻页的实现在不同App里差异很大。我把常用的方式做了个对比方式适用场景优点缺点控件点击“下一篇”有明确翻页按钮的小说/文章类App定位准、不易误触控件可能随版本变化手势滑动信息流、上下滑动类App通用性强可能与系统手势冲突scrollDown()滚动长页面、可滚动RecyclerView实现简单WebView/自定义组件可能失效我实际使用时是把三种方式揉在一起写一个nextPage()函数优先走控件点击不行就尝试滚动最后用手势滑动兜底。function nextPage() { let w device.width(); let h device.height(); // 优先找“下一页”按钮 let nextBtn text(下一页).findOne(1000); if (nextBtn) { nextBtn.click(); return true; } // 尝试无障碍滚动 if (scrollDown()) { return true; } // 手势滑动兜底 let sx w / 2 random(-60, 60); let sy h * 0.75 random(-30, 30); let ey h * 0.25 random(-30, 30); swipe(sx, sy, sx, ey, random(700, 1200)); return true; }MIUI上特别要注意全面屏手势的冲突。如果手机开启了全面屏手势屏幕边缘向内侧滑是返回操作所以滑动翻页的起点不要放在屏幕最左或最右边缘保持在50%到70%的水平位置更安全。3.3 循环节流与随机化既是稳定性问题也是风控问题翻页循环本身不复杂复杂的是怎么让它看起来更像真人操作并且不会因为异常弹窗卡死。我的核心思路只有一个随机化。不要用while(true)死循环加上次数上限。例如计划阅读30分钟、每次翻页间隔5秒那么循环次数大概是360次代码里直接指定上限function readLoop(minutes) { let totalCount Math.round(minutes * 60 / 5); for (let i 0; i totalCount; i) { nextPage(); log(已阅读第 (i 1) 页); sleep(random(3000, 7000)); } }随机化的维度包括休眠时间在3秒到7秒之间浮动不固定滑动坐标起点和终点的XY坐标在上下左右各偏移几十像素滑动时长从800毫秒到1500毫秒之间浮动。固定的操作频率和坐标不仅容易被App的风控机制识别还容易在重复区域触发系统的“防误触”机制。3.4 定时任务与耗电控制自动阅读最终要落到“定时执行”上。Auto.js自带定时任务功能侧边栏-定时任务-添加选择脚本和触发时间。但这个功能在MIUI上是不折不扣的重灾区系统会把定时任务的进程给冻结掉导致到点不执行。我的实际做法分两套一是充电场景下不锁屏在家或工位上插着充电器把系统锁屏设为“无锁屏”休眠设为30分钟脚本完成后手动锁屏。这个方案成功率高到95%以上因为彻底绕开了锁屏唤醒和后台冻结的问题。二是必须锁屏运行只能靠环境配合。把省电策略设为无限制、自启动打开、最近任务加锁再通过adb把Auto.js加入系统的设备空闲白名单adb shell dumpsys deviceidle whitelist com.autojs这个命令把Auto.js加入Doze省电白名单降低锁屏后进程被冻结的概率。但它不能保证MIUI自己的省电策略不去干预所以还是会有偶发失败。耗电控制方面屏幕常亮跑一两个小时的电量开销确实不小。我的习惯是边充电边跑同时把亮度调到最低。Auto.js里可以直接调亮度device.setScreenBrightness(1);如果不想一直亮屏也可以间隔一段时间调低亮度但别直接调成0某些机型调成0后会黑屏但触摸事件还能注入看起来很吓人。4. MIUI后台杀进程实录脚本跑一半就消失的完整排查链路接下来要讲的是我踩得最深的一个坑脚本跑着跑着就没了没有报错没有退出日志就好像Auto.js从来没启动过一样。这个问题在MIUI上非常典型我把整个排查链路完整记录下来供你参考。4.1 现象日志停在某个时间点第一次遇到这个情况时我设置的定时任务是凌晨1点跑自动阅读第二天去看Auto.js的console日志发现输出停在凌晨1点32分后面什么都没有。Auto.js主界面显示“服务未连接”点进去一看无障碍服务已经被系统关闭了。一开始我以为是代码有bug试了加try-catch、加日志重定向问题依然存在。后来才意识到这根本不是代码层的错误而是系统在管后台进程。4.2 排查链路从最近任务锁定开始逐项确认如果你也遇到脚本中途消失请按这个顺序排查检查无障碍服务状态设置-更多设置-无障碍看Auto.js是否处于开启状态如果已经自动关闭说明系统回收了服务检查最近任务锁定进入最近任务看Auto.js卡片是否上锁如果没锁一键清理就能把它杀掉检查省电策略应用详情-省电策略确认当前是“无限制”还是被改成了“智能限制”。MIUI有些版本会在电量低时自动把应用改成智能限制检查自启动应用详情-自启动确认允许检查开发者选项的后台进程限制设置为“标准限制”看系统耗电排行设置-省电与电池-更多电池功能-应用智能省电找到Auto.js如果状态是“受限”或“智能限制”改回“无限制”。我把这些问题汇总成一张自查表每次系统更新或者刷机后按表过一遍就完事。检查项期望值常见错误值无障碍服务开启已关闭省电策略无限制智能限制/受限自启动允许禁止最近任务锁定已锁定未锁定后台进程限制标准限制不超过2个进程通知权限允许禁止4.3 锁屏后脚本中断的深层原因即便把所有设置都调对了锁屏后的脚本中断依然可能发生。这背后的原因不只是MIUI省电策略还包括Android本身的Doze机制。Android进入Doze模式后会限制网络访问和CPU唤醒Auto.js的JavaScript引擎在Doze模式下虽然不至于完全停止但网络请求、定时器等都会受到影响。如果阅读App刚好需要网络加载下一页而Auto.js正处于“半冻结”状态整个流程就会卡住看起来像死了一样。MIUI在这一层的处理更激进神隐模式会限制后台应用的定位、网络等能力这种限制连“无限制”省电策略都不一定能完全绕开。我有一条额外的经验运行期间别开省电模式。MIUI的省电模式会开启更激进的后台清理策略跟Auto.js这类工具几乎是天敌。4.4 我在用的务实组合方案折腾了大半个月之后我放弃了“让它自己完全全自动地锁屏解锁运行”的执念改用一个更务实的组合方案运行场景固定在工位或床头手机插着充电器把系统的“自动锁屏时间”调成30分钟锁屏方式保持“滑动锁屏”或“无锁屏”彻底躲开密码键盘这个坑脚本开头调低屏幕亮度运行结束后脚本手动把亮度恢复然后通过device.setScreenBrightness(0)灭屏或者干脆不处理等系统自动锁定。这套方案的代价是需要你“给手机一个固定的姿势”但换来了极高的稳定性。我连续跑了一周没有一次脚本中途消失的情况。如果你非要做到“手机放兜里也能定时自动阅读”那就得考虑root后用更底层的方式保活或者换其他有系统级签名的工具。但这些方案的维护成本和风险都会高不少我个人的建议是先试试上面的务实组合大概率能满足需求。5. 给脚本做个体检异常兜底、日志和边界问题写到这里你已经能把一条完整流程跑通了。但脚本能跑和跑得稳是两回事。我把最后一道工序总结为“给脚本做体检”主要包含异常兜底、日志输出和边界情况处理。5.1 异常兜底启动失败重试、控件找不到的fallback一个好的自动化脚本不能裸奔。我给自己的脚本加了一个统一入口函数function run() { try { checkEnv(); // 检查无障碍/省电设置 wakeAndUnlock(); // 亮屏解锁 launchReader(); // 启动阅读App readLoop(30); // 阅读30分钟 } catch (e) { log(e.toString()); sleep(3000); // 出错了自动重试一次 run(); } }重试逻辑需要谨慎加一个最大重试次数避免死循环function runWithRetry(maxRetry) { for (let i 0; i maxRetry; i) { try { runOnce(); break; } catch (e) { log(第 (i 1) 次运行失败: e.toString()); sleep(5000); } } }控件查找方面最容易出的问题是布局加载慢还没等控件出现就去findOne()结果为空。解决办法是给findOne加上超时时间并且在返回null时走fallback逻辑let btn text(阅读全文).findOne(3000); if (btn) { btn.click(); } else { // 找不到“阅读全文”可能是页面结构变化直接下滑一屏 swipe(w / 2, h * 0.8, w / 2, h * 0.3, 600); }5.2 坐标与控件混合定位脚本写久了会发现纯坐标定位的代码脆弱得不堪一击App上一个布局调整就能让它失效。但纯控件定位也有玩不转的时候有些App的按钮是用自定义View绘制的无障碍树里根本拿不到。我的做法是“控件优先、坐标兜底”。每一个关键操作都先尝试用控件ID或文本定位拿不到再用相对坐标。坐标计算不要写死像素用device.width()和device.height()做比例换算这样换机型时调整成本小很多。拿“点击下一章”举例function clickNextChapter() { let w device.width(); let h device.height(); // 优先按文字定位 let target text(下一章).findOne(2000); if (target) { target.click(); return true; } // 兜底屏幕右下角区域 click(w * 0.85, h * 0.85); return true; }5.3 日志输出与运行监控脚本长时间的自动化运行中日志是你排查问题的唯一线索。我的习惯是把日志同时输出到控制台和文件控制台用console.show()悬浮窗文件用Auto.js的files模块追加写入function log(msg) { let time new Date().toLocaleString(); console.log(time msg); files.append(/sdcard/Auto.js/runtime.log, time msg \n); }日志文件要注意定期清理不然跑几个月能撑大几百MB。我一般在脚本开头先检查日志文件大小超过5MB就清空重建。5.4 容易被忽略的边界阅读时长统计规则、网络切换、低电量最后聊几个实际运行中才会遇到的边界问题。阅读App对“有效阅读”的判定通常有规则。翻页太快会不算时长甚至触发反作弊机制。所以哪怕看着进度条“飞”得很爽也要控制节奏。我个人实测过最稳妥的是每次翻页后休眠4到8秒加上随机的坐标偏移和等待基本能模拟自然阅读的节奏。还有一个是网络切换弹窗。Wi-Fi断掉切到移动网络时很多阅读App会弹出一个“当前网络不可用是否使用移动数据”的提示。这个弹窗会挡住正文区域的控件导致text(下一页)找不到目标。我的兜底方案是定期检查当前是否在线function isNetworkAvailable() { // Auto.js 里简单判断网络 let context context; let cm context.getSystemService(context.CONNECTIVITY_SERVICE); let info cm.getActiveNetworkInfo(); return info ! null info.isConnected(); }低电量也是一个坑。夜间跑脚本电池低于某个阈值后MIUI会自动进入超级省电模式把绝大多数后台进程都冻结掉。我在脚本开头加了个判断电量低于20%直接退出并把日志写清楚。let battery device.getBattery(); if (battery 20) { log(电量过低退出执行: battery %); exit(); }6. 我用了两个月后的真实感受这套方案我在MIUI 14的Redmi K50上跑了两三个月期间经历过MIUI系统更新、App改版、Auto.js服务被系统回收等各种问题。总结下来最大的感受是脚本写得再优雅不如环境配置得对。每当你觉得“这段代码怎么这么不稳定”的时候先去检查一遍无障碍服务、省电策略、自启动这三个基础项一半以上的问题都能解决。还有一个小技巧每次刷机、换手机或者系统大版本更新后不要急着跑完整流程先跑一个最小验证脚本只做“亮屏-解锁-打开App”这三步。确认基础链路正常后再上完整的自动阅读逻辑能省大量排查时间。最后再说一句实在话自动化脚本是工具用得好能省下大量重复劳动比如清理未读、辅助阅读、定时签到之类的。但别拿去搞恶意刷量、薅羊毛之类的灰度操作很多阅读App都有风控机制封号是一方面万一被平台追究起来得不偿失。保持脚本的“个人辅助”定位它才能真正稳定地为你服务。