 | |  |  | agent代理模式功能小结
- // 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===== 示例结束 =====");
复制代码
| |  | |  |
|