adb截图-------在小程序中实现纯 JS 驱动的 ADB 客户端
这个文章是用来记录下技术原理。前段时间总是被产品纠正截电视机的图截了100多张虽然现在有ai但是也是要一张张的截图人都截图截傻了还耽误时间本来有app可以截图但是产品手机又是ios手机我就想着能不能做个小程序经过我一个晚上的问ai做测试终于把他给做成了小程序名字叫“安卓5555工具箱”以后截图的事产品也可以自己做了。传统的 ADB 工作流通常是这样的开发者在电脑端执行 adb shell 系统中的 adb.exe (C/C 编写) 通过 USB 或局域网 TCP连接到手机的 adbd 守护进程从而进行设备认证与通信。但在小程序中没有任何底层的可执行文件。要在小程序这种纯 JavaScript 容器中运行原生 ADB引擎其核心技术实现可以拆解为以下三个关键层底层通信层突破网络限制 (TCP Socket)ADB 协议本质上是在网络层或 USB 传输层上收发二进制数据包。由于小程序环境无法直接调用系统的 USB接口但最新的微信小程序基础库开放了一个关键能力——原生TCP Socket ( wx.createTCPSocket )。Android 手机开启“无线调试”或“网络 ADB”后会在本地开启一个 TCP 端口通常是5555这也是工具箱名字的由来。我们只需要在小程序中调用原生的 Socket API 即可建立物理通道// 1. 创建小程序的 TCP 实例 const socket wx.createTCPSocket(); // 2. 发起连接直连 Android 手机的 5555 端口 socket.connect({ address: 192.168.1.100, // 手机的局域网 IP port: 5555 });这一步直接绕过了需要依托 PC 机做网络转发的限制实现了移动设备到 Android 手机的端到端直连。数据流封装层拥抱 Web 规范 (Web Streams)仅仅拥有 TCP 连接还不够小程序的 Socket API 是基于事件回调机制的如 onMessage。但现代化的前端协议处理库往往依赖于标准的流式读写接口。为此项目在底层设计了一个适配器将非标准的 TCP 读写事件强行包装成了 Web 标准的 ReadableStream 和 WritableStream核心代码逻辑如下// 将 TCP 接收事件转换为 ReadableStream const readable new ReadableStreamUint8Array({ start(controller) { socket.onMessage((res) { // 当 TCP 收到数据将其转为 Uint8Array 并压入流中 const chunk new Uint8Array(res.message); controller.enqueue(chunk); }); } }); // 将 TCP 发送事件封装为 WritableStream const writable new WritableStreamUint8Array({ write(chunk) { // 当协议库向流中写入数据时通过 TCP 发送给目标手机 socket.write(chunk.buffer); } }); // 最终将它们暴露给上层 return { readable, writable }经过这一层的转换小程序特有的网络 API 就具备了标准的流式 I/O 能力为后续接入上层协议库铺平了道路。协议解析层引入 WebADB 核心引擎通信打通了数据流也标准化了接下来面临的最难问题是如何让 JavaScript 理解复杂的 ADB 加密握手协议和指令集“安卓5555工具箱”引入了开源界著名的 WebADB 协议库NPM 包 yume-chan/adb 。WebADB 原本是用纯 TypeScript重写来服务于浏览器 WebUSB API 的而工具箱将其进行了创造性的“嫁接”。它跳过了 WebADB 默认的 WebUSB 传输层直接将上面封装好的 TCP 数据流注入到 WebADB 的核心解析器中import { Adb, AdbDaemonTransport } from yume-chan/adb; // 1. 拿到封装好的 TCP Stream (包含 readable 和 writable) const connection await tcpDevice.connect(); // 2. 注入 WebADB 进行协议认证处理复杂的 RSA 握手 const transport await AdbDaemonTransport.authenticate({ serial: tcpDevice.serial, connection: connection, // 管理连接密钥首次连接设备时屏幕会弹窗请求授权 credentialStore: new CustomLocalStorageCredentialManager(adb-credentials), }); // 3. 认证成功获得最终的纯 JS adb 实例 const adb new Adb(transport); // // 接下来即可通过 JS API 控制 Android 设备 // // 示例执行一条 shell 命令 const output await adb.subprocess.noneProtocol.spawnWaitText(ls -l); console.log(文件夹内容, output); // 示例获取手机型号 const model await adb.getProp(ro.product.model); console.log(手机型号, model);前端展现层 (Taro React)底层通信与协议解析彻底走通后最后一步就是 UI 交互的呈现。项目采用了 Taro 框架结合 React 语法将 WebADB解析出的底层数据如系统属性、应用列表、命令行的输出流等直接映射到组件状态上。当你点击界面上的“卸载应用”按钮时本质上就是触发了 adb 实例的一条指令。总结小程序之所以能够成立核心在于串联了三项关键技术微信 TCP Socket提供底层物理通道 ➡️ Web Streams API提供标准化数据接口 ➡️ WebADB 协议库提供 ADB协议解析能力。它在没有原生 C 模块介入的情况下利用纯 JavaScript 构建了硬核的系统级调试能力。这不仅是对 Web技术边界的一次极佳探索也向我们展示了优秀的底层开源协议库在不同容器环境中强大的复用潜力。