前言
大家好,我是鲫小鱼。是一名不写前端代码的前端工程师,热衷于分享非前端的知识,带领切图仔逃离切图圈子,欢迎关注我,微信公众号:《鲫小鱼不正经》。欢迎点赞、收藏、关注,一键三连!!
第九章:自动处理弹窗与异常
一、理论讲解:弹窗与异常自动化的意义
在移动端自动化脚本开发中,弹窗、广告、异常提示是影响自动化流程稳定性的最大干扰因素。自动检测并处理弹窗、异常,不仅能提升脚本的健壮性,还能实现真正的"无人值守"自动化。
1.1 常见弹窗类型
- 权限请求弹窗(如存储、定位、通知权限)
- 广告弹窗、活动弹窗、更新提示
- 网络异常、登录失效、系统错误弹窗
- 二次确认、验证码、警告弹窗
- App 内自定义弹窗、Dialog、PopupWindow
1.2 弹窗与异常的自动化难点
- 弹窗文本、控件、结构多变,难以唯一定位
- 弹窗出现时机不确定,需实时监控
- 多种弹窗可能叠加、嵌套、遮挡主流程
- 异常弹窗需区分"可忽略"与"需处理"
- 误点风险,需精准识别
1.3 Auto.js 弹窗处理能力
- 支持多线程/异步实时监控弹窗
- 支持多种查找方式(text、desc、id、正则、模糊)
- 支持批量处理、优先级处理、条件判断
- 支持日志记录、异常上报、自动重试
- 支持自定义弹窗规则、黑白名单
二、基础用法与进阶代码示例
2.1 实时监控并自动关闭弹窗
// 子线程实时监控弹窗
threads.start(function(){
let popupTexts = ["关闭", "取消", "我知道了", "忽略", "不再提示", "以后再说", "同意", "允许"];
while(true){
popupTexts.forEach(txt => {
let btn = text(txt).findOne(500);
if(btn){
btn.click();
log("自动关闭弹窗:" + txt);
}
});
sleep(1000);
}
});
2.2 正则与模糊查找弹窗控件
// 正则查找所有"确定/OK/Yes"按钮
textMatches(/(确定|OK|Yes)/).find().forEach(btn => btn.click());
// 模糊查找包含"权限"或"广告"的弹窗
textContains("权限").find().forEach(node => node.click());
textContains("广告").find().forEach(node => node.click());
2.3 多层弹窗与嵌套弹窗处理
// 递归查找并关闭所有弹窗
function closeAllPopups(node) {
if (!node) return;
if (node.clickable() && /关闭|取消|忽略/.test(node.text())) {
node.click();
log("递归关闭弹窗:" + node.text());
}
for (let i = 0; i < node.childCount(); i++) {
closeAllPopups(node.child(i));
}
}
closeAllPopups(className("android.view.ViewGroup").findOne());
2.4 弹窗优先级与条件处理
// 优先关闭高危弹窗,再处理普通弹窗
let highPriority = ["危险", "警告", "异常", "登录失效"];
let normalPriority = ["广告", "活动", "推荐"];
highPriority.forEach(txt => {
let btn = textContains(txt).findOne(500);
if(btn) btn.click();
});
normalPriority.forEach(txt => {
let btn = textContains(txt).findOne(500);
if(btn) btn.click();
});
2.5 弹窗黑白名单与自定义规则
// 只处理白名单内的弹窗
let whitelist = ["关闭", "取消", "同意"];
whitelist.forEach(txt => {
let btn = text(txt).findOne(500);
if(btn) btn.click();
});
// 跳过黑名单弹窗
let blacklist = ["重要提示", "不可关闭"];
blacklist.forEach(txt => {
let node = textContains(txt).findOne(500);
if(node) log("跳过黑名单弹窗:" + txt);
});
2.6 弹窗处理日志与异常上报
// 记录弹窗处理日志
function logPopup(msg) {
let line = `[${new Date().toLocaleTimeString()}] ${msg}`;
files.append("/sdcard/popup.log", line + "\n");
toast(msg);
}
// 异常弹窗上报(如推送到微信/邮箱)
function reportException(msg) {
// 这里可集成第三方推送API
log("异常上报:" + msg);
}
2.7 弹窗处理与主流程协同
// 主流程与弹窗处理线程协同
var popupThread = threads.start(function(){
// ...弹窗处理逻辑...
});
// 主流程
for(let i=0;i<10;i++){
toast("主流程第" + (i+1) + "步");
sleep(2000);
}
// 结束时关闭弹窗线程
popupThread.interrupt();
2.8 异常捕获与自动重试
// 捕获异常并自动重试
function safeClick(selector, retry=3) {
for(let i=0;i<retry;i++){
try{
let btn = selector.findOne(2000);
if(btn){
btn.click();
return true;
}
}catch(e){
log("点击异常,重试中..." + e);
}
sleep(1000);
}
return false;
}
safeClick(text("确定"));
三、实战项目:全局弹窗与异常自动处理器
3.1 需求分析
- 实时监控全局弹窗、广告、异常提示
- 支持多种弹窗类型、文本、控件、正则、模糊查找
- 支持弹窗优先级、黑白名单、自定义规则
- 支持日志记录、异常上报、自动重试
- 支持主流程与弹窗线程协同、自动退出
3.2 项目结构
autojs-popupguard/
├── main.js
├── modules/
│ ├── popup_guard.js
│ └── logger.js
├── logs/
│ └── popup.log
└── README.md
3.3 popup_guard.js 代码
// modules/popup_guard.js
const logger = require("./logger.js");
const popupTexts = ["关闭", "取消", "我知道了", "忽略", "不再提示", "以后再说", "同意", "允许", "确定", "OK", "Yes"];
const highPriority = ["危险", "警告", "异常", "登录失效"];
const blacklist = ["重要提示", "不可关闭"];
function startGuard() {
return threads.start(function(){
while(true){
// 优先处理高危弹窗
highPriority.forEach(txt => {
let btn = textContains(txt).findOne(500);
if(btn){
btn.click();
logger.log("高危弹窗已处理:" + txt);
}
});
// 处理普通弹窗
popupTexts.forEach(txt => {
let btn = text(txt).findOne(500);
if(btn){
btn.click();
logger.log("弹窗已关闭:" + txt);
}
});
// 跳过黑名单弹窗
blacklist.forEach(txt => {
let node = textContains(txt).findOne(500);
if(node) logger.log("跳过黑名单弹窗:" + txt);
});
sleep(1000);
}
});
}
module.exports = { startGuard };
3.4 日志模块 modules/logger.js
// modules/logger.js
function log(msg) {
let line = `[${new Date().toLocaleTimeString()}] ${msg}`;
files.append("../logs/popup.log", line + "\n");
toast(msg);
}
module.exports = { log };
3.5 main.js 代码
// main.js
const guard = require("./modules/popup_guard.js");
const logger = require("./modules/logger.js");
// 启动弹窗守护线程
var guardThread = guard.startGuard();
// 主流程示例
for(let i=0;i<10;i++){
logger.log("主流程第" + (i+1) + "步");
sleep(2000);
}
logger.log("主流程结束");
// 结束时关闭弹窗线程
guardThread.interrupt();
四、分步详解与进阶技巧
4.1 多线程弹窗监控
- 主线程与弹窗线程分离,互不干扰
- 支持多线程并发监控不同App、不同页面
4.2 正则、模糊查找与动态适配
- 用 textMatches、textContains 提升弹窗适配率
- 动态适配不同品牌、不同语言、不同版本弹窗
4.3 弹窗优先级与黑白名单
- 高危弹窗优先处理,普通弹窗批量处理,黑名单弹窗跳过
- 支持自定义弹窗规则、动态调整优先级
4.4 异常捕获与自动重试
- try-catch 捕获异常,日志记录
- 异常弹窗自动重试、报警、上报
4.5 日志记录与异常上报
- 详细记录弹窗处理历史、异常信息
- 支持推送到微信/邮箱/钉钉等第三方平台
4.6 主流程与弹窗线程协同
- 主流程与弹窗线程互不阻塞,提升健壮性
- 支持主流程结束时自动关闭弹窗线程
4.7 性能优化与资源释放
- 控制弹窗线程数量,避免资源耗尽
- 弹窗处理加超时,避免死循环
- 日志分级输出,开发阶段多输出,正式运行时降级
- 异步处理耗时操作,提升主流程响应
- 定期清理无用变量、释放资源,降低内存占用
五、常见问题与解决方案
| 问题 | 解决方案 |
|---|---|
| 弹窗找不到/误点 | 检查控件属性、增加等待时间、优化查找方式 |
| 弹窗处理线程卡死/崩溃 | try-catch 捕获异常,日志记录,自动重启 |
| 多层弹窗/嵌套弹窗未处理 | 用递归、分步处理、增加查找深度 |
| 黑名单弹窗误处理 | 优化黑白名单规则,动态调整 |
| 异常弹窗未上报/日志丢失 | 检查日志路径、权限、输出逻辑 |
| 弹窗处理与主流程冲突 | 合理拆分主流程与弹窗线程,避免互相阻塞 |
| 误点导致主流程异常 | 增加弹窗识别条件、日志回溯、异常捕获 |
| 资源泄漏/线程未释放 | 线程退出及时释放资源,定期清理无用变量 |
六、性能优化建议
- 控制弹窗线程数量,避免资源耗尽
- 弹窗查找加超时,避免死循环
- 优先级处理,提升高危弹窗响应速度
- 日志分级输出,开发阶段多输出,正式运行时降级
- 异步处理耗时操作,提升主流程响应
- 定期清理无用变量、释放资源,降低内存占用
- 合理 sleep,避免无效等待
- 主流程与弹窗线程分离,提升健壮性
最后感谢阅读!欢迎关注我,微信公众号:
《鲫小鱼不正经》。欢迎点赞、收藏、关注,一键三连!!!