B2B网络软件
标题:
adb.exec() 高级用法完整示例
[打印本页]
作者:
YYPOST群发软件
时间:
1 小时前
标题:
adb.exec() 高级用法完整示例
adb.exec() 高级用法完整示例
1.png
(1.59 MB, 下载次数: 0)
下载附件
1 小时前
上传
2.png
(1.69 MB, 下载次数: 0)
下载附件
1 小时前
上传
// =============================================================================
// AIWROK adb.exec() 高级用法完整示例
// =============================================================================
// 适用平台:AIWROK 安卓自动化软件
// 引擎:Rhino (ES5)
// 说明:adb.exec(command, isRoot) 是 AIWROK 提供的 ADB 命令执行接口
// - 参数1 (command):要执行的 shell 命令字符串
// - 参数2 (isRoot):boolean,true=以 root 权限执行(su -c),false=普通权限执行
// - 返回值:JSON 格式 {"errorMsg":"","success":"实际内容"},需提取 success 字段
//
// 与 agent.shell() 的区别:
// - agent.shell() 仅在代理模式下可用,需要 root 或 PC_ADB 连接
// - adb.exec() 可直接在设备端执行,isRoot 参数灵活控制权限
// - adb.exec() 返回值需要清洗,agent.shell() 返回值相对干净
// =============================================================================
print.log("===== adb.exec() 高级用法完整示例 =====\n");
// =============================================================================
// 工具函数:清洗 adb.exec 返回值
// =============================================================================
// adb.exec() 实际返回 JSON 格式: {"errorMsg":"","success":"实际内容"}
// 需要提取 success 字段的值,并处理转义字符
function 清洗输出(原始结果) {
if (!原始结果) return "";
var 结果 = String(原始结果);
// 格式1: JSON 格式 {"errorMsg":"","success":"实际内容"}
if (结果.charAt(0) === "{") {
try {
var json = JSON.parse(结果);
if (json && json.success !== undefined) {
// 检查是否有错误
if (json.errorMsg && json.errorMsg !== "") {
print.log("⚠ 命令返回错误: " + json.errorMsg);
}
return String(json.success).trim();
}
} catch (e) {
// JSON.parse 失败,尝试正则提取 success 字段
var successMatch = 结果.match(/"success"\s*:\s*"([\s\S]*?)"\s*[,}]/);
if (successMatch) {
return successMatch[1]
.replace(/\\n/g, "\n")
.replace(/\\t/g, "\t")
.replace(/\\"/g, '"')
.replace(/\\\\/g, "\\")
.trim();
}
}
return 结果.trim();
}
// 格式2: 旧格式 successMsg:内容,errorMsg:内容(兼容 agent.shell)
if (结果.indexOf("successMsg:") === 0) {
结果 = 结果.substring("successMsg:".length);
}
var 错误索引 = 结果.indexOf(",errorMsg:");
if (错误索引 !== -1) {
结果 = 结果.substring(0, 错误索引);
}
return 结果.trim();
}
// 工具函数:安全执行命令并返回清洗后的结果
function 执行命令(命令, 是否root) {
try {
var 原始 = adb.exec(命令, 是否root || false);
return 清洗输出(String(原始));
} catch (e) {
print.log("⚠ 命令执行异常 [" + 命令 + "]: " + e.message);
return "";
}
}
// 工具函数:安全执行命令(不关心返回值,只关心是否成功)
function 执行命令静默(命令, 是否root) {
try {
adb.exec(命令, 是否root || false);
return true;
} catch (e) {
print.log("⚠ 命令执行异常 [" + 命令 + "]: " + e.message);
return false;
}
}
// =============================================================================
// 工具函数:3秒倒计时(每个动作前执行,增加节奏感)
// =============================================================================
function 倒计时(秒数, 提示) {
秒数 = 秒数 || 3;
提示 = 提示 || "";
for (var i = 秒数; i > 0; i--) {
print.log("⏳ " + 提示 + " 倒计时: " + i + " 秒...");
sleep.second(1);
}
print.log("▶ " + 提示 + " 开始执行");
}
// =============================================================================
// 第一部分:基础文件操作
// =============================================================================
倒计时(3, "第一部分:基础文件操作");
print.log("========== 第一部分:基础文件操作 ==========\n");
// 1.1 列出目录内容(非 root)
print.log("--- 1.1 列出 /sdcard/ 目录内容 ---");
var 目录列表 = 执行命令("ls -la /sdcard/", false);
print.log("目录内容:\n" + 目录列表);
// 1.2 列出指定目录并过滤(结合 grep 管道,注意不能用 grep -P)
print.log("\n--- 1.2 列出 /sdcard/ 下的 .png 文件 ---");
var 图片列表 = 执行命令("ls /sdcard/*.png 2>/dev/null", false);
print.log("PNG 文件:\n" + (图片列表 || "无"));
// 1.3 查看文件内容
print.log("\n--- 1.3 查看 /sdcard/test.txt 文件内容 ---");
var 文件内容 = 执行命令("cat /sdcard/test.txt 2>/dev/null", false);
print.log("文件内容:\n" + (文件内容 || "文件不存在或为空"));
// 1.4 创建目录(需要 root 时操作 /data 等系统目录)
print.log("\n--- 1.4 创建目录 ---");
执行命令静默("mkdir -p /sdcard/aiwrok_test", false);
print.log("✓ 已创建 /sdcard/aiwrok_test 目录");
// 1.5 复制文件
print.log("\n--- 1.5 复制文件 ---");
执行命令静默("cp /sdcard/test.txt /sdcard/aiwrok_test/test_backup.txt 2>/dev/null", false);
print.log("✓ 已复制文件");
// 1.6 写入文件(通过 echo 重定向)
print.log("\n--- 1.6 通过 echo 写入文件 ---");
执行命令静默("echo 'AIWROK adb.exec 测试写入' > /sdcard/aiwrok_test/write_test.txt", false);
var 写入验证 = 执行命令("cat /sdcard/aiwrok_test/write_test.txt", false);
print.log("写入验证:" + 写入验证);
// 1.7 获取文件大小和权限信息
print.log("\n--- 1.7 获取文件详细信息 ---");
var 文件信息 = 执行命令("ls -l /sdcard/aiwrok_test/write_test.txt", false);
print.log("文件信息:" + 文件信息);
// 1.8 统计目录下文件数量
print.log("\n--- 1.8 统计 /sdcard/ 下文件数量 ---");
var 文件数 = 执行命令("ls /sdcard/ | wc -l", false);
print.log("文件数量:" + 文件数);
// =============================================================================
// 第二部分:应用管理(Package Manager)
// =============================================================================
倒计时(3, "第二部分:应用管理");
print.log("\n========== 第二部分:应用管理 ==========\n");
// 2.1 列出所有已安装的第三方应用
print.log("--- 2.1 列出所有第三方应用包名 ---");
var 第三方应用 = 执行命令("pm list packages -3", false);
var 应用数组 = 第三方应用 ? 第三方应用.split("\n") : [];
print.log("第三方应用数量:" + 应用数组.length);
// 只打印前5个
for (var i = 0; i < Math.min(5, 应用数组.length); i++) {
print.log(" " + 应用数组[i]);
}
if (应用数组.length > 5) {
print.log(" ... 共 " + 应用数组.length + " 个应用");
}
// 2.2 列出所有系统应用
print.log("\n--- 2.2 列出系统应用数量 ---");
var 系统应用 = 执行命令("pm list packages -s", false);
var 系统应用数组 = 系统应用 ? 系统应用.split("\n") : [];
print.log("系统应用数量:" + 系统应用数组.length);
// 2.3 查看指定应用信息
print.log("\n--- 2.3 查看微信应用信息 ---");
var 微信信息 = 执行命令("pm list packages com.tencent.mm", false);
print.log("微信包名信息:" + (微信信息 || "未安装微信"));
// 2.4 启动应用(通过 am start)
print.log("\n--- 2.4 启动指定应用 ---");
// 启动设置应用
执行命令静默("am start -a android.settings.SETTINGS", false);
print.log("✓ 已启动系统设置");
// 2.5 通过 monkey 启动应用
print.log("\n--- 2.5 通过 monkey 启动应用 ---");
// 执行命令静默("monkey -p com.tencent.mm 1", false);
print.log("(示例)可通过 monkey -p <包名> 1 启动应用");
// 2.6 强制停止应用
print.log("\n--- 2.6 强制停止应用 ---");
// 执行命令静默("am force-stop com.tencent.mm", false);
print.log("(示例)可通过 am force-stop <包名> 强制停止应用");
// 2.7 清除应用数据(需要 root 或对应权限)
print.log("\n--- 2.7 清除应用数据(root 示例)---");
// adb.exec("pm clear com.example.app", true); // true = root 权限
print.log("(示例)adb.exec('pm clear com.example.app', true) 以 root 清除应用数据");
// 2.8 安装 / 卸载 APK
print.log("\n--- 2.8 安装/卸载 APK ---");
// 安装:adb.exec("pm install /sdcard/app.apk", false);
// 卸载:adb.exec("pm uninstall com.example.app", false);
print.log("(示例)pm install / pm uninstall 可安装/卸载应用");
// =============================================================================
// 第三部分:系统信息获取
// =============================================================================
倒计时(3, "第三部分:系统信息获取");
print.log("\n========== 第三部分:系统信息获取 ==========\n");
// 3.1 获取系统属性(getprop)
print.log("--- 3.1 获取设备系统属性 ---");
var 设备型号 = 执行命令("getprop ro.product.model", false);
var 安卓版本 = 执行命令("getprop ro.build.version.release", false);
var SDK版本 = 执行命令("getprop ro.build.version.sdk", false);
var 制造商 = 执行命令("getprop ro.product.manufacturer", false);
var 序列号 = 执行命令("getprop ro.serialno", false);
print.log("设备型号:" + 设备型号);
print.log("安卓版本:" + 安卓版本);
print.log("SDK版本:" + SDK版本);
print.log("制造商:" + 制造商);
print.log("序列号:" + 序列号);
// 3.2 获取屏幕分辨率
print.log("\n--- 3.2 获取屏幕分辨率 ---");
var 分辨率 = 执行命令("wm size", false);
print.log("屏幕分辨率:" + 分辨率);
var 密度 = 执行命令("wm density", false);
print.log("屏幕密度:" + 密度);
// 3.3 获取电池信息(多策略:sysfs → dumpsys解析 → bms回退)
print.log("\n--- 3.3 获取电池信息 ---");
var 电池信息3 = 获取电池信息();
print.log("电池电量:" + (电池信息3.电量 || "未知") + "%");
print.log("电池状态:" + (电池信息3.状态 || "未知"));
print.log("电池温度:" + (电池信息3.温度 || "未知"));
print.log("电池技术:" + (电池信息3.技术 || "未知"));
// 3.4 获取内存信息
print.log("\n--- 3.4 获取内存信息 ---");
var 内存信息 = 执行命令("cat /proc/meminfo | head -5", false);
print.log("内存信息:\n" + 内存信息);
// 3.5 获取 CPU 信息
print.log("\n--- 3.5 获取 CPU 信息 ---");
var CPU信息 = 执行命令("cat /proc/cpuinfo | head -10", false);
print.log("CPU信息:\n" + CPU信息);
// 3.6 获取存储信息
print.log("\n--- 3.6 获取存储信息 ---");
var 存储信息 = 执行命令("df /sdcard", false);
print.log("存储信息:\n" + 存储信息);
// 3.7 获取网络连接信息
print.log("\n--- 3.7 获取网络信息 ---");
var IP地址 = 执行命令("ip addr show wlan0 | grep 'inet '", false);
print.log("IP地址:" + IP地址);
// WiFi状态:管道grep返回空,改用JS解析 dumpsys wifi 完整输出
var WiFi完整 = 执行命令("dumpsys wifi 2>/dev/null", false);
var WiFi状态 = "未知";
if (WiFi完整 && WiFi完整.length > 0) {
var WiFi行 = WiFi完整.split("\n");
for (var wi = 0; wi < WiFi行.length; wi++) {
var 行内容 = WiFi行[wi].trim().toLowerCase();
if (行内容.indexOf("wi-fi is") !== -1 || 行内容.indexOf("wifi is") !== -1) {
WiFi状态 = WiFi行[wi].trim();
break;
}
}
// 回退:搜索 "Wi-Fi" 关键字所在行
if (WiFi状态 === "未知") {
for (var wi2 = 0; wi2 < WiFi行.length; wi2++) {
if (WiFi行[wi2].toLowerCase().indexOf("wifi") !== -1 && WiFi行[wi2].indexOf("SSID") !== -1) {
WiFi状态 = WiFi行[wi2].trim();
break;
}
}
}
}
print.log("WiFi状态:" + WiFi状态);
// =============================================================================
// 第四部分:输入模拟(Input Commands)
// =============================================================================
倒计时(3, "第四部分:输入模拟");
print.log("\n========== 第四部分:输入模拟 ==========\n");
// 4.1 模拟点击(input tap)
print.log("--- 4.1 模拟点击坐标 ---");
// 执行命令静默("input tap 540 960", false);
print.log("(示例)input tap 540 960 → 点击屏幕中心");
// 4.2 模拟滑动(input swipe)
print.log("\n--- 4.2 模拟滑动 ---");
// 执行命令静默("input swipe 540 1500 540 500 300", false); // 上滑
print.log("(示例)input swipe 540 1500 540 500 300 → 向上滑动");
// 4.3 模拟长按(swipe 起点终点相同,时长 > 500ms)
print.log("\n--- 4.3 模拟长按 ---");
// 执行命令静默("input swipe 540 960 540 960 1000", false);
print.log("(示例)input swipe 540 960 540 960 1000 → 长按 1 秒");
// 4.4 模拟输入文字(仅支持 ASCII)
print.log("\n--- 4.4 模拟输入文字 ---");
// 执行命令静默("input text 'hello123'", false);
print.log("(示例)input text 'hello123' → 输入 ASCII 文字");
// 4.5 模拟按键事件(input keyevent)
print.log("\n--- 4.5 模拟按键事件 ---");
var 按键说明 = {
"3": "KEYCODE_HOME (Home键)",
"4": "KEYCODE_BACK (返回键)",
"24": "KEYCODE_VOLUME_UP (音量加)",
"25": "KEYCODE_VOLUME_DOWN (音量减)",
"26": "KEYCODE_POWER (电源键)",
"27": "KEYCODE_CAMERA (相机键)",
"66": "KEYCODE_ENTER (回车键)",
"82": "KEYCODE_MENU (菜单键)",
"279": "KEYCODE_PASTE (粘贴键)"
};
for (var 键码 in 按键说明) {
// 执行命令静默("input keyevent " + 键码, false);
print.log(" keyevent " + 键码 + " → " + 按键说明[键码]);
}
// 4.6 模拟组合键(Ctrl+V 粘贴)
print.log("\n--- 4.6 模拟组合键 ---");
// 执行命令静默("input keyevent 50 --meta 0x1000", false); // Ctrl+V
print.log("(示例)input keyevent 50 --meta 0x1000 → Ctrl+V 粘贴");
// =============================================================================
// 第五部分:截图与媒体控制
// =============================================================================
倒计时(3, "第五部分:截图与媒体控制");
print.log("\n========== 第五部分:截图与媒体控制 ==========\n");
// 5.1 截图保存到文件
print.log("--- 5.1 截图保存到文件 ---");
var 截图路径 = "/sdcard/aiwrok_test/screenshot_" + Date.now() + ".png";
执行命令静默("screencap -p " + 截图路径, false);
var 截图验证 = 执行命令("ls -l " + 截图路径, false);
print.log("截图文件:" + 截图验证);
// 5.2 截图直接输出到 stdout(用于获取二进制数据)
print.log("\n--- 5.2 截图输出到 stdout ---");
print.log("(示例)screencap -p 可直接输出 PNG 数据流");
// 5.3 录屏(需要 Android 4.4+)
print.log("\n--- 5.3 录屏命令 ---");
print.log("(示例)screenrecord --time-limit 10 /sdcard/aiwrok_test/record.mp4 → 录屏10秒");
// 5.4 媒体音量控制(管道grep返回空,改用JS解析)
print.log("\n--- 5.4 媒体音量控制 ---");
var 音频完整 = 执行命令("dumpsys audio 2>/dev/null", false);
var 音量输出 = "";
if (音频完整 && 音频完整.length > 0) {
var 音频行 = 音频完整.split("\n");
var 音量行 = [];
for (var ai = 0; ai < 音频行.length; ai++) {
if (音频行[ai].indexOf("Stream volume") !== -1 || 音频行[ai].indexOf("STREAM_MUSIC") !== -1) {
音量行.push(音频行[ai].trim());
}
}
音量输出 = 音量行.length > 0 ? 音量行.join("\n") : "未找到音量信息";
} else {
音量输出 = "dumpsys audio 不可用";
}
print.log("当前音频流信息:\n" + 音量输出);
// =============================================================================
// 第六部分:进程管理
// =============================================================================
倒计时(3, "第六部分:进程管理");
print.log("\n========== 第六部分:进程管理 ==========\n");
// 6.1 查看所有运行中的进程
print.log("--- 6.1 查看运行中的进程(前10个)---");
var 进程列表 = 执行命令("ps | head -10", false);
print.log("进程列表:\n" + 进程列表);
// 6.2 查找特定进程
print.log("\n--- 6.2 查找特定进程 ---");
// 注意:Android shell 不支持 grep -P,使用普通 grep
var 微信进程 = 执行命令("ps | grep com.tencent.mm", false);
print.log("微信进程:" + (微信进程 || "微信未运行"));
// 6.3 获取 CPU 占用最高的进程
print.log("\n--- 6.3 CPU 占用最高的进程 ---");
var CPU占用 = 执行命令("top -n 1 -b | head -15", false);
print.log("CPU占用情况:\n" + CPU占用);
// 6.4 杀死进程(需要 root 或同 UID)
print.log("\n--- 6.4 杀死进程 ---");
// 执行命令静默("kill <PID>", true); // 需要 root
print.log("(示例)kill <PID> 以 root 权限杀死指定进程");
// 6.5 获取前台 Activity(管道grep返回空,改用JS解析完整输出)
print.log("\n--- 6.5 获取前台 Activity ---");
// 策略1:dumpsys activity activities 完整输出 + JS搜索 mResumedActivity
var activity完整6 = 执行命令("dumpsys activity activities 2>/dev/null", false);
if (activity完整6 && activity完整6.length > 0) {
var resumedIdx6 = activity完整6.indexOf("mResumedActivity");
if (resumedIdx6 !== -1) {
print.log("前台Activity:" + activity完整6.substring(resumedIdx6, resumedIdx6 + 200).split("\n")[0]);
} else {
print.log("前台Activity:未找到 mResumedActivity");
}
} else {
print.log("前台Activity:dumpsys activity 不可用");
}
// 策略2:dumpsys window 完整输出 + JS搜索 mCurrentFocus
var 窗口完整6 = 执行命令("dumpsys window 2>/dev/null", false);
if (窗口完整6 && 窗口完整6.length > 0) {
var focusIdx6 = 窗口完整6.indexOf("mCurrentFocus");
if (focusIdx6 !== -1) {
print.log("当前焦点窗口:" + 窗口完整6.substring(focusIdx6, focusIdx6 + 200).split("\n")[0]);
} else {
print.log("当前焦点窗口:未找到 mCurrentFocus");
}
} else {
print.log("当前焦点窗口:dumpsys window 不可用");
}
// =============================================================================
// 第七部分:文件权限与系统管理(root 场景)
// =============================================================================
倒计时(3, "第七部分:root权限场景");
print.log("\n========== 第七部分:root 权限场景 ==========\n");
// 7.1 修改文件权限
print.log("--- 7.1 修改文件权限 ---");
// adb.exec("chmod 777 /data/local/tmp/test", true); // root 权限
print.log("(示例)adb.exec('chmod 777 /data/local/tmp/test', true) 以 root 修改权限");
// 7.2 读取系统分区文件(需要 root)
print.log("\n--- 7.2 读取系统分区文件 ---");
// var hosts内容 = 执行命令("cat /etc/hosts", true); // root 权限读取
print.log("(示例)adb.exec('cat /etc/hosts', true) 以 root 读取系统文件");
// 7.3 修改系统设置(settings 命令在 Android 14 非 root 下报权限错误,需 root)
print.log("\n--- 7.3 修改系统设置 ---");
// 获取屏幕超时时间(需 root,否则报 INTERACT_ACROSS_USERS 权限错误)
var 屏幕超时 = 执行命令("settings get system screen_off_timeout", true);
if (!屏幕超时 || 屏幕超时.indexOf("Exception") !== -1 || 屏幕超时.indexOf("Permission") !== -1) {
// 回退1:非root尝试
var 屏幕超时2 = 执行命令("settings get system screen_off_timeout", false);
if (屏幕超时2 && 屏幕超时2.indexOf("Exception") === -1) {
屏幕超时 = 屏幕超时2;
} else {
// 回退2:通过 content query 读取
var content查询 = 执行命令("content query --uri content://settings/system --where \"name='screen_off_timeout'\"", false);
if (content查询 && content查询.indexOf("value=") !== -1) {
var valIdx = content查询.indexOf("value=");
屏幕超时 = content查询.substring(valIdx + 6).split(",")[0].trim();
} else {
屏幕超时 = "";
}
}
}
print.log("当前屏幕超时:" + (屏幕超时 || "获取失败(需 root 权限)") + " 毫秒");
// 修改屏幕超时(需 root)
// 执行命令静默("settings put system screen_off_timeout 60000", true);
print.log("(示例)settings put system screen_off_timeout 60000 → 设置屏幕超时60秒");
// 7.4 获取/修改输入法(需 root)
print.log("\n--- 7.4 获取/修改输入法 ---");
var 当前输入法 = 执行命令("settings get secure default_input_method", true);
if (!当前输入法 || 当前输入法.indexOf("Exception") !== -1 || 当前输入法.indexOf("Permission") !== -1) {
// 回退1:非root尝试
当前输入法 = 执行命令("settings get secure default_input_method", false);
if (!当前输入法 || 当前输入法.indexOf("Exception") !== -1) {
// 回退2:通过 content query 读取
var 输入法查询 = 执行命令("content query --uri content://settings/secure --where \"name='default_input_method'\"", false);
if (输入法查询 && 输入法查询.indexOf("value=") !== -1) {
var imeValIdx = 输入法查询.indexOf("value=");
当前输入法 = 输入法查询.substring(imeValIdx + 6).split(",")[0].trim();
} else {
// 回退3:通过 imba 命令(部分设备可用)
var imba列表 = 执行命令("ime list -s 2>/dev/null", false);
当前输入法 = imba列表 || "";
}
}
}
print.log("当前默认输入法:" + (当前输入法 || "获取失败(需 root 权限)"));
// 7.5 挂载/卸载系统分区(root)
print.log("\n--- 7.5 挂载系统分区读写(root)---");
// adb.exec("mount -o remount,rw /system", true);
print.log("(示例)adb.exec('mount -o remount,rw /system', true) 以 root 重新挂载/system为读写");
// 7.6 写入系统文件(root)
print.log("\n--- 7.6 写入系统 hosts 文件(root)---");
// adb.exec("echo '127.0.0.1 example.com' >> /etc/hosts", true);
print.log("(示例)以 root 权限修改 hosts 文件");
// =============================================================================
// 第八部分:网络操作
// =============================================================================
倒计时(3, "第八部分:网络操作");
print.log("\n========== 第八部分:网络操作 ==========\n");
// 8.1 检查网络连通性
print.log("--- 8.1 Ping 测试 ---");
var ping结果 = 执行命令("ping -c 3 www.baidu.com", false);
print.log("Ping 结果:\n" + ping结果);
// 8.2 获取网络接口信息
print.log("\n--- 8.2 网络接口信息 ---");
var 网络接口 = 执行命令("ip addr", false);
print.log("网络接口:\n" + 网络接口.substring(0, 200) + "...");
// 8.3 获取路由表
print.log("\n--- 8.3 路由表 ---");
var 路由表 = 执行命令("ip route", false);
print.log("路由表:" + 路由表);
// 8.4 获取 DNS 配置(多策略:resolv.conf → getprop → dhcp属性 → dumpsys解析)
print.log("\n--- 8.4 DNS 配置 ---");
var DNS1 = "";
var DNS2 = "";
// 策略1:resolv.conf
var DNS原始 = 执行命令("cat /etc/resolv.conf 2>/dev/null", false);
if (DNS原始 && DNS原始.length > 0) {
var DNS行 = DNS原始.split("\n");
var DNS序号 = 0;
for (var di = 0; di < DNS行.length; di++) {
var 行 = DNS行[di].trim();
if (行.indexOf("nameserver") === 0) {
DNS序号++;
if (DNS序号 === 1) DNS1 = 行.substring("nameserver".length).trim();
else if (DNS序号 === 2) DNS2 = 行.substring("nameserver".length).trim();
}
}
}
// 策略2:getprop net.dns
if (!DNS1) DNS1 = 执行命令("getprop net.dns1 2>/dev/null", false);
if (!DNS2) DNS2 = 执行命令("getprop net.dns2 2>/dev/null", false);
// 策略3:getprop dhcp.wlan0.dns(部分设备可用)
if (!DNS1) DNS1 = 执行命令("getprop dhcp.wlan0.dns1 2>/dev/null", false);
if (!DNS2) DNS2 = 执行命令("getprop dhcp.wlan0.dns2 2>/dev/null", false);
// 策略4:解析 dumpsys connectivity(搜索 DnsServerSearchDomains 或 dns 字样)
if (!DNS1) {
var 连通性完整 = 执行命令("dumpsys connectivity 2>/dev/null", false);
if (连通性完整 && 连通性完整.length > 0) {
var 连通行 = 连通性完整.split("\n");
for (var ci = 0; ci < 连通行.length; ci++) {
var 连接内容 = 连通行[ci].trim();
if (连接内容.indexOf("DnsAddresses") !== -1 || 连接内容.indexOf("dns addresses") !== -1) {
// 尝试提取IP地址格式 x.x.x.x
var ipMatch = 连接内容.match(/\d+\.\d+\.\d+\.\d+/g);
if (ipMatch) {
if (!DNS1) DNS1 = ipMatch[0];
if (ipMatch.length > 1 && !DNS2) DNS2 = ipMatch[1];
}
}
}
}
}
print.log("DNS1:" + (DNS1 || "获取失败"));
print.log("DNS2:" + (DNS2 || "获取失败"));
// 8.5 通过 curl 获取网络数据(部分设备支持)
print.log("\n--- 8.5 curl 获取数据 ---");
var curl结果 = 执行命令("curl -s http://ip-api.com/line/ 2>/dev/null", false);
print.log("网络出口信息:\n" + (curl结果 || "curl 不可用或网络不通"));
// =============================================================================
// 第九部分:UI 自动化辅助(uiautomator)
// =============================================================================
倒计时(3, "第九部分:UI自动化辅助");
print.log("\n========== 第九部分:UI 自动化辅助 ==========\n");
// 9.1 获取 UI XML(多策略:auto.getXml → uiautomator dump → 完整路径)
print.log("--- 9.1 获取当前界面 UI XML ---");
var UI_XML = "";
// 策略1:优先使用 AIWROK 原生 auto.getXml()(最可靠)
try {
if (typeof auto !== "undefined" && auto.getXml) {
var 原始XML = String(auto.getXml());
if (原始XML && 原始XML.length > 10 && 原始XML.indexOf("<") !== -1) {
UI_XML = 原始XML;
print.log("✓ 通过 auto.getXml() 获取成功");
}
}
} catch (e1) {
print.log("⚠ auto.getXml() 失败: " + e1.message);
}
// 策略2:uiautomator dump(如果 auto.getXml 不可用)
if (!UI_XML) {
执行命令静默("mkdir -p /sdcard/aiwrok_test", false);
var UI临时文件 = "/sdcard/aiwrok_test/ui_dump.xml";
// 先尝试 --compressed
var dump结果1 = 执行命令("uiautomator dump --compressed " + UI临时文件 + " 2>&1", false);
sleep.millisecond(500);
UI_XML = 执行命令("cat " + UI临时文件 + " 2>/dev/null", false);
if (UI_XML && UI_XML.length > 10 && UI_XML.indexOf("<") !== -1) {
print.log("✓ 通过 uiautomator --compressed 获取成功");
} else {
// 回退:不带 --compressed
var dump结果2 = 执行命令("uiautomator dump " + UI临时文件 + " 2>&1", false);
sleep.millisecond(500);
UI_XML = 执行命令("cat " + UI临时文件 + " 2>/dev/null", false);
if (UI_XML && UI_XML.length > 10 && UI_XML.indexOf("<") !== -1) {
print.log("✓ 通过 uiautomator dump 获取成功(非压缩模式)");
} else {
// 回退:尝试 /system/bin/ 完整路径
var dump结果3 = 执行命令("/system/bin/uiautomator dump " + UI临时文件 + " 2>&1", false);
sleep.millisecond(500);
UI_XML = 执行命令("cat " + UI临时文件 + " 2>/dev/null", false);
if (UI_XML && UI_XML.length > 10 && UI_XML.indexOf("<") !== -1) {
print.log("✓ 通过 /system/bin/uiautomator 获取成功");
} else {
UI_XML = "";
}
}
}
}
if (UI_XML && UI_XML.length > 10) {
print.log("UI XML 长度:" + UI_XML.length + " 字符");
print.log("UI XML 前200字符:" + UI_XML.substring(0, 200) + "...");
} else {
print.log("⚠ 获取 UI XML 失败(uiautomator 不可用且 auto.getXml 不可用)");
}
// 9.2 获取当前界面包名(多策略:dumpsys window → dumpsys activity → AIWROK原生 → shell)
print.log("\n--- 9.2 获取当前界面包名 ---");
var 前台包名 = "";
var 前台Activity = "";
var activity完整 = "";
// 策略1:dumpsys window 完整输出 + JS搜索 mCurrentFocus
var 窗口完整 = 执行命令("dumpsys window 2>/dev/null", false);
if (窗口完整 && 窗口完整.length > 0) {
var focusIndex = 窗口完整.indexOf("mCurrentFocus");
if (focusIndex !== -1) {
var focusLine = 窗口完整.substring(focusIndex, focusIndex + 200).split("\n")[0];
print.log("焦点窗口:" + focusLine);
var spaceIdx = focusLine.indexOf(" ");
if (spaceIdx !== -1) {
var sub = focusLine.substring(spaceIdx + 1);
var slashIdx = sub.indexOf("/");
if (slashIdx !== -1) {
前台包名 = sub.substring(0, slashIdx);
print.log("当前前台包名:" + 前台包名);
}
}
} else {
// 回退:搜索 mFocusedApp
var appIndex = 窗口完整.indexOf("mFocusedApp");
if (appIndex !== -1) {
var appLine = 窗口完整.substring(appIndex, appIndex + 200).split("\n")[0];
print.log("焦点应用:" + appLine);
var appSlash = appLine.indexOf("/");
if (appSlash !== -1) {
var appSub = appLine.substring(appLine.indexOf(" ") + 1, appSlash);
if (appSub) 前台包名 = appSub;
}
}
}
}
// 策略2:dumpsys activity activities + JS搜索 mResumedActivity
if (!前台包名) {
activity完整 = 执行命令("dumpsys activity activities 2>/dev/null", false);
if (activity完整 && activity完整.length > 0) {
var resumedIdx = activity完整.indexOf("mResumedActivity");
if (resumedIdx !== -1) {
var resumedLine = activity完整.substring(resumedIdx, resumedIdx + 300).split("\n")[0];
print.log("前台Activity:" + resumedLine);
// 提取包名:格式通常为 mResumedActivity: ActivityRecord{... u0 com.xxx.xxx/...}
var 包名提取 = resumedLine.match(/(\w+\.\w+\.\w+)/);
if (包名提取) {
前台包名 = 包名提取[1];
print.log("当前前台包名(从Activity提取):" + 前台包名);
}
}
}
}
// 策略3:AIWROK 原生方法(部分方法不稳定,作为最后回退)
if (!前台包名) {
try {
if (typeof auto !== "undefined") {
if (auto.getTopPackName) 前台包名 = String(auto.getTopPackName());
if (!前台包名 && auto.getTopPackNameV2) 前台包名 = String(auto.getTopPackNameV2());
if (!前台包名 && auto.getPackName) 前台包名 = String(auto.getPackName());
}
} catch (e3) {
print.log("⚠ AIWROK 原生方法获取包名失败: " + e3.message);
}
}
if (!前台包名) {
print.log("⚠ 未获取到前台包名(dumpsys 和 AIWROK 方法均不可用)");
}
// 9.3 获取 Activity 栈
print.log("\n--- 9.3 获取 Activity 栈信息 ---");
// 确保 activity完整 有值(可能在 9.2 策略2 中已获取)
if (!activity完整) {
activity完整 = 执行命令("dumpsys activity activities 2>/dev/null", false);
}
if (activity完整 && activity完整.length > 0) {
// 在 JS 中搜索关键字
var 栈行 = activity完整.split("\n");
var 栈输出 = [];
for (var si = 0; si < 栈行.length; si++) {
if (栈行[si].indexOf("Run #") !== -1 || 栈行[si].indexOf("mResumed") !== -1) {
栈输出.push(栈行[si].trim());
}
}
if (栈输出.length > 0) {
for (var sj = 0; sj < 栈输出.length; sj++) {
print.log(" " + 栈输出[sj]);
}
} else {
// 回退:输出前5行看看格式
print.log("Activity栈:未找到 Run # 信息,输出前5行:");
for (var sk = 0; sk < Math.min(5, 栈行.length); sk++) {
print.log(" " + 栈行[sk].trim());
}
}
} else {
print.log("Activity栈:dumpsys activity 不可用");
}
// =============================================================================
// 第十部分:综合实战 —— 应用信息采集器
// =============================================================================
倒计时(3, "第十部分:应用信息采集器");
print.log("\n========== 第十部分:综合实战:应用信息采集器 ==========\n");
/**
* 综合示例:采集设备上所有第三方应用的详细信息
* 展示 adb.exec 在复杂场景下的组合使用
*/
// 工具函数:获取指定包名的应用详细信息
function 获取应用详情(包名) {
var 详情 = {
包名: 包名,
版本名: "",
版本号: "",
安装路径: "",
数据目录: "",
大小: "",
是否运行: false
};
try {
// 获取完整 package 信息(dumpsys 管道在部分设备返回空,改用 JS 解析)
var 包信息完整 = 执行命令("dumpsys package " + 包名 + " 2>/dev/null", false);
if (包信息完整 && 包信息完整.length > 0) {
// 策略1:搜索 versionName= (标准格式)
var vNameIdx = 包信息完整.indexOf("versionName=");
if (vNameIdx !== -1) {
var vNameSub = 包信息完整.substring(vNameIdx + "versionName=".length);
详情.版本名 = vNameSub.split("\n")[0].trim();
}
// 策略2:搜索 versionName (不带=,部分MIUI/HyperOS格式)
if (!详情.版本名) {
var vNameIdx2 = 包信息完整.indexOf("versionName ");
if (vNameIdx2 !== -1) {
var vNameSub2 = 包信息完整.substring(vNameIdx2 + "versionName ".length);
详情.版本名 = vNameSub2.split("\n")[0].trim();
}
}
// 搜索 versionCode
var vCodeIdx = 包信息完整.indexOf("versionCode=");
if (vCodeIdx !== -1) {
var vCodeSub = 包信息完整.substring(vCodeIdx + "versionCode=".length);
详情.版本号 = vCodeSub.split(" ")[0].trim();
}
if (!详情.版本号) {
var vCodeIdx2 = 包信息完整.indexOf("versionCode ");
if (vCodeIdx2 !== -1) {
var vCodeSub2 = 包信息完整.substring(vCodeIdx2 + "versionCode ".length);
详情.版本号 = vCodeSub2.split(" ")[0].trim();
}
}
}
// 策略3:如果 dumpsys package 未找到,尝试 pm dump
if (!详情.版本名) {
var pmDump = 执行命令("pm dump " + 包名 + " 2>/dev/null", false);
if (pmDump && pmDump.length > 0) {
var pmVNameIdx = pmDump.indexOf("versionName=");
if (pmVNameIdx !== -1) {
详情.版本名 = pmDump.substring(pmVNameIdx + "versionName=".length).split("\n")[0].trim();
}
var pmVCodeIdx = pmDump.indexOf("versionCode=");
if (pmVCodeIdx !== -1) {
详情.版本号 = pmDump.substring(pmVCodeIdx + "versionCode=".length).split(" ")[0].trim();
}
}
}
// 获取安装路径
var 路径信息 = 执行命令("pm path " + 包名, false);
if (路径信息) {
详情.安装路径 = 路径信息.replace("package:", "").trim();
}
// 检查是否正在运行
var 进程检查 = 执行命令("ps | grep " + 包名, false);
详情.是否运行 = !!(进程检查 && 进程检查.length > 0);
} catch (e) {
print.log("⚠ 获取 " + 包名 + " 详情失败: " + e.message);
}
return 详情;
}
// 工具函数:获取设备综合信息
function 获取设备信息() {
var 设备 = {};
try {
设备.型号 = 执行命令("getprop ro.product.model", false);
设备.品牌 = 执行命令("getprop ro.product.brand", false);
设备.安卓版本 = 执行命令("getprop ro.build.version.release", false);
设备.SDK = 执行命令("getprop ro.build.version.sdk", false);
设备.分辨率 = 执行命令("wm size", false);
// 电池信息改用多策略获取函数
var 设备电池 = 获取电池信息();
设备.电量 = 设备电池.电量 ? (设备电池.电量 + "%") : "未知";
设备.总内存 = 执行命令("cat /proc/meminfo | head -1", false);
设备.可用存储 = 执行命令("df /sdcard | tail -1", false);
} catch (e) {
print.log("⚠ 获取设备信息失败: " + e.message);
}
return 设备;
}
// 执行采集
print.log("--- 10.1 采集设备信息 ---");
var 设备信息 = 获取设备信息();
print.log("设备型号:" + 设备信息.型号);
print.log("设备品牌:" + 设备信息.品牌);
print.log("安卓版本:" + 设备信息.安卓版本);
print.log("屏幕分辨率:" + 设备信息.分辨率);
print.log("电量信息:" + 设备信息.电量);
print.log("内存信息:" + 设备信息.总内存);
print.log("\n--- 10.2 采集第三方应用信息(前3个)---");
var 应用列表原始 = 执行命令("pm list packages -3", false);
if (应用列表原始) {
var 应用列表 = 应用列表原始.split("\n");
var 采集数量 = Math.min(3, 应用列表.length);
for (var j = 0; j < 采集数量; j++) {
var 包名 = 应用列表[j].replace("package:", "").trim();
if (包名) {
print.log("\n 应用 " + (j + 1) + ": " + 包名);
var 详情 = 获取应用详情(包名);
print.log(" 版本名: " + 详情.版本名);
print.log(" 版本号: " + 详情.版本号);
print.log(" 安装路径: " + 详情.安装路径);
print.log(" 是否运行: " + (详情.是否运行 ? "是 ✓" : "否"));
}
}
}
// =============================================================================
// 第十一部分:综合实战 —— 系统监控工具
// =============================================================================
倒计时(3, "第十一部分:系统监控工具");
print.log("\n\n========== 第十一部分:综合实战:系统监控工具 ==========\n");
/**
* 综合示例:系统资源监控工具
* 定时采集 CPU、内存、电池、网络等系统指标
*/
// 工具函数:获取 CPU 使用率(top 命令输出格式因设备而异,多策略解析)
function 获取CPU使用率() {
try {
var cpu信息 = 执行命令("top -n 1 -b 2>/dev/null", false);
if (cpu信息) {
var 行数组 = cpu信息.split("\n");
for (var k = 0; k < 行数组.length; k++) {
var 行 = 行数组[k].trim();
// 匹配包含 CPU 和 % 的行(如 "400%cpu 12%user 4%nice 8%sys 376%idle")
if (行.indexOf("cpu") !== -1 && 行.indexOf("%") !== -1 && 行.indexOf("PID") === -1) {
return 行;
}
}
// 如果没找到 CPU 行,返回前3行
return 行数组.slice(0, 3).join("\n");
}
} catch (e) {
print.log("⚠ 获取CPU使用率失败: " + e.message);
}
return "获取失败";
}
// 工具函数:获取内存使用情况
function 获取内存使用() {
try {
var meminfo = 执行命令("cat /proc/meminfo | head -3", false);
return meminfo || "获取失败";
} catch (e) {
return "获取失败: " + e.message;
}
}
// 工具函数:获取电池详细信息(多策略:sysfs文件 → dumpsys解析 → getprop回退)
function 获取电池信息() {
var 电池 = { 电量: "", 温度: "", 状态: "", 技术: "" };
try {
// 策略1:sysfs 文件系统(标准路径)
电池.电量 = 执行命令("cat /sys/class/power_supply/battery/capacity 2>/dev/null", false);
var 温度原始 = 执行命令("cat /sys/class/power_supply/battery/temp 2>/dev/null", false);
if (温度原始) {
var 温度值 = parseInt(温度原始.trim(), 10);
电池.温度 = isNaN(温度值) ? "" : (温度值 / 10) + "°C";
}
var 状态原始 = 执行命令("cat /sys/class/power_supply/battery/status 2>/dev/null", false);
var 状态映射 = {"Charging": "充电中", "Discharging": "放电中", "Full": "已充满", "Not charging": "未充电"};
电池.状态 = 状态映射[状态原始] || 状态原始 || "";
电池.技术 = 执行命令("cat /sys/class/power_supply/battery/technology 2>/dev/null", false);
// 策略2:如果 sysfs 为空,用 dumpsys battery 解析(不用管道grep,直接JS搜索)
if (!电池.电量) {
var dumpsys电池 = 执行命令("dumpsys battery 2>/dev/null", false);
if (dumpsys电池 && dumpsys电池.length > 0) {
var 电池行 = dumpsys电池.split("\n");
for (var bi = 0; bi < 电池行.length; bi++) {
var 行内容 = 电池行[bi].trim();
if (行内容.indexOf("level:") !== -1 && !电池.电量) {
电池.电量 = 行内容.replace("level:", "").trim();
}
if (行内容.indexOf("temperature:") !== -1 && !电池.温度) {
var 温度提取 = parseInt(行内容.replace("temperature:", "").trim(), 10);
电池.温度 = isNaN(温度提取) ? "" : (温度提取 / 10) + "°C";
}
if (行内容.indexOf("status:") !== -1 && !电池.状态) {
var 状态提取 = 行内容.replace("status:", "").trim();
电池.状态 = 状态映射[状态提取] || 状态提取 || "";
}
if (行内容.indexOf("technology:") !== -1 && !电池.技术) {
电池.技术 = 行内容.replace("technology:", "").trim();
}
}
}
}
// 策略3:如果仍为空,尝试 bms 路径(部分高通设备)
if (!电池.电量) {
电池.电量 = 执行命令("cat /sys/class/power_supply/bms/capacity 2>/dev/null", false);
}
} catch (e) {
print.log("⚠ 获取电池信息失败: " + e.message);
}
return 电池;
}
// 工具函数:获取网络流量统计
function 获取网络流量() {
try {
// 获取 wlan0 接口的流量统计
var 流量 = 执行命令("cat /proc/net/dev | grep wlan0", false);
if (流量) {
// /proc/net/dev 格式: " wlan0: rx_bytes rx_packets ... tx_bytes tx_packets ..."
// trim 后 split: 字段[0]="wlan0:" 字段[1]=rx_bytes 字段[2]=rx_packets ... 字段[9]=tx_bytes 字段[10]=tx_packets
var 字段 = 流量.trim().split(/\s+/);
if (字段.length >= 11) {
return {
接收字节: 字段[1],
接收包数: 字段[2],
发送字节: 字段[9],
发送包数: 字段[10]
};
}
}
} catch (e) {
print.log("⚠ 获取网络流量失败: " + e.message);
}
return null;
}
// 执行监控
print.log("--- 11.1 系统资源快照 ---");
print.log("\n[CPU 使用率]");
print.log(" " + 获取CPU使用率());
print.log("\n[内存使用]");
var 内存 = 获取内存使用();
var 内存行 = 内存.split("\n");
for (var p = 0; p < 内存行.length; p++) {
print.log(" " + 内存行[p]);
}
print.log("\n[电池信息]");
var 电池 = 获取电池信息();
print.log(" 电量: " + (电池.电量 || "未知") + "%");
print.log(" 温度: " + (电池.温度 || "未知"));
print.log(" 状态: " + (电池.状态 || "未知"));
print.log(" 电池技术: " + (电池.技术 || "未知"));
print.log("\n[网络流量]");
var 流量 = 获取网络流量();
if (流量) {
print.log(" 接收: " + 流量.接收字节 + " 字节 / " + 流量.接收包数 + " 包");
print.log(" 发送: " + 流量.发送字节 + " 字节 / " + 流量.发送包数 + " 包");
} else {
print.log(" 获取流量信息失败");
}
// =============================================================================
// 第十二部分:综合实战 —— 智能清理工具
// =============================================================================
倒计时(3, "第十二部分:智能清理工具");
print.log("\n\n========== 第十二部分:综合实战:智能清理工具 ==========\n");
/**
* 综合示例:智能清理工具
* 清理缓存、杀死后台进程、释放内存
* 展示 root 和非 root 模式的组合使用
*/
// 工具函数:获取缓存大小
function 获取缓存大小() {
try {
var 缓存信息 = 执行命令("du -sh /sdcard/Android/data/*/cache 2>/dev/null", false);
return 缓存信息 || "无缓存数据";
} catch (e) {
return "获取失败";
}
}
// 工具函数:清理指定应用的缓存
function 清理应用缓存(包名) {
// pm clear 会清除所有数据(包括登录状态),谨慎使用
// 这里使用 root 权限只清缓存目录
var 结果 = 执行命令("rm -rf /sdcard/Android/data/" + 包名 + "/cache/* 2>/dev/null", false);
return 结果;
}
// 工具函数:强制停止所有第三方后台应用
function 停止后台应用() {
var 停止数量 = 0;
try {
var 应用列表 = 执行命令("pm list packages -3", false);
if (应用列表) {
var 应用 = 应用列表.split("\n");
for (var q = 0; q < 应用.length; q++) {
var 包名 = 应用[q].replace("package:", "").trim();
if (包名) {
// 检查是否在运行
var 进程 = 执行命令("ps | grep " + 包名, false);
if (进程 && 进程.length > 0) {
// 强制停止
执行命令静默("am force-stop " + 包名, false);
print.log(" ✓ 已停止: " + 包名);
停止数量++;
}
}
}
}
} catch (e) {
print.log("⚠ 停止后台应用失败: " + e.message);
}
return 停止数量;
}
// 执行清理(演示模式,不实际执行)
print.log("--- 12.1 查看缓存情况 ---");
print.log("缓存信息:\n" + 获取缓存大小());
print.log("\n--- 12.2 清理临时文件 ---");
执行命令静默("rm -rf /sdcard/aiwrok_test/* 2>/dev/null", false);
print.log("✓ 已清理 /sdcard/aiwrok_test/ 临时文件");
print.log("\n--- 12.3 停止后台应用(需要时启用)---");
print.log("(演示模式)实际使用时调用 停止后台应用() 函数");
// 使用 root 模式清空系统缓存(高级操作)
print.log("\n--- 12.4 系统级缓存清理(root)---");
// adb.exec("echo 3 > /proc/sys/vm/drop_caches", true); // root 权限释放内存
print.log("(示例)adb.exec('echo 3 > /proc/sys/vm/drop_caches', true) 以 root 清空系统缓存");
// =============================================================================
// 第十三部分:adb.exec 与 agent.shell 对比与互转
// =============================================================================
倒计时(3, "第十三部分:API对比与互转");
print.log("\n\n========== 第十三部分:adb.exec 与 agent.shell 对比 ==========\n");
print.log("┌─────────────┬────────────────────┬────────────────────┐");
print.log("│ 特性 │ adb.exec() │ agent.shell() │");
print.log("├─────────────┼────────────────────┼────────────────────┤");
print.log("│ 权限控制 │ 第二参数控制 root │ 需要代理模式/root │");
print.log("│ 返回值 │ 需清洗 successMsg │ 相对干净 │");
print.log("│ 适用场景 │ 通用命令执行 │ 代理模式自动化 │");
print.log("│ root 支持 │ isRoot=true 即可 │ 依赖代理模式 │");
print.log("│ 异常处理 │ 需 try-catch │ 需 try-catch │");
print.log("│ 执行模式 │ 设备端直接执行 │ 通过 agent 代理 │");
print.log("└─────────────┴────────────────────┴────────────────────┘");
// 互转示例:统一命令执行接口
print.log("\n--- 统一命令执行接口(自动选择 adb.exec 或 agent.shell)---");
function 智能执行(命令, 需要root) {
var 结果 = "";
try {
// 优先使用 adb.exec
if (typeof adb !== "undefined" && adb.exec) {
var 原始 = adb.exec(命令, 需要root || false);
结果 = 清洗输出(String(原始));
print.log("[adb.exec] " + 命令 + " → " + 结果.substring(0, 50));
}
// 回退到 agent.shell
else if (typeof agent !== "undefined" && agent.shell) {
结果 = String(agent.shell(命令));
print.log("[agent.shell] " + 命令 + " → " + 结果.substring(0, 50));
}
// 回退到 shell.exec
else if (typeof shell !== "undefined" && shell.exec) {
结果 = String(shell.exec(命令));
print.log("[shell.exec] " + 命令 + " → " + 结果.substring(0, 50));
}
else {
print.log("⚠ 无可用的命令执行接口");
}
} catch (e) {
print.log("⚠ 智能执行异常: " + e.message);
}
return 结果;
}
// 测试统一接口
print.log("\n测试统一接口:");
智能执行("getprop ro.product.model", false);
智能执行("ls /sdcard/", false);
// =============================================================================
// 第十四部分:定时任务 —— 周期性系统监控
// =============================================================================
倒计时(3, "第十四部分:定时系统监控");
print.log("\n\n========== 第十四部分:定时系统监控 ==========\n");
/**
* 综合示例:定时监控系统状态并记录日志
* 使用 setInterval 周期性采集系统信息
*/
var 监控次数 = 0;
var 最大监控次数 = 3; // 演示用,实际可设为更大值
function 系统监控任务() {
监控次数++;
print.log("\n--- 第 " + 监控次数 + " 次监控 [" + new Date().toLocaleTimeString() + "] ---");
// 采集 CPU
var cpu = 获取CPU使用率();
print.log(" CPU: " + cpu);
// 采集内存
var mem = 执行命令("cat /proc/meminfo | head -1", false);
print.log(" 内存: " + mem);
// 采集电池
var 电池 = 获取电池信息();
print.log(" 电量: " + (电池.电量 || "?") + "% | 温度: " + (电池.温度 || "?"));
// 采集前台应用(管道grep返回空,改用JS解析dumpsys window完整输出)
var 监控窗口 = 执行命令("dumpsys window 2>/dev/null", false);
if (监控窗口 && 监控窗口.length > 0) {
var focusIdx = 监控窗口.indexOf("mCurrentFocus");
if (focusIdx !== -1) {
var focus行 = 监控窗口.substring(focusIdx, focusIdx + 200).split("\n")[0];
print.log(" 前台: " + focus行);
} else {
// 回退:搜索 mFocusedApp
var appIdx = 监控窗口.indexOf("mFocusedApp");
if (appIdx !== -1) {
var app行 = 监控窗口.substring(appIdx, appIdx + 200).split("\n")[0];
print.log(" 前台: " + app行);
} else {
print.log(" 前台: 未获取到焦点窗口");
}
}
} else {
print.log(" 前台: dumpsys window 不可用");
}
if (监控次数 >= 最大监控次数) {
print.log("\n✓ 监控完成,共执行 " + 监控次数 + " 次");
}
}
// 执行一次监控演示
系统监控任务();
// 实际定时监控(取消注释即可启用)
// setInterval(function() {
// 系统监控任务();
// }, 60000); // 每60秒监控一次
// =============================================================================
// 第十五部分:日志记录系统
// =============================================================================
倒计时(3, "第十五部分:日志记录系统");
print.log("\n\n========== 第十五部分:adb.exec 日志记录系统 ==========\n");
/**
* 综合示例:将 adb.exec 执行结果写入日志文件
* 实现命令执行日志的持久化存储
*/
function 写入日志(内容) {
var 时间戳 = new Date().toISOString();
var 日志行 = "[" + 时间戳 + "] " + 内容 + "\n";
// 使用 echo 追加写入日志文件
执行命令静默("echo '" + 日志行.replace(/'/g, "'\\''") + "' >> /sdcard/aiwrok_test/adb_log.txt", false);
}
function 记录命令执行(命令, 是否root) {
var 开始时间 = Date.now();
var 结果 = 执行命令(命令, 是否root);
var 耗时 = Date.now() - 开始时间;
var 日志内容 = "CMD: " + 命令 + " | ROOT: " + 是否root + " | TIME: " + 耗时 + "ms | RESULT: " + 结果.substring(0, 100);
写入日志(日志内容);
print.log(" 📝 " + 日志内容);
return 结果;
}
print.log("--- 15.1 记录命令执行日志 ---");
// 创建日志目录
执行命令静默("mkdir -p /sdcard/aiwrok_test", false);
// 执行并记录
记录命令执行("getprop ro.product.model", false);
记录命令执行("ls /sdcard/", false);
// 电池信息:不用 grep 管道(返回空),改用多策略获取函数
var 电池日志 = 获取电池信息();
记录命令执行("echo 'battery_level=" + (电池日志.电量 || "unknown") + " temp=" + (电池日志.温度 || "unknown") + "'", false);
print.log("\n--- 15.2 查看日志文件 ---");
var 日志内容 = 执行命令("cat /sdcard/aiwrok_test/adb_log.txt 2>/dev/null", false);
print.log("日志内容:\n" + (日志内容 || "日志为空"));
// =============================================================================
// 总结
// =============================================================================
print.log("\n\n========== 总结 ==========\n");
print.log("adb.exec(command, isRoot) 核心用法:");
print.log(" 1. 基础用法:adb.exec('ls', false) → 非root执行ls命令");
print.log(" 2. root用法:adb.exec('chmod 777 /data/tmp', true) → root执行");
print.log(" 3. 文件操作:ls/cat/cp/mv/rm/mkdir/chmod");
print.log(" 4. 应用管理:pm list/install/uninstall/clear, am start/force-stop");
print.log(" 5. 系统信息:getprop/dumpsys/wm size/df/cat /proc/meminfo");
print.log(" 6. 输入模拟:input tap/swipe/text/keyevent");
print.log(" 7. 截图录屏:screencap/screenrecord");
print.log(" 8. 进程管理:ps/top/kill");
print.log(" 9. 网络操作:ping/ip/curl");
print.log(" 10. UI辅助:uiautomator dump");
print.log("");
print.log("注意事项:");
print.log(" - 返回值为 JSON 格式 {\"errorMsg\":\"\",\"success\":\"内容\"},需提取 success 字段");
print.log(" - Java String 需用 String() 转为 JS 原生字符串再做正则/分割");
print.log(" - 不支持 grep -P,使用普通 grep");
print.log(" - root 模式需设备已 root 或 PC_ADB 连接");
print.log(" - 建议所有调用包裹 try-catch 防止异常");
print.log(" - isRoot=true 时底层通过 su -c 执行,需 root 权限");
print.log("\n✅ adb.exec() 高级用法示例执行完毕");
复制代码
欢迎光临 B2B网络软件 (http://bbs.niubt.cn/)
Powered by Discuz! X3.2