自动发帖软件
标题:
agent代理模式功能小结
[打印本页]
作者:
发帖软件
时间:
3 小时前
标题:
agent代理模式功能小结
agent代理模式功能小结
1.png
(743.08 KB, 下载次数: 0)
3 小时前
上传
// AIWROK agent 代理 API 完整示例
// 展示常用的代理操作
print.log("===== agent 代理 API 示例 =====");
// ========== 1. 绝对坐标点击 agent.click(x, y) ==========
print.log("\n--- 1. 绝对坐标点击 agent.click(x, y) ---");
print.log("说明:使用屏幕绝对像素坐标进行点击");
print.log("适用:已知精确坐标的场景");
var 屏幕宽 = screen.getScreenWidth();
var 屏幕高 = screen.getScreenHeight();
print.log("当前屏幕:" + 屏幕宽 + " x " + 屏幕高);
agent.click(100, 100);
print.log("✓ 已点击坐标 (100, 100)");
var 中心X = Math.floor(屏幕宽 / 2);
var 中心Y = Math.floor(屏幕高 / 2);
agent.click(中心X, 中心Y);
print.log("✓ 已点击屏幕中心 (" + 中心X + ", " + 中心Y + ")");
// ========== 2. 百分比坐标点击 agent.clickPercent(px, py) ==========
print.log("\n--- 2. 百分比坐标点击 agent.clickPercent(px, py) ---");
print.log("说明:使用百分比坐标(0.0-1.0),自动适配不同屏幕");
print.log("适用:需要在不同分辨率设备上运行的脚本");
agent.clickPercent(0.5, 0.5);
print.log("✓ 已点击屏幕中心 (50%, 50%)");
agent.clickPercent(0.9, 0.9);
print.log("✓ 已点击屏幕右下区域 (90%, 90%)");
agent.clickPercent(0.5, 0.1);
print.log("✓ 已点击屏幕顶部中间 (50%, 10%)");
// ========== 3. 查找文字并点击 ==========
print.log("\n--- 3. 查找文字并点击 ---");
print.log("说明:通过 agent.shell() 执行 uiautomator dump 获取 UI XML");
print.log("注意:agent.getXml() 返回对象而非字符串,获取UI() 返回字符串");
function 执行Shell(命令) {
var 结果 = agent.shell(命令);
if (!结果) return "";
var 结果字符串 = "";
if (typeof 结果 === "string") {
结果字符串 = 结果;
} else if (结果.toString) {
结果字符串 = 结果.toString();
} else {
结果字符串 = "" + 结果;
}
var startIdx = -1;
if (typeof 结果字符串.indexOf === "function") {
startIdx = 结果字符串.indexOf("successMsg:");
}
if (startIdx !== -1) {
var afterSuccess = 结果字符串.substring(startIdx + 11);
var errorIdx = afterSuccess.indexOf(",errorMsg:");
if (errorIdx !== -1) {
var content = afterSuccess.substring(0, errorIdx);
var endMarker = content.indexOf("UI hierchary dumped to:");
if (endMarker !== -1) {
content = content.substring(0, endMarker);
}
return "" + content.trim();
}
return "" + afterSuccess.trim();
}
return "" + 结果字符串;
}
function 获取UI() {
var 临时文件 = "/sdcard/ui_dump.xml";
agent.shell("uiautomator dump --compressed " + 临时文件 + " 2>/dev/null");
var 结果 = agent.shell("cat " + 临时文件);
if (!结果) return "";
var 结果字符串 = "";
if (typeof 结果 === "string") {
结果字符串 = 结果;
} else if (结果.toString) {
结果字符串 = 结果.toString();
} else {
结果字符串 = "" + 结果;
}
var startIdx = -1;
if (typeof 结果字符串.indexOf === "function") {
startIdx = 结果字符串.indexOf("successMsg:");
}
var content = "";
if (startIdx !== -1) {
var afterSuccess = 结果字符串.substring(startIdx + 11);
var errorIdx = afterSuccess.indexOf(",errorMsg:");
if (errorIdx !== -1) {
content = afterSuccess.substring(0, errorIdx);
var endMarker = content.indexOf("UI hierchary dumped to:");
if (endMarker !== -1) {
content = content.substring(0, endMarker);
}
} else {
content = afterSuccess;
}
content = content.trim();
} else {
content = 结果字符串;
}
return "" + content;
}
var xml = 获取UI();
if (xml.indexOf("网络和互联网") !== -1) {
print.log("找到【网络和互联网】节点");
var 文字索引 = xml.indexOf("网络和互联网");
var 后面 = xml.substring(文字索引);
var m = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (m) {
var left = parseInt(m[1]);
var top = parseInt(m[2]);
var right = parseInt(m[3]);
var bottom = parseInt(m[4]);
var centerX = (left + right) / 2;
var centerY = (top + bottom) / 2;
print.log("节点范围:[" + left + "," + top + "][" + right + "," + bottom + "]");
print.log("计算中心点:(" + centerX + ", " + centerY + ")");
agent.click(centerX, centerY);
print.log("✓ 已点击【网络和互联网】");
} else {
print.log("⚠ 未找到节点坐标");
}
} else {
print.log("当前页面未找到【网络和互联网】");
}
print.log("\n💡 点击提示:");
print.log("- agent.click(x,y) 适合固定坐标或从节点计算出的坐标");
print.log("- agent.clickPercent(px,py) 适合跨设备兼容的场景");
print.log("- 两者可以配合 auto.findText() 实现智能定位点击");
// ========== 4. 滑动操作 ==========
print.log("\n--- 4. 滑动操作 ---");
agent.swip(540, 2800, 540, 800, 500); // 从下往上滑动
print.log("✓ 滑动完成");
// ========== 5. AI 算法滑动(模拟手动)==========
print.log("\n--- 5. AI 算法滑动 ---");
agent.swipAI(540, 2800, 540, 800); // 更自然的滑动
print.log("✓ AI 滑动完成");
// ========== 6. 按键操作 ==========
print.log("\n--- 6. 按键操作 ---");
agent.back(); // 返回键
print.log("✓ 按下返回键");
agent.home(); // Home 键
print.log("✓ 按下 Home 键");
agent.home2(); // Home 键(另一种实现方式)
print.log("✓ 发送 Home 按键(home2)");
agent.recents(); // 最近任务键
print.log("✓ 按下最近任务键");
// agent.power(); // 开机键(移到脚本最后,避免提前关屏)
// print.log("✓ 按下开机键");
agent.keyPress(4); // 发送按键码 4(返回键,等同于 back())
print.log("✓ 通过 keyPress 发送返回键");
agent.keyPress(3); // 发送按键码 3(Home 键,等同于 home())
print.log("✓ 通过 keyPress 发送 Home 键");
// ========== 7. 输入文本 ==========
print.log("\n--- 7. 输入文本 ---");
agent.input("Hello World"); // 输入文字
print.log("✓ 已输入文本");
// ========== 8. 获取节点信息 ==========
print.log("\n--- 8. 获取节点信息 ---");
print.log("注意:agent.getXml() 返回对象,获取UI() 返回字符串");
var xml2 = 获取UI();
print.log("XML 长度:" + xml2.length);
function 查找所有包含文字的节点(xml, 文字) {
var 结果 = [];
var 位置 = 0;
while (true) {
var 索引 = xml.indexOf('text="' + 文字 + '"', 位置);
if (索引 === -1) break;
var 后面 = xml.substring(索引);
var m = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (m) {
结果.push({
left: parseInt(m[1]),
top: parseInt(m[2]),
right: parseInt(m[3]),
bottom: parseInt(m[4]),
centerX: (parseInt(m[1]) + parseInt(m[3])) / 2,
centerY: (parseInt(m[2]) + parseInt(m[4])) / 2
});
}
位置 = 索引 + 10;
}
return 结果;
}
var nodes = 查找所有包含文字的节点(xml2, "同意");
print.log("找到包含'同意'的节点数:" + nodes.length);
function 查找所有节点JSON(xml) {
var 结果 = [];
var 节点列表 = [];
var classIndex = xml.indexOf('class="');
while (classIndex !== -1) {
var 后面 = xml.substring(classIndex);
var boundsM = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
var textM = 后面.match(/text="([^"]*)"/);
var idM = 后面.match(/resource-id="([^"]*)"/);
if (boundsM) {
var 节点 = {
class: "",
left: parseInt(boundsM[1]),
top: parseInt(boundsM[2]),
right: parseInt(boundsM[3]),
bottom: parseInt(boundsM[4]),
text: textM ? textM[1] : "",
resourceId: idM ? idM[1] : ""
};
结果.push(节点);
}
classIndex = xml.indexOf('class="', classIndex + 7);
}
return 结果;
}
var jsonNodes = 查找所有节点JSON(xml2);
print.log("JSON 节点数:" + jsonNodes.length);
print.log("\n💡 提示:agent.findNodesByTextMatches/Contains/Json 在实际设备上不存在");
print.log(" 请使用 agent.shell('uiautomator dump ...') + 自定义函数解析");
// ========== 9. 截图 ==========
print.log("\n--- 9. 屏幕截图 ---");
print.log("说明:agent.screenShot() 在部分设备上不存在,使用 shell 命令截图");
var 截图路径 = "/sdcard/screenshot_" + Date.now() + ".png";
agent.shell("screencap -p " + 截图路径);
print.log("✓ 截图已保存到:" + 截图路径);
var 检查文件 = 执行Shell("ls -l " + 截图路径);
if (检查文件) {
print.log("✓ 截图文件信息:" + 检查文件);
}
// ========== 10. Shell 命令 ==========
print.log("\n--- 10. 执行 Shell 命令 ---");
var result = 执行Shell("uiautomator dump --compressed /proc/self/fd/1 2>/dev/null");
print.log("✓ Shell 命令执行完成");
// ========== 11. 触摸事件(高级)==========
print.log("\n--- 11. 触摸事件 ---");
print.log("说明:touchDown 可用,但 touchMove/touchUp/touchUpUp 在部分设备上不存在");
print.log("注意:实际测试中,仅 touchDown 可调用,其他方法报错");
agent.touchDown(540, 1800); // 按下(x, y)- 已验证可用
sleep.millisecond(毫秒 = 100);
// agent.touchMove(540, 1900); // 移动 - 报错:Can't find method
// sleep.millisecond(毫秒 = 100);
// agent.touchUp(540, 1900); // 抬起 - 报错:Can't find method
print.log("✓ touchDown 执行完成(touchMove/touchUp/touchUpUp 在当前设备上不可用)");
// touchUpUp 与 touchUp 类似,但同样在当前设备上不可用
// agent.touchUpUp(540, 1900); // 触摸抬起 - 报错:Can't find method
print.log("✓ touchUpUp 在当前设备上不可用");
// ========== 12. 检查代理状态 ==========
print.log("\n--- 12. 代理状态 ---");
var isOpen = agent.isOpen();
print.log("代理是否开启:" + isOpen);
// ========== 13. 开启代理模式 ==========
print.log("\n--- 13. 开启代理模式 agent.start() ---");
print.log("说明:开启代理模式,手机必须 root 或使用 PC_IDE 的 adb 连接");
print.log("返回值:boolean,成功返回 true");
var 开启结果 = agent.start();
print.log("开启代理模式结果:" + 开启结果);
var 再次检查 = agent.isOpen();
print.log("开启后代理状态:" + 再次检查);
// ========== 14. 四个方向滑动 ==========
print.log("\n--- 14. 四个方向滑动 ---");
print.log("说明:通过交换起止坐标实现上/下/左/右四个方向的滑动");
var 中X = Math.floor(屏幕宽 / 2);
var 中Y = Math.floor(屏幕高 / 2);
var 偏移 = 800;
// 向上滑动(内容向上滚动,看下方内容)
agent.swip(中X, 中Y + 偏移, 中X, 中Y - 偏移, 500);
print.log("✓ 向上滑动完成");
// 向下滑动(内容向下滚动,看上方内容)
agent.swip(中X, 中Y - 偏移, 中X, 中Y + 偏移, 500);
print.log("✓ 向下滑动完成");
// 向左滑动(查看右侧内容,如翻页)
agent.swip(中X + 偏移, 中Y, 中X - 偏移, 中Y, 500);
print.log("✓ 向左滑动完成");
// 向右滑动(查看左侧内容,如返回上一页)
agent.swip(中X - 偏移, 中Y, 中X + 偏移, 中Y, 500);
print.log("✓ 向右滑动完成");
// ========== 15. 长按操作 ==========
print.log("\n--- 15. 长按操作 ---");
print.log("说明:由于 touchUp 在当前设备上不可用,使用 swip 实现长按");
// agent.touchDown(540, 1800);
// sleep.second(秒 = 2);
// agent.touchUp(540, 1800); // 报错:Can't find method
// print.log("✓ 长按 (540, 1800) 持续 2 秒完成");
// 长按用 swip 实现(起点终点几乎相同,时间长)
agent.swip(540, 1800, 541, 1801, 2000);
print.log("✓ 通过 swip 实现长按完成(持续 2 秒)");
// ========== 15. 双击操作 ==========
print.log("\n--- 15. 双击操作 ---");
print.log("说明:两次连续 click,间隔 100-200ms 模拟双击");
agent.click(540, 1800);
sleep.millisecond(毫秒 = 150);
agent.click(540, 1800);
print.log("✓ 双击 (540, 1800) 完成");
// ========== 16. 剪贴板操作与粘贴 ==========
print.log("\n--- 16. 剪贴板操作与粘贴 ---");
print.log("说明:先写入剪贴板,再通过按键粘贴到当前输入框");
var 待输入文本 = "这是要粘贴的中文内容";
// 方式1:通过 Clipboard.copy() 设置剪贴板
Clipboard.copy(待输入文本);
sleep.millisecond(毫秒 = 300);
// 方式2:通过 shell service call clipboard(双保险,部分设备 Clipboard API 失效时使用)
agent.shell("service call clipboard 3 i32 1 s16 '" + 待输入文本 + "' i32 0");
sleep.millisecond(毫秒 = 300);
// 触发粘贴:KEYCODE_PASTE (279)
agent.shell("input keyevent 279");
sleep.second(秒 = 1);
print.log("✓ 已通过 KEYCODE_PASTE 粘贴文本");
// 备用方式:Ctrl+V 组合键(KEYCODE_V=50 + META_CTRL_ON=0x1000)
// agent.shell("input keyevent 50 --meta 0x1000");
// ========== 17. 启动应用 ==========
print.log("\n--- 17. 启动应用 ---");
print.log("说明:使用 app.openApp() 启动指定包名的应用");
var 抖音包名 = "com.ss.android.ugc.aweme";
var 小红书包名 = "com.xingin.xhs";
var 微信包名 = "com.tencent.mm";
var 头条极速版包名 = "com.ss.android.article.lite";
var 设置包名 = "com.android.settings";
print.log("常用应用包名:");
print.log("- 抖音:" + 抖音包名);
print.log("- 小红书:" + 小红书包名);
print.log("- 微信:" + 微信包名);
print.log("- 头条极速版:" + 头条极速版包名);
print.log("- 设置:" + 设置包名);
// 启动抖音(示例,注释掉避免实际执行)
// app.openApp(抖音包名);
// sleep.second(秒 = 5);
// print.log("✓ 已启动抖音");
print.log("💡 提示:启动后可配合 agent.clickPercent() 进行界面操作");
// ========== 18. 通过 resourceId 查找节点 ==========
print.log("\n--- 18. 通过 resourceId 查找节点 ---");
print.log("说明:从 XML 中通过 resource-id 属性查找节点坐标");
function 通过ID查找节点(xml, resourceId) {
var 索引 = xml.indexOf('resource-id="' + resourceId + '"');
if (索引 === -1) {
return null;
}
var 后面 = xml.substring(索引);
var m = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (!m) {
return null;
}
var left = parseInt(m[1]);
var top = parseInt(m[2]);
var right = parseInt(m[3]);
var bottom = parseInt(m[4]);
return {
left: left,
top: top,
right: right,
bottom: bottom,
centerX: (left + right) / 2,
centerY: (top + bottom) / 2,
width: right - left,
height: bottom - top
};
}
var xmlForId = 获取UI();
function 获取当前包名(xml) {
var m = xml.match(/package="([^"]+)"/);
return m ? m[1] : "";
}
var 当前包名 = 获取当前包名(xmlForId);
print.log("当前前台应用包名:" + 当前包名);
var 节点ById = 通过ID查找节点(xmlForId, "android:id/title");
if (节点ById) {
print.log("✓ 找到标题节点,中心点:(" + 节点ById.centerX + ", " + 节点ById.centerY + ")");
print.log(" 尺寸:" + 节点ById.width + " x " + 节点ById.height);
} else {
var 所有Ids = [];
var idIndex = xmlForId.indexOf('resource-id="');
while (idIndex !== -1) {
var endIndex = xmlForId.indexOf('"', idIndex + 13);
if (endIndex !== -1) {
var id = xmlForId.substring(idIndex + 13, endIndex);
if (id && !id.match(/^com\.android/) && !所有Ids[id]) {
所有Ids.push(id);
所有Ids[id] = true;
}
}
idIndex = xmlForId.indexOf('resource-id="', idIndex + 13);
}
print.log("⚠ 未找到指定 resourceId,当前界面可用 resource-id 列表(前10个):");
for (var i = 0; i < Math.min(10, 所有Ids.length); i++) {
print.log(" - " + 所有Ids[i]);
}
}
// ========== 19. 通过 className 查找所有节点 ==========
print.log("\n--- 19. 通过 className 查找所有节点 ---");
print.log("说明:查找界面上所有指定 className 的节点(如所有按钮/输入框)");
function 通过Class查找所有节点(xml, className) {
var 结果 = [];
var 查找值 = 'class="' + className + '"';
var 位置 = 0;
while (true) {
var 索引 = xml.indexOf(查找值, 位置);
if (索引 === -1) break;
var 后面 = xml.substring(索引);
var m = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (m) {
var left = parseInt(m[1]);
var top = parseInt(m[2]);
var right = parseInt(m[3]);
var bottom = parseInt(m[4]);
结果.push({
left: left,
top: top,
right: right,
bottom: bottom,
centerX: (left + right) / 2,
centerY: (top + bottom) / 2,
width: right - left,
height: bottom - top
});
}
位置 = 索引 + 查找值.length;
}
return 结果;
}
var xmlForClass = 获取UI();
// 查找所有 EditText 输入框
var 输入框列表 = 通过Class查找所有节点(xmlForClass, "android.widget.EditText");
print.log("找到 EditText 输入框数量:" + 输入框列表.length);
for (var i = 0; i < 输入框列表.length; i++) {
var 框 = 输入框列表[i];
print.log(" 输入框[" + i + "] 中心(" + 框.centerX + ", " + 框.centerY + ") 尺寸 " + 框.width + "x" + 框.height);
}
// 查找所有 Button 按钮
var 按钮列表 = 通过Class查找所有节点(xmlForClass, "android.widget.Button");
print.log("找到 Button 按钮数量:" + 按钮列表.length);
// ========== 20. 通过 content-desc 查找节点 ==========
print.log("\n--- 20. 通过 content-desc 查找节点 ---");
print.log("说明:通过无障碍描述查找节点(适合图标按钮,如返回/加号)");
function 通过ContentDesc查找节点(xml, desc) {
var 索引 = xml.indexOf('content-desc="' + desc + '"');
if (索引 === -1) {
return null;
}
var 后面 = xml.substring(索引);
var m = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (!m) {
return null;
}
var left = parseInt(m[1]);
var top = parseInt(m[2]);
var right = parseInt(m[3]);
var bottom = parseInt(m[4]);
return {
left: left,
top: top,
right: right,
bottom: bottom,
centerX: (left + right) / 2,
centerY: (top + bottom) / 2
};
}
var xmlForDesc = 获取UI();
var 返回节点 = 通过ContentDesc查找节点(xmlForDesc, "返回");
if (返回节点) {
print.log("✓ 找到【返回】按钮,中心点:(" + 返回节点.centerX + ", " + 返回节点.centerY + ")");
} else {
print.log("⚠ 当前页面未找到 content-desc=返回 的节点");
}
// 常见的 content-desc 值:返回、发布、加号、+、搜索、菜单、更多
// ========== 21. 通过 hint 查找输入框 ==========
print.log("\n--- 21. 通过 hint 查找输入框 ---");
print.log("说明:输入框未输入内容时通常显示 hint 提示文字(如标题/正文)");
function 通过Hint查找输入框(xml, hint) {
var 索引 = xml.indexOf('hint="' + hint + '"');
if (索引 === -1) {
// 尝试变体
var 变体 = [hint, "请输入" + hint, "输入" + hint, "写" + hint];
for (var i = 0; i < 变体.length; i++) {
索引 = xml.indexOf('hint="' + 变体[i] + '"');
if (索引 !== -1) {
hint = 变体[i];
break;
}
}
}
if (索引 === -1) {
return null;
}
var 后面 = xml.substring(索引);
var m = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (!m) {
return null;
}
return {
centerX: (parseInt(m[1]) + parseInt(m[3])) / 2,
centerY: (parseInt(m[2]) + parseInt(m[4])) / 2,
hint: hint
};
}
var xmlForHint = 获取UI();
var 标题框 = 通过Hint查找输入框(xmlForHint, "标题");
if (标题框) {
print.log("✓ 找到标题输入框(hint=" + 标题框.hint + ")中心点:(" + 标题框.centerX + ", " + 标题框.centerY + ")");
} else {
print.log("⚠ 未找到标题输入框");
}
// ========== 22. 等待节点出现 ==========
print.log("\n--- 22. 等待节点出现 ---");
print.log("说明:循环检测 XML,直到出现目标文字或超时(适合页面加载等待)");
function 等待文字出现(目标文字, 超时秒) {
var 开始时间 = Date.now();
var 超时毫秒 = 超时秒 * 1000;
while (Date.now() - 开始时间 < 超时毫秒) {
try {
var xml = 获取UI();
if (xml.indexOf(目标文字) !== -1) {
var 已等待 = Math.floor((Date.now() - 开始时间) / 1000);
print.log("✓ 在 " + 已等待 + " 秒后检测到【" + 目标文字 + "】");
return true;
}
} catch (e) {
print.log("⚠ 获取 XML 出错:" + e.message);
}
sleep.second(秒 = 1);
}
print.log("✗ 等待 " + 超时秒 + " 秒后未出现【" + 目标文字 + "】");
return false;
}
// 示例:等待"下一步"按钮出现(最多 10 秒)
// var 找到 = 等待文字出现("下一步", 10);
// if (找到) {
// agent.click(节点.centerX, 节点.centerY);
// }
print.log("💡 提示:循环等待 + 节点查找 + 点击 = 稳定的自动化流程");
// ========== 23. 实用 Shell 命令大全 ==========
print.log("\n--- 23. 实用 Shell 命令大全 ---");
print.log("说明:通过 agent.shell() 执行各种系统命令");
// 1. 获取当前界面 XML(最常用)
var uiXml = 执行Shell("uiautomator dump --compressed /proc/self/fd/1 2>/dev/null");
print.log("✓ 1. 获取 UI XML,长度:" + uiXml.length);
// 2. 模拟按键事件(input keyevent)
agent.shell("input keyevent 4"); // KEYCODE_BACK 返回键
agent.shell("input keyevent 3"); // KEYCODE_HOME Home键
agent.shell("input keyevent 24"); // KEYCODE_VOLUME_UP 音量加
agent.shell("input keyevent 25"); // KEYCODE_VOLUME_DOWN 音量减
agent.shell("input keyevent 26"); // KEYCODE_POWER 电源键
agent.shell("input keyevent 279"); // KEYCODE_PASTE 粘贴
print.log("✓ 2. 模拟按键事件完成");
// 3. 启动应用(am start)
// agent.shell("am start -n com.xingin.xhs/.activity.SplashActivity");
// agent.shell("monkey -p com.xingin.xhs 1"); // 通过 monkey 启动
print.log("✓ 3. am start / monkey 启动应用");
// 4. 强制停止应用
// agent.shell("am force-stop com.xingin.xhs");
print.log("✓ 4. am force-stop 强制停止应用");
// 5. 设置剪贴板(service call clipboard)
agent.shell("service call clipboard 3 i32 1 s16 '剪贴板内容' i32 0");
print.log("✓ 5. service call clipboard 设置剪贴板");
// 6. 长按滑动(input swipe,可模拟长按)
// agent.shell("input swipe 540 1800 541 1801 2000");
print.log("✓ 6. input swipe 模拟长按");
// 7. 输入文字(input text,仅支持 ASCII)
agent.shell("input text 'Hello'");
print.log("✓ 7. input text 输入 ASCII 文字");
// 8. 获取系统属性
var 属性值 = 执行Shell("getprop ro.product.model");
print.log("✓ 8. 设备型号:" + 属性值);
// ========== 24. 截图保存到文件 ==========
print.log("\n--- 24. 截图保存到文件 ---");
print.log("说明:使用 screencap 命令截图,agent.screenShot() 在部分设备上不存在");
var 截图路径 = "/sdcard/screenshot_" + Date.now() + ".png";
agent.shell("screencap -p " + 截图路径);
print.log("✓ 截图已保存到:" + 截图路径);
var 文件检查 = 执行Shell("ls -l " + 截图路径);
if (文件检查) {
var 大小信息 = 文件检查;
print.log("✓ 截图文件信息:" + 大小信息);
}
print.log("💡 配合 file API 持久化截图,便于后续 OCR 找字或上传");
// ========== 25. 综合实战:智能查找并点击流程 ==========
print.log("\n--- 25. 综合实战:智能查找并点击流程 ---");
print.log("说明:循环查找节点 → 计算 → 点击 → 验证 → 重试");
function 智能查找并点击(目标文字, 超时秒) {
var 开始时间 = Date.now();
var 超时毫秒 = 超时秒 * 1000;
var 尝试次数 = 0;
while (Date.now() - 开始时间 < 超时毫秒) {
尝试次数++;
try {
var xml = 获取UI();
// 检查目标文字是否存在
if (xml.indexOf(目标文字) === -1) {
sleep.second(秒 = 1);
continue;
}
// 通过 bounds 正则提取坐标
var 文字索引 = xml.indexOf(目标文字);
var 后面 = xml.substring(文字索引);
var m = 后面.match(/bounds="\[(\d+),(\d+)\]\[(\d+),(\d+)\]"/);
if (m) {
var left = parseInt(m[1]);
var top = parseInt(m[2]);
var right = parseInt(m[3]);
var bottom = parseInt(m[4]);
var cx = (left + right) / 2;
var cy = (top + bottom) / 2;
agent.click(cx, cy);
print.log("✓ 第 " + 尝试次数 + " 次尝试:已点击【" + 目标文字 + "】(" + cx + ", " + cy + ")");
// 点击后等待并验证
sleep.second(秒 = 1);
var xml2 = 获取UI();
if (xml2.indexOf(目标文字) === -1) {
print.log("✓ 验证成功:目标已消失");
return true;
} else {
print.log("⚠ 目标仍存在,可能点击未生效,重试...");
}
}
} catch (e) {
print.log("⚠ 第 " + 尝试次数 + " 次尝试出错:" + e.message);
}
sleep.second(秒 = 1);
}
print.log("✗ 超时 " + 超时秒 + " 秒,共尝试 " + 尝试次数 + " 次未成功");
return false;
}
// 示例调用(注释避免实际执行)
// 智能查找并点击("同意", 10);
// 智能查找并点击("下一步", 15);
// 智能查找并点击("发布", 10);
print.log("💡 此函数封装了完整的查找→点击→验证→重试流程,可直接复用");
// ========== 26. 错误处理与重试机制 ==========
print.log("\n--- 26. 错误处理与重试机制 ---");
print.log("说明:使用 try-catch 包裹关键操作,失败时自动重试");
function 带重试的操作(操作函数, 操作名, 最大重试) {
最大重试 = 最大重试 || 3;
for (var i = 1; i <= 最大重试; i++) {
try {
print.log("第 " + i + "/" + 最大重试 + " 次尝试 " + 操作名);
var 结果 = 操作函数();
if (结果) {
print.log("✓ " + 操作名 + " 成功");
return true;
}
} catch (e) {
print.log("⚠ 第 " + i + " 次出错:" + e.message);
}
if (i < 最大重试) {
sleep.second(秒 = 1);
}
}
print.log("✗ " + 操作名 + " 失败,已重试 " + 最大重试 + " 次");
return false;
}
// 示例:带重试的点击操作
// 带重试的操作(function() {
// var xml = 获取UI();
// if (xml.indexOf("下一步") === -1) return false;
// // ... 查找并点击
// return true;
// }, "点击下一步", 3);
print.log("💡 try-catch + 重试机制可大幅提升脚本稳定性");
// ========== 27. 应用管理与切换 ==========
print.log("\n--- 27. 应用管理与切换 ---");
print.log("说明:启动、切换、关闭应用的常用方法");
// 启动应用
// app.openApp("com.xingin.xhs");
// sleep.second(秒 = 5);
// 通过 shell 启动指定 Activity(更精确)
// agent.shell("am start -n com.xingin.xhs/.activity.SplashActivity");
// 通过包名启动(monkey 方式,更通用)
// agent.shell("monkey -p com.xingin.xhs 1");
// 强制停止应用
// agent.shell("am force-stop com.xingin.xhs");
// 切换到最近任务
// agent.recents();
// sleep.second(秒 = 1);
// agent.clickPercent(0.5, 0.5); // 点击第一个任务
// 查看当前前台应用
var 当前应用 = 执行Shell("dumpsys window | grep mCurrentFocus");
var 当前应用长度 = typeof 当前应用.length === "function" ? 当前应用.length() : (当前应用.length || 0);
var 当前应用显示 = 当前应用.substring(0, Math.min(当前应用长度, 100));
print.log("当前前台应用信息:" + 当前应用显示);
print.log("💡 应用管理流程:启动 → 操作 → 验证 → 关闭");
// ========== 28. 电源键操作(最后执行)==========
print.log("\n--- 28. 电源键操作 ---");
print.log("说明:移到最后执行,避免提前关屏影响后续操作");
agent.power(); // 开机键
print.log("✓ 按下开机键(关屏)");
print.log("\n===== 示例结束 =====");
复制代码
欢迎光临 自动发帖软件 (http://www.fatiegongju.com/)
Powered by Discuz! X3.2