这次我们来看一个用 ADB 调试工具实现的创意小项目。ADB(Android Debug Bridge)是 Android 开发者最熟悉的调试工具之一,通常用于安装应用、抓取日志、执行 Shell 命令。但它的能力远不止于此,通过组合一些 ADB 命令,我们可以实现很多自动化、批处理甚至“好玩”的功能,比如自动截图、批量安装、设备状态监控,甚至是简单的远程控制。
这个项目的核心不是某个具体的软件,而是一种思路:利用 ADB 的命令行特性,结合脚本(如批处理、Python、Shell),将零散的操作串联起来,实现一个定制化的自动化工具。对于开发者、测试人员或喜欢折腾的安卓用户来说,掌握这种思路,可以极大提升效率,解决一些重复性工作。
本文将带你从零开始,理解如何用 ADB 构建一个实用的自动化工具。我们会重点拆解几个典型场景,比如自动备份应用、定时截图、监控设备状态并通知,以及如何将这些功能封装成一个简单的脚本工具。整个过程不依赖复杂的开发环境,只要你的电脑能正常连接安卓设备并运行 ADB 命令即可。
1. 核心能力速览
| 能力项 | 说明 |
|---|---|
| 项目类型 | 基于 ADB 命令的自动化脚本/工具集 |
| 核心依赖 | Android SDK Platform-Tools (adb 工具) |
| 硬件门槛 | 无特殊要求,支持 Windows/macOS/Linux,需 USB 连接安卓设备或开启无线调试 |
| 启动方式 | 命令行直接运行脚本(.bat, .sh, .py) |
| 主要功能 | 设备连接管理、应用安装/卸载、文件推送/拉取、屏幕截图、日志抓取、Shell 命令批量执行、简单状态监控 |
| 是否支持 API | 本身是命令行工具,可通过脚本封装提供类 API 的调用接口 |
| 是否支持批量任务 | 是,ADB 原生支持多设备操作,脚本可轻松实现批量处理 |
| 适合场景 | 安卓应用测试自动化、多设备批量部署、日常效率工具开发、设备状态监控 |
2. 适用场景与使用边界
这个基于 ADB 的自动化方案主要适合以下几类用户:
- 安卓应用开发者/测试人员:用于快速在多台测试设备上安装、卸载应用,抓取崩溃日志,执行 Monkey 测试等。
- 移动设备管理员:需要对一批安卓设备(如企业定制设备、展示机)进行统一的应用部署、配置或文件管理。
- 效率爱好者或极客:希望用脚本自动化一些手机上的重复操作,比如每日自动备份聊天记录截图、定时清理缓存等。
- 安卓系统爱好者:用于探索设备功能、提取系统文件或进行一些非破坏性的调试。
使用边界与重要提醒:
- 合法授权:仅对你拥有完全控制权的设备进行操作。未经授权对他人的设备使用 ADB 可能涉及隐私侵犯甚至违法。
- 数据安全:执行
adb shell rm、adb uninstall等删除命令前务必确认路径和包名,误操作可能导致数据丢失。 - 系统风险:避免对
/system、/vendor等系统分区进行写操作,除非你明确知道后果(通常需要 Root 权限)。不当操作可能使设备变砖。 - 功能限制:ADB 的权限受设备开发者选项和 USB 调试授权限制。部分系统级操作需要设备已获取 Root 权限。
- 非商业工具:本方案是技术实践,稳定性取决于设备状态和 ADB 版本,不适合作为高可用商业产品的核心依赖。
3. 环境准备与前置条件
在开始编写“好玩的东西”之前,你需要一个可用的 ADB 环境。
1. 获取 ADB 工具
- 推荐方式:下载 Android SDK Platform-Tools。
- 访问 Android 开发者网站 下载对应操作系统的包。
- 解压后,你会得到包含
adb.exe(Windows) 或adb(macOS/Linux) 的文件夹。
- 简易方式(Windows):网络上也有独立的 ADB 工具包,但建议从官方渠道获取以保证安全。
2. 配置系统环境变量(可选但推荐)为了能在任何命令行窗口中使用adb命令,建议将其路径加入系统环境变量PATH。
- Windows:将 platform-tools 文件夹的完整路径(如
C:\android\platform-tools)添加到系统属性 -> 高级 -> 环境变量 -> 系统变量 -> Path中。 - macOS/Linux:将 platform-tools 文件夹路径添加到
~/.bashrc或~/.zshrc文件中的PATH变量里,例如export PATH=$PATH:/path/to/platform-tools。 - 验证:打开新的终端/命令提示符,输入
adb version,能显示版本号即表示配置成功。
3. 准备安卓设备
- 在设备的设置 -> 关于手机中,连续点击“版本号”7次,以启用“开发者选项”。
- 进入设置 -> 系统与更新 -> 开发者选项,开启“USB 调试”。
- 使用 USB 数据线连接电脑和设备。首次连接时,设备屏幕上会弹出“允许 USB 调试吗?”的授权对话框,勾选“始终允许”并点击“确定”。
4. 验证连接在电脑终端执行:
adb devices如果看到设备序列号后面显示device(而不是unauthorized),则表示连接成功。
List of devices attached ABCDEFG123456 device4. 安装部署与启动方式
我们的“项目”本质上是一系列脚本,因此没有复杂的安装过程。核心是创建一个项目目录,用来存放你的脚本文件、配置文件以及输入输出素材。
推荐的项目目录结构:
your_adb_project/ ├── scripts/ # 存放各类脚本 │ ├── backup_apps.bat │ ├── auto_screenshot.py │ └── monitor_device.sh ├── config/ # 配置文件(如设备列表、应用包名列表) │ └── app_list.txt ├── inputs/ # 输入文件(如待安装的APK) │ └── my_app.apk ├── outputs/ # 输出文件(截图、日志、备份文件) │ ├── screenshots/ │ └── logs/ └── README.md # 项目说明启动方式:根据脚本类型,在命令行中进入脚本所在目录直接运行即可。
- Windows 批处理 (.bat):双击运行,或在命令提示符中执行
scripts\backup_apps.bat。 - Linux/macOS Shell 脚本 (.sh):需要先赋予执行权限
chmod +x scripts/monitor_device.sh,然后运行./scripts/monitor_device.sh。 - Python 脚本 (.py):确保已安装 Python,然后运行
python scripts/auto_screenshot.py。
5. 功能测试与效果验证
下面我们通过几个具体的“好玩”脚本案例,来验证 ADB 自动化的能力。
5.1 功能一:批量备份已安装应用 (APK)
这个脚本可以一键备份你设备上所有第三方应用到电脑。
脚本示例 (Windows -backup_apps.bat):
@echo off REM 创建备份目录,以当前日期命名 set BACKUP_DIR=outputs\backup_%date:~0,4%%date:~5,2%%date:~8,2% if not exist "%BACKUP_DIR%" mkdir "%BACKUP_DIR%" echo 正在获取应用列表... REM 获取所有第三方应用包名(排除系统应用) adb shell pm list packages -3 > %BACKUP_DIR%\packages.txt echo 开始备份应用... for /f "tokens=2 delims=:" %%i in (%BACKUP_DIR%\packages.txt) do ( set PACKAGE_NAME=%%i REM 去除换行符 set PACKAGE_NAME=!PACKAGE_NAME: =! echo 备份: !PACKAGE_NAME! adb shell pm path !PACKAGE_NAME! > %BACKUP_DIR%\temp_path.txt for /f "tokens=2 delims=:" %%j in (%BACKUP_DIR%\temp_path.txt) do ( set APK_PATH=%%j set APK_PATH=!APK_PATH: =! adb pull !APK_PATH! %BACKUP_DIR%\ ) ) del %BACKUP_DIR%\temp_path.txt echo 备份完成!文件保存在: %BACKUP_DIR% pause操作步骤:
- 将上述代码保存为
backup_apps.bat,放在scripts文件夹。 - 确保设备通过 ADB 连接成功。
- 双击运行
backup_apps.bat。 - 观察命令行窗口,它会列出正在备份的每一个应用包名。
预期结果与验证:
- 成功:脚本运行完毕后,会在
outputs文件夹下生成一个类似backup_20231027的目录,里面包含所有备份的.apk文件和一个packages.txt列表。 - 失败排查:
- 如果脚本一闪而过,可能是 ADB 环境变量未配置。请在脚本开头添加
cd /d “你的platform-tools绝对路径”,或直接在platform-tools目录下运行脚本。 - 如果备份文件为空,检查
adb shell pm list packages -3命令是否正常输出包名。可能需要在设备上再次确认 USB 调试授权。
- 如果脚本一闪而过,可能是 ADB 环境变量未配置。请在脚本开头添加
5.2 功能二:自动定时截图并传回电脑
这个 Python 脚本可以每隔一段时间自动截图,并保存到电脑指定文件夹。
脚本示例 (Python -auto_screenshot.py):
import os import time import subprocess from datetime import datetime # 配置 SCREENSHOT_INTERVAL = 5 # 截图间隔(秒) OUTPUT_DIR = "outputs/screenshots" os.makedirs(OUTPUT_DIR, exist_ok=True) def take_screenshot(): """使用adb截图并拉取到电脑""" timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") device_file = f"/sdcard/screenshot_{timestamp}.png" local_file = os.path.join(OUTPUT_DIR, f"screenshot_{timestamp}.png") # 在设备上截图 subprocess.run(["adb", "shell", "screencap", "-p", device_file], check=True) # 将截图文件拉取到电脑 subprocess.run(["adb", "pull", device_file, local_file], check=True) # (可选)删除设备上的临时文件 subprocess.run(["adb", "shell", "rm", device_file], check=True) print(f"[{datetime.now().strftime('%H:%M:%S')}] 截图已保存: {local_file}") return local_file if __name__ == "__main__": print(f"开始自动截图,间隔 {SCREENSHOT_INTERVAL} 秒。按 Ctrl+C 停止。") try: while True: take_screenshot() time.sleep(SCREENSHOT_INTERVAL) except KeyboardInterrupt: print("\n自动截图已停止。") except subprocess.CalledProcessError as e: print(f"ADB命令执行失败: {e}") print("请检查设备连接和授权。")操作步骤:
- 确保电脑已安装 Python。
- 将代码保存为
auto_screenshot.py。 - 在命令行中运行
python auto_screenshot.py。 - 脚本会开始每隔5秒截图一次。
预期结果与验证:
- 成功:在
outputs/screenshots目录下会不断生成以时间戳命名的 PNG 截图文件。 - 失败排查:
- 如果提示
adb不是内部或外部命令,请确保 ADB 在系统 PATH 中,或在脚本中使用adb的绝对路径。 - 如果截图失败,检查设备屏幕是否解锁,以及
/sdcard/目录是否有写入权限。
- 如果提示
5.3 功能三:简易设备状态监控(CPU/内存)
这个脚本可以定期检查设备的 CPU 和内存使用情况,并在资源占用过高时给出提示。
脚本示例 (Shell -monitor_device.sh):
#!/bin/bash # 设备状态监控脚本 OUTPUT_LOG="outputs/device_status.log" INTERVAL=2 # 监控间隔(秒) HIGH_CPU_THRESHOLD=80 # CPU告警阈值(%) HIGH_MEM_THRESHOLD=90 # 内存告警阈值(%) echo "开始监控设备状态,日志将保存至 $OUTPUT_LOG" echo "时间戳,CPU占用(%),内存占用(%),状态" > $OUTPUT_LOG while true; do TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') # 获取CPU占用(取一个核心的瞬时值,这里使用top命令) CPU_USAGE=$(adb shell "top -bn1 | grep -E '^\s*[0-9]+' | head -1 | awk '{print \$9}'" | tr -d '\r') # 获取内存占用(使用proc/meminfo) MEM_INFO=$(adb shell "cat /proc/meminfo | grep -E 'MemTotal|MemAvailable'") MEM_TOTAL=$(echo "$MEM_INFO" | grep MemTotal | awk '{print $2}') MEM_AVAIL=$(echo "$MEM_INFO" | grep MemAvailable | awk '{print $2}') if [ -z "$MEM_TOTAL" ] || [ -z "$MEM_AVAIL" ]; then MEM_PERCENT="N/A" else MEM_USED=$((MEM_TOTAL - MEM_AVAIL)) MEM_PERCENT=$((MEM_USED * 100 / MEM_TOTAL)) fi STATUS="Normal" # 告警判断 if [ "$CPU_USAGE" != "N/A" ] && [ "$CPU_USAGE" -gt "$HIGH_CPU_THRESHOLD" ]; then STATUS="High CPU!" echo "[$TIMESTAMP] 警告:CPU占用过高!当前: ${CPU_USAGE}%" >&2 fi if [ "$MEM_PERCENT" != "N/A" ] && [ "$MEM_PERCENT" -gt "$HIGH_MEM_THRESHOLD" ]; then STATUS="High Memory!" echo "[$TIMESTAMP] 警告:内存占用过高!当前: ${MEM_PERCENT}%" >&2 fi # 写入日志 echo "$TIMESTAMP,$CPU_USAGE,$MEM_PERCENT,$STATUS" >> $OUTPUT_LOG sleep $INTERVAL done操作步骤:
- 将代码保存为
monitor_device.sh。 - 赋予执行权限:
chmod +x monitor_device.sh。 - 运行脚本:
./monitor_device.sh。 - 观察终端输出,同时日志会记录到
outputs/device_status.log文件。
预期结果与验证:
- 成功:脚本持续运行,在终端输出时间戳和状态,并将数据记录到 CSV 格式的日志文件中。当 CPU 或内存超过阈值时,终端会显示警告信息。
- 失败排查:
- 如果
top或cat /proc/meminfo命令无输出,可能是设备权限问题。部分定制系统可能限制了这些命令。可以尝试其他命令如adb shell dumpsys cpuinfo | grep TOTAL。 - 如果数值异常,请注意不同安卓版本和硬件,获取系统资源使用情况的方法可能有差异,脚本可能需要调整。
- 如果
6. 接口 API 与批量任务
虽然 ADB 本身是命令行工具,但我们可以通过脚本将其封装成更友好的接口,并轻松实现批量任务。
1. 封装为简单的 HTTP API 服务你可以使用 Python 的 Flask 或 FastAPI 框架,将 ADB 操作包装成 HTTP 接口,方便其他程序调用。
# 示例:简易的 Flask ADB API 服务 (api_server.py) from flask import Flask, request, jsonify import subprocess import threading app = Flask(__name__) def run_adb_command(cmd_args): """安全执行ADB命令""" try: result = subprocess.run(['adb'] + cmd_args, capture_output=True, text=True, timeout=10) return { "returncode": result.returncode, "stdout": result.stdout, "stderr": result.stderr } except subprocess.TimeoutExpired: return {"error": "Command timeout"} except Exception as e: return {"error": str(e)} @app.route('/api/devices', methods=['GET']) def get_devices(): """获取已连接设备列表""" result = run_adb_command(['devices']) # 简单处理输出,提取设备ID devices = [] for line in result.get('stdout', '').splitlines()[1:]: if line.strip() and 'device' in line: dev_id = line.split('\t')[0] devices.append(dev_id) return jsonify({"devices": devices}) @app.route('/api/screenshot', methods=['POST']) def take_screenshot(): """触发截图并返回文件路径""" import time filename = f"screenshot_{int(time.time())}.png" device_path = f"/sdcard/{filename}" local_path = f"./outputs/{filename}" # 执行截图和拉取 cap_result = run_adb_command(['shell', 'screencap', '-p', device_path]) if cap_result.get('returncode') != 0: return jsonify({"success": False, "error": cap_result.get('stderr')}), 500 pull_result = run_adb_command(['pull', device_path, local_path]) if pull_result.get('returncode') != 0: return jsonify({"success": False, "error": pull_result.get('stderr')}), 500 # 清理设备端文件 run_adb_command(['shell', 'rm', device_path]) return jsonify({"success": True, "file_path": local_path}) if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, debug=False)启动服务后,就可以通过curl http://127.0.0.1:5000/api/screenshot或 Postman 来远程触发截图了。
2. 实现多设备批量任务ADB 原生支持-s <设备序列号>来指定对哪台设备操作。利用这一点,可以轻松编写批量脚本。
#!/bin/bash # batch_install.sh - 在多台设备上批量安装APK APK_FILE="inputs/my_app.apk" DEVICE_LIST=("device_serial_1" "device_serial_2") # 替换为你的设备序列号 for DEVICE in "${DEVICE_LIST[@]}"; do echo "正在处理设备: $DEVICE" # 检查设备是否在线 if adb -s $DEVICE get-state &>/dev/null; then echo " 安装APK..." adb -s $DEVICE install -r "$APK_FILE" if [ $? -eq 0 ]; then echo " 安装成功!" else echo " 安装失败。" fi else echo " 设备 $DEVICE 未连接或未授权。" fi echo "---" done先通过adb devices获取所有设备的序列号,填入数组,运行脚本即可实现批量部署。
7. 资源占用与性能观察
基于 ADB 的脚本工具本身资源占用极低,主要消耗在于:
- ADB 守护进程 (adb server):在电脑后台运行,占用少量内存(通常几十MB)。
- 脚本解释器:运行 Python 或 Shell 解释器会占用一定的 CPU 和内存,但对于简单的命令循环来说微不足道。
- 设备端影响:执行
screencap、top等命令时,会在设备上启动相应进程,可能瞬时增加 CPU 负载。频繁操作(如每秒截图)可能导致设备发热或耗电增加。
性能观察建议:
- 电脑端:可以通过任务管理器(Windows)或
top/htop(Linux/macOS)观察adb和你的脚本进程的资源使用情况。 - 设备端:可以使用
adb shell top来监控设备在执行 ADB 命令时的实时资源消耗。 - 优化方向:
- 降低频率:对于监控类脚本,适当增加间隔时间(如从1秒改为5秒)。
- 命令优化:使用更高效的命令组合。例如,获取内存信息,
adb shell dumpsys meminfo可能比解析/proc/meminfo更准确,但输出内容更多,需要权衡。 - 避免阻塞:在脚本中为
subprocess.run设置合理的timeout参数,防止某个 ADB 命令卡死导致整个脚本僵住。
8. 常见问题与排查方法
在玩转 ADB 自动化时,你可能会遇到以下典型问题:
| 问题现象 | 可能原因 | 排查方式 | 解决方案 |
|---|---|---|---|
adb devices显示unauthorized | 设备未授权电脑的 USB 调试请求。 | 查看设备屏幕是否有授权弹窗。 | 在设备上点击“允许”。如果之前拒绝了,可能需要重启 adb server (adb kill-server&&adb start-server) 或设备上的 USB 调试开关。 |
adb devices无设备或显示offline | 1. 数据线或 USB 口问题。 2. 驱动未安装(Windows)。 3. 设备未开启 USB 调试。 | 1. 换线换口。 2. 检查设备管理器是否有未知设备。 3. 确认开发者选项和 USB 调试已开启。 | 1. 使用原装数据线。 2. 安装对应品牌的 USB 驱动或通用 ADB 驱动。 3. 重新开关 USB 调试。 |
adb不是内部或外部命令 | ADB 可执行文件路径未加入系统环境变量 PATH。 | 在命令行输入adb,看是否提示找不到命令。 | 将platform-tools目录的绝对路径添加到系统环境变量 PATH 中。或在脚本中使用 ADB 的绝对路径。 |
执行adb shell某些命令提示Permission denied | 命令需要 Root 权限,但设备未 Root。 | 尝试执行adb root,看是否成功。 | 对于非 Root 设备,避免访问需要高权限的路径(如/system)。寻找替代方案或使用run-as命令在应用沙盒内操作。 |
| 脚本执行截图等命令非常慢 | 可能是使用了旧的screencap方法或网络连接(无线 ADB)不稳定。 | 检查是 USB 连接还是无线连接。 | 1. 优先使用 USB 连接。 2. 对于截图,可以尝试 adb exec-out screencap -p > screenshot.png,它不生成设备临时文件,速度更快。 |
| 批量操作时,部分设备失败 | 多设备环境下未指定设备序列号,命令默认发给了第一个设备。 | 在命令中明确使用-s <序列号>指定目标设备。 | 在脚本中循环设备列表,并对每个设备使用adb -s <序列号> <命令>。 |
| 无线 ADB 连接后经常断开 | 设备或电脑网络不稳定,或进入休眠。 | adb devices查看设备状态是否频繁变为offline。 | 1. 保持设备屏幕常亮(开发者选项中有“保持唤醒”设置)。 2. 使用更稳定的网络环境。 3. 编写重连逻辑,在脚本中检测到断开时自动执行 adb connect <IP:端口>。 |
9. 最佳实践与使用建议
为了让你的 ADB 自动化项目更稳定、更安全,遵循以下建议:
- 从简单开始,逐步复杂:先验证单个 ADB 命令在命令行中能否成功,再将其写入脚本。先实现核心功能,再添加错误处理和日志。
- 异常处理与日志记录:脚本中一定要对
subprocess.run或命令执行结果进行判断(检查returncode)。将所有操作、成功/失败信息写入日志文件,便于后期排查。 - 设备连接稳定性:对于需要长时间运行的监控脚本,增加连接状态检查。如果检测到设备断开,可以尝试自动重连或暂停任务并报警。
- 资源清理:像
screencap这类在设备上生成临时文件的操作,完成后尽量使用adb shell rm清理,避免占用设备存储空间。 - 配置与代码分离:将设备序列号、IP地址、监控阈值、文件路径等配置信息提取到单独的配置文件(如
config.ini或settings.json)中,而不是硬编码在脚本里。 - 安全第一:涉及
adb shell rm、adb uninstall等破坏性操作的脚本,在执行前可以增加二次确认,或者先执行一次“模拟运行”(dry-run),只打印将要执行的命令而不实际执行。 - 版本兼容性:不同安卓版本、不同厂商定制的系统,其 ADB Shell 命令的输出格式、可用命令可能有差异。在脚本中处理命令输出时,要有一定的容错性,或针对不同系统编写适配逻辑。
- 用于生产环境前充分测试:在重要的设备上运行脚本前,务必在测试机上完整跑通所有流程。特别是批量操作,避免因脚本错误导致大规模设备出现问题。
10. 总结与下一步
通过本文的探索,你会发现 ADB 不仅仅是一个调试桥梁,更是一个强大的自动化控制接口。将零散的 ADB 命令通过脚本组织起来,就能创造出各种提升效率的“好玩的东西”,从简单的备份工具到复杂的设备监控系统。
最值得尝试的起点:建议从“批量备份应用”或“自动定时截图”脚本开始。这两个场景需求明确,命令简单,能让你快速获得成就感,并理解 ADB 命令执行、文件传输和设备交互的基本流程。
最容易踩的坑:设备连接和授权是新手的第一道关卡。务必确保adb devices能稳定列出设备且状态为device。路径和权限是第二道关,在设备上操作文件时,优先使用/sdcard/或应用私有目录,避免因权限问题失败。
后续扩展方向:
- 与 GUI 结合:使用 Python 的 Tkinter、PyQt 或 Web 框架为你的脚本制作一个图形界面,让非命令行用户也能方便使用。
- 集成到 CI/CD:将 ADB 自动化脚本集成到 Jenkins、GitLab CI 等持续集成平台,实现应用打包后自动安装到测试机并运行测试用例。
- 探索更多 ADB 命令:
adb shell input(模拟点击、滑动、输入)、adb logcat(抓取日志)、adb backup/restore(备份恢复)、adb shell am/pm(管理 Activity 和包)等,每一个命令背后都是一个可自动化的场景。 - 设备集群管理:如果你有大量安卓设备(如测试实验室),可以开发一个集中管理平台,通过 ADB 统一控制所有设备的状态、应用部署和任务执行。
掌握 ADB 自动化,相当于为你打开了一扇高效管理安卓设备的大门。从今天写下的第一个脚本开始,逐步构建你的工具库,你会发现很多重复、繁琐的工作都能交给电脑自动完成。