做移动端自动化这行,如果有人问我第一个必须吃透的工具是什么,我十有八九会回答adb。这玩意儿听起来像个命令行小工具,但它几乎贯穿了自动化脚本的整个生命周期:连接设备、模拟点击、安装应用、抓取日志、监控状态,样样都离不开它。我刚入行时第一次在终端敲下adb shell input tap 540 960,手机屏幕像被一只看不见的手戳了一下——那一刻我就意识到,这不只是一个调试工具,它是自动化脚本的万能钥匙。这篇文章我会从实际使用的角度出发,把adb自动化脚本从环境搭建、命令拆解到多设备并发、常见坑位一次讲清楚,适合刚接触自动化的测试新手,也适合想用脚本解放双手的普通开发者。
1. ADB自动化脚本的设计与整体思路
1.1 ADB到底解决了什么问题
先说个最直观的场景:你手里有台安卓手机,想自动完成“打开应用→点击某个按钮→滑动页面→截图”这一连串操作。如果全靠人肉点,一次两次还行,次数多了不仅浪费时间,还容易点错。而adb给了我们一条从电脑直接指挥手机的通道,通过它发出的命令可以控制手机的触控、按键、应用启动、数据读取等方方面面。
换句话说,adb就是PC和Android设备之间的“遥控器总线”。它不是某个App里的功能,而是安卓系统自带的调试工具,地位相当于Linux里的shell。自动化脚本想要“可编程地操作手机”,底层几乎绕不开adb,这也是为什么很多自动化框架在运行前都要先检查adb devices能不能正常识别设备。
在实际项目中,我用adb自动化脚本解决过不少实际问题:
- 每天定时清理手机后台进程和缓存文件,模拟用户操作释放内存;
- 批量给几十台测试机安装同一款App,省去手动一个个拖拽安装;
- 自动跑一轮App启动耗时测试,连续冷启动20次记录时间;
- 无人值守时抓取崩溃日志,把
logcat输出保存成文件供后续分析; - 用脚本模拟用户滑动、点击、截图,做简单的冒烟测试。
你会发现这些场景有一些共同点:操作重复、量大、需要稳定执行、最好不动手。这正是adb自动化脚本最擅长的领域。
1.2 为什么选ADB而不是其他方案
很多刚接触自动化的朋友会纠结:现在有Appium、Airtest、Auto.js这么多工具,为什么还要专门学adb?我的观点是:adb是地基,其他工具是盖在上面的房子。
Appium这样的框架确实能精确定位控件,而且跨平台,但它的底层驱动Android的部分仍然是依赖adb去安装和启动应用,再通过UiAutomator等机制做控件解析。Airtest确实能用图像识别来点击,但它脱离不了adb来连接设备。Auto.js这类手机端脚本工具确实方便,但它需要在手机上安装App并授予无障碍权限,对部分设备和系统版本有兼容问题。
如果你只是快速做一个脚本,或者做一些框架覆盖不到的底层操作,直接敲adb是最直接、最轻量的方式。比起动辄几百MB的自动化框架,adb工具包本身只有几MB,不需要在手机上装额外的服务端,只要开了USB调试就能连,几乎没有环境依赖。
给个选型参考:
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| adb原始命令 | 连接管理、模拟点击、应用操作、日志抓取 | 轻量、稳定、可用shell脚本直接控制 | 无法直接获取控件层级,依赖坐标或命令 |
| Appium | 跨端UI自动化、复杂断言 | 支持控件定位、多语言编写 | 环境重、启动慢、学习曲线陡 |
| Airtest | 游戏自动化、图像识别 | 可视化脚本、适合游戏场景 | 图像识别受分辨率影响较大 |
| Auto.js | 手机端脚本 | 无需电脑、直接在手机运行 | 无障碍权限限制、部分系统可能封禁 |
所以我的建议是:先把adb学扎实,再根据项目需要去扩展框架。遇到框架失灵的时候,回头看adb命令往往是排查问题的突破口。
1.3 环境搭建:从零到能跑通第一行命令
这部分看着基础,但很多坑都藏在这里。先说Windows下的配置方法,Mac和Linux相对简单。
第一步,下载adb工具。一般不需要装完整版Android Studio,直接下载platform-tools就可以,里面包含了adb、fastboot等常用工具。解压后放到一个固定目录,比如D:\platform-tools。
第二步,配置环境变量。右键“此电脑” → 属性 → 高级系统设置 → 环境变量,在“系统变量”里找到Path,把D:\platform-tools追加进去。配置好后重新开一个命令行窗口,输入adb version,如果输出版本信息就说明配置成功。
第三步,手机打开开发者选项。一般是在“关于手机”里连续点击“版本号”7次,然后在设置里找到“开发者选项”,打开“USB调试”。不同品牌的入口位置可能不太一样,但基本都在设置里搜“开发者选项”就能找到。
第四步,连接手机。用数据线把手机连到电脑,首次连接时手机会弹窗询问“是否允许USB调试”,勾选“始终允许”并确认。然后在电脑终端输入adb devices,看到类似下面这样的输出就说明连接成功:
List of devices attached R58M1234567 device如果显示unauthorized,说明手机上没点授权弹窗,重新插拔数据线或执行adb kill-server再adb start-server后重试即可。
我还遇到过没有数据线的情况,其实adb也支持无线连接。只要手机和电脑在同一局域网,先用数据线连接一次,执行adb tcpip 5555,然后拔掉线,再执行adb connect 192.168.x.x:5555,就能走WiFi调试了。这种方式在做长时间自动化任务时特别实用,不用一直挂着数据线。
2. 核心命令与脚本化的关键细节
2.1 连接管理:一切脚本的前提
自动化脚本第一步就是确保设备在线,所以连接管理命令必须滚瓜烂熟。
adb devices是最常用的,它列出当前连接的所有设备状态。常见状态有三种:device表示正常连接,unauthorized表示未授权,offline表示设备离线。写脚本时我习惯先做一次连接检查,设备不在线就直接退出,避免后面命令全部报错。
adb -s <序列号> shell可以指定某台设备执行命令,这在多设备场景下至关重要。比如你有两台手机,不指定序列号时adb会报错说“more than one device”,只有用-s指定目标设备才能精确操作。
日常维护中还可能需要重启adb服务。设备长时间连接后偶尔会变得迟钝,执行adb kill-server再adb start-server往往能解决。注意这两个命令会中断当前所有adb连接,别在自动化跑到一半的时候手痒乱敲。
2.2 高频操作命令盘点
我这里整理了一份脚本中经常用到的adb命令清单,每条都标注了用途,方便你随时查阅。
adb shell pm list packages:列出已安装应用包名,经常用于检查目标应用是否安装。adb shell pm list packages -3:只显示第三方安装的应用,区分系统应用很方便。adb shell am start -n <包名>/<Activity名>:启动指定应用的指定界面。获取Activity名可以先执行adb shell dumpsys window | grep mCurrentFocus,从当前前台窗口看出来。adb shell am force-stop <包名>:强制停止应用,相当于手动划掉后台任务。adb shell input tap <x> <y>:模拟点击屏幕上坐标点。adb shell input swipe <x1> <y1> <x2> <y2> <时长ms>:模拟从起点滑动到终点。adb shell input text <内容>:向输入框填入文本,注意不能直接输入中文。adb shell screencap -p /sdcard/screen.png:截图并保存到设备,再配合adb pull拉到电脑。adb shell screenrecord /sdcard/demo.mp4:录屏,用于记录自动化执行过程。adb logcat -c:清空日志缓冲区;adb logcat > log.txt:把日志输出到本地文件。adb shell dumpsys meminfo <包名>:查看应用内存占用。adb shell dumpsys batterystats --enable full-wake-history:开启电池和唤醒历史的详细统计,之后可以导出分析设备耗电情况。adb install -r <apk路径>:覆盖安装应用,相当于保留数据的重新安装。
这些命令看着零散,但组合起来能实现非常强大的自动化流程。比如我要做一个“自动启动应用并截图”的脚本,只需要三行命令:am start启动,screencap截图,pull拉取。逻辑简单可靠。
2.3 坐标体系:为什么你的点击总是不准
很多人在写模拟点击脚本时都会遇到一个问题:为什么我明明算好了坐标,脚本点下去却不对?这就要理解Android的坐标体系。
adb shell input tap使用的是屏幕的绝对像素坐标,原点在屏幕左上角,x轴向右,y轴向下。不同设备的分辨率和DPI不同,同样一个逻辑位置在1080x1920和1440x3200上的像素坐标完全不一样。
所以我建议在写坐标点击脚本前,先执行adb shell wm size看看分辨率,执行adb shell wm density看DPI。如果脚本要适配多种设备,最好把坐标都写成一个相对比例,而不是写死绝对像素。比如把点击位置表达成“屏幕宽度的50%,屏幕高度的30%”,然后在代码里根据实际分辨率动态计算。
另外还要注意横竖屏切换对坐标的影响。横屏时坐标轴也会旋转,我踩过一次坑:在竖屏下算好的坐标,切到横屏后点到了完全无关的区域。解决方案是脚本执行前先判断当前屏幕方向,或者强制应用保持竖屏。
3. 实操记录:从单条命令到完整自动化脚本
3.1 第一个脚本:定时清理后台应用
直接写命令叫“用adb”,但真正能被称作“自动化脚本”的,是把它写成可在任意时间重复执行的一组逻辑。我先分享一个我自己常用的清理脚本,逻辑很简单:启动脚本后,先检查设备连接状态,然后依次强制停止指定的应用包名。
假设我们要清理微信、支付宝和某个游戏应用,可以写一个shell脚本(Linux/macOS或Windows的Git Bash环境都能跑):
#!/bin/bash adb devices | grep -w "device" > /dev/null if [ $? -ne 0 ]; then echo "设备未连接,请检查adb devices输出" exit 1 fi packages=( "com.tencent.mm" "com.eg.android.AlipayGphone" "com.tencent.tmgp.somegame" ) for pkg in "${packages[@]}"; do echo "正在清理 $pkg" adb shell am force-stop "$pkg" done这段脚本做的事情很朴素,但你把它配合系统的计划任务(Windows的任务计划程序或crontab)使用,就能实现每天凌晨自动清理后台应用,省去了手动划任务的麻烦。实际工作中,我还会在清理前先执行adb shell am kill-all来杀掉所有后台进程,再针对个别顽固应用做force-stop。
注意一点:force-stop对系统应用需要一定权限,部分厂商ROM会限制。遇到这种情况,退而求其次用am kill只能终止允许被杀死的后台进程,效果不如force-stop彻底,但至少不会误伤系统关键进程。
3.2 模拟用户操作:自动滑动与点击
比清理后台更常见的需求是模拟真实用户操作。比如你想让手机自动刷一会儿短视频,或者自动走一遍App的新手引导,核心就是input swipe和input tap。
这里分享一个真实案例。之前我负责的App有一个签到功能,入口在首页顶部,需要先点击签到按钮,再在弹出的弹窗里点击“立即签到”,最后还要截图保存结果。我把这个流程写成了Python脚本,用subprocess调adb命令,虽然简单,但很能说明问题:
import subprocess import time def adb_shell(command): subprocess.run(f"adb shell {command}", shell=True, check=True) # 1. 启动应用 adb_shell("am start -n com.example.app/.MainActivity") time.sleep(3) # 2. 点击首页签到按钮,坐标按1080x1920分辨率的相对位置计算 adb_shell("input tap 540 300") time.sleep(2) # 3. 点击弹窗确认按钮 adb_shell("input tap 540 960") time.sleep(1) # 4. 截图并拉到本地 adb_shell("screencap -p /sdcard/checkin.png") subprocess.run("adb pull /sdcard/checkin.png ./", shell=True) print("签到完成")这段代码没有任何高深技术,但它是理解adb自动化的良好起点:启动、点击、等待、截图,这就是脚本最基本的闭环。需要注意sleep的时间要合理,太短会导致界面还没加载出来就点击,太长又影响效率。我一般会根据页面加载速度动态调整,必要时通过dumpsys window判断当前窗口是否已经切换。
实际测试还有个容易忽略的点:如果目标按钮在刷列表时才会出现,直接tap会找不到位置。这种情况下我的做法是先执行几条swipe命令把列表滚动到目标区域,再执行点击。这种“先滑动后点击”的模式在自动化脚本里非常常见。
3.3 批量安装:几十台设备的提效利器
日常测试经常要往多台手机装同一个App,手动一个个拖APK简直折磨。用adb脚本批量安装效率完全不同。
我先讲核心命令:adb install -r path/to/app.apk,-r表示覆盖安装保留数据。如果APK的targetSdk版本比较新,而设备Android版本较旧,可能会碰到安装失败,提示INSTALL_FAILED_DEPRECATED_SDK_INT之类的问题。此时可以加一个参数:adb install --bypass-low-target-sdk-block -r app.apk,绕过targetSdk校验。这个参数是Android 14之后引入的,但用来解决SDK兼容问题很实用。
批量安装的脚本逻辑大致如下:
#!/bin/bash adb devices | grep -w "device" | awk '{print $1}' > devices.txt while read -r device; do echo "开始安装到 $device" adb -s "$device" install -r ./app.apk if [ $? -eq 0 ]; then echo "$device 安装成功" else echo "$device 安装失败" >> install_fail.log fi done < devices.txt这个脚本先把设备列表读出来,然后逐台安装,失败的信息写入日志。虽然结构简单,但比手动操作强太多了。如果在Windows自带的cmd里跑,语法会有差异,我更推荐装一个Git Bash或者直接用Python写循环。
3.4 日志与状态采集:让脚本更智能
真正让adb自动化脚本显得“智能”的地方,在于它会读取设备状态并做出判断。你可以用dumpsys系列命令拿到系统内部数据,然后让脚本根据这些数据决定下一步行动。
举个例子,之前做功耗测试时需要分析App在后台的唤醒情况。我先执行:
adb shell dumpsys batterystats --enable full-wake-history让设备开始记录详细的唤醒历史。测试跑一段时间后,再执行:
adb shell dumpsys batterystats > batterystats.txt把这个文件导出来,就能看到App的wakelock(唤醒锁)持有时间、CPU运行时间、网络活动等统计数据。脚本可以根据这些数据分析出App是否存在异常频繁唤醒导致耗电过快的问题。
再比如自动化过程中如果发现页面没有跳转成功,可以在脚本里加入adb shell dumpsys window | grep mCurrentFocus,获取当前前台窗口的Activity,和期望的Activity做对比。不一致就重试,重试N次还不行就打日志并退钉。这种“判断—重试—退出”的逻辑是所有可靠自动化脚本的共同特性。
4. 进阶玩法:多设备并发与UI控件交互
4.1 多设备并发控制的几个思路
很多人用adb连多台设备时都会遇到同一个问题:不加-s参数,adb命令根本没法执行,因为设备不唯一。我处理多设备自动化主要有三种模式。
第一种最简单,就是前面批量安装脚本里展示的逐台循环。它虽然挨个执行,但胜在稳定,脚本好写,也不会把设备搞乱。缺点是当设备数量多、操作耗时长时,整体时间线性增长。
第二种是并行执行,利用shell的&操作符或Python的ThreadPoolExecutor。比如需要在10台设备上同时启动某个App,可以给每台设备开一个子进程执行命令:
from concurrent.futures import ThreadPoolExecutor devices = ["device_a", "device_b", "device_c"] def start_app(device): cmd = f"adb -s {device} shell am start -n com.example/.MainActivity" subprocess.run(cmd, shell=True) with ThreadPoolExecutor(max_workers=5) as executor: executor.map(start_app, devices)注意max_workers不要开太多,否则电脑CPU和USB带宽都会吃紧,反而容易出问题。我一般控制在3到5个并发。
第三种是使用某些自动化测试平台或框架内置的多设备管理能力。但即便用了框架,底层最终还是落到adb的-s参数上,理解这个本质能帮你快速排查各种并发异常。
4.2 从坐标到控件文本:用adb读取UiAutomator属性
前面讲的点击都是基于坐标,但真实项目的UI元素位置经常变动,坐标一旦失效脚本就废了。这时候需要一种能拿到控件信息的方式。
adb本身提供了一个很好用的命令:
adb shell uiautomator dump /sdcard/ui.xml adb pull /sdcard/ui.xml它会把当前界面所有控件的层级和属性导出成XML文件。你可以在这份XML里搜索控件文本、resource-id或content-desc,然后计算出该控件的bounds中心点坐标,再用input tap去点击。
这样做的好处是:脚本不再依赖写死的坐标,而是根据控件实际位置动态定位。比如搜索一个文本为“签到”的Button,然后提取它的bounds属性[400,900][680,1020],可以算出中心点是(540, 960),再交给点击命令执行。
这套思路虽然不如Appium那样优雅,但在轻量脚本里完全够用。而且一旦掌握,你还能用它解决很多奇怪的UI自动识别问题,比如不同分辨率适配。
4.3 权限增强思路:Shizuku与无USB调试场景
有些自动化脚本想执行的高权限操作,在非root设备上会被限制。比如直接控制系统设置、模拟其他应用点击等。除了root,还有一个折中方案是借助Shizuku。
Shizuku的运行原理是:通过adb授予一个系统级API权限给手机上的一个小服务,之后这个服务可以代表你执行很多高权限命令,而不需要重新插USB线。它启动后,即使和电脑断开连接,手机上的脚本依然可以调用shizuku shell来执行命令。
举个例子,如果你通过Shizuku的API运行:
sh /storage/emulated/0/android/data/com.omarea.vtools/up.sh这其实是借助Shizuku权限去执行一个脚本文件,完成一些普通App做不到的系统级修改。使用Shizuku时需要先在电脑上执行一次adb shell sh /sdcard/Android/data/moe.shizuku.privileged.api/start.sh之类的启动脚本,之后手机会弹窗请求授权,确认后就生效了。
不过要提醒一句,这类高权限方案有成百上千种应用场景,但也要注意隐私和合规。脚本里不要做任何越权获取用户信息、绕过应用检测的事情,仅用在工作所需的正规自动化测试中。
4.4 模拟器与电视设备的特殊处理
说到设备多样性,模拟器和智能电视也经常出现在adb自动化需求里。
模拟器(如夜神、雷电、MuMu)本质上是一个运行在电脑上的Android虚拟机,它默认会开一个adb端口供外部连接。打开模拟器后,你直接执行adb connect 127.0.0.1:5555或adb connect 127.0.0.1:62001(不同模拟器端口不同)就可以连上。连接成功后,模拟器就被当成一台普通设备来操作。用adb命令控制游戏自动刷初始号、跑图之类的场景就是这样实现的。
电视盒子、智能电视也支持adb,很多老款智能电视在设置里没有直接的开发者选项,需要连续按“版本号”之类的隐藏入口,个别品牌甚至要输入特定校验码才能开启。打开adb后,电视和电脑连同一个局域网,就可以adb connect <电视IP>:5555连接。连上之后用input keyevent KEYCODE_DPAD_UP、KEYCODE_DPAD_DOWN这类按键事件来控制焦点移动,代替物理遥控器完成操作。这在做电视端App自动化测试时非常实用。
5. 常见问题与排查技巧实录
5.1 高频连接异常速查表
总有人问我“为什么我adb连不上设备”,其实大部分问题都集中在下面这几种情况。我整理了一张速查表,可以对照着排查。
| 异常现象 | 常见原因 | 快速解决办法 |
|---|---|---|
adb devices显示 unauthorized | 手机未点“允许USB调试”授权弹窗 | 拔插数据线,重新弹窗并勾选始终允许;或执行adb kill-server后重连 |
| 设备显示 offline | adb服务版本与设备端不匹配或服务异常 | 执行adb kill-server和adb start-server重启服务;换一根数据线 |
| error: could not initialize winsock: a system call has failed. (10107) | Windows下winsock初始化异常,常见于杀毒软件/网络驱动干扰 | 重启adb服务,以管理员身份运行命令行;关闭或暂时卸载可疑安全软件后重试 |
| more than one device | 连接了多台设备但命令未指定序列号 | 在命令里加-s <序列号>参数 |
| 找不到设备 | 没开启USB调试、驱动没装好、线缆只支持充电不支持数据传输 | 确认开发者选项,安装设备驱动,换双通数据线 |
| adb不是内部或外部命令 | 环境变量没配置或PATH未生效 | 重新配置platform-tools路径,新开命令行窗口 |
| INSTALL_FAILED_TARGET_SDK_TOO_LOW | 设备系统版本比APK targetSdk低 | 使用adb install --bypass-low-target-sdk-block参数安装 |
| 连接WiFi后不稳定 | 手机息屏会断开WiFi或限制adb后台 | 在开发者选项里开启“保持唤醒”,或使用usb连接 |
5.2 逐步排查:连接正常但点击没反应
这是很诡异的一种故障:adb devices正常,adb shell也能执行,但input tap或input swipe就是没反应。
我遇到过几次这种情况,排查路径基本上是这样的:
先确认当前屏幕是不是解锁状态。手机锁屏时input tap点击会失效,因为点击事件被锁屏拦截了。先执行adb shell input keyevent KEYCODE_WAKEUP唤醒屏幕,再用adb shell wm dismiss-keyguard解锁。
再检查有没有App悬浮窗遮挡。某些应用会把触摸事件拦截在自己的窗口层,导致点击命令被吃掉。这种情况可以用adb shell dumpsys window | grep -i input查看输入分发目标,如果目标窗口不是你想点的那个,大概率是有系统弹窗或悬浮按钮盖住了。
最后检查坐标是否正确。特别是横竖屏切换后,坐标轴会变化,之前竖屏的坐标在横屏下点击的位置完全不一样。我碰到过最坑的一次是某款手机系统自带“单手模式”,把屏幕内容缩放了30%,所有坐标自然全偏了。关闭单手模式后恢复正常。
5.3 脚本稳定性的几个建议
写adb自动化脚本,最容易翻车的地方不是命令不会写,而是脚本不够健壮。我在实践中总结了几条经验:
第一,脚本每一步操作之间一定要加合理延迟。不要指望命令一条条飞快执行完,App的页面加载、动画过渡都需要时间。sleep 1可能不够,3秒也可能长了,建议根据场景实测调整,必要时在点击前做页面元素判断。
第二,操作前先获取当前窗口焦点,确认页面到位后再执行后面的动作。我常用adb shell dumpsys window | grep mCurrentFocus做一个前置校验。匹配不到期望的Activity时,不继续执行,先截图留证再退出脚本。这个设计帮我避免了很多“点半天结果全点在错误页面”的情况。
第三,脚本要有日志。每做一步就把执行结果写入一个日志文件,出问题时能直接定位到哪一步失败。简单做法是在shell里用>> log.txt追加输出,Python里更简单,直接用logging模块。
第四,尽量不在脚本里写死复杂坐标。能用uiautomator dump动态解析控件位置就动态解析,不能的话至少把坐标写成相对比例。这样换设备、改分辨率时,只需要改一行配置而不是整个脚本。
还有一个小技巧:长时间跑自动化前,先在设备设置里关闭“屏幕超时自动锁屏”,或者发送一个adb shell settings put system screen_off_timeout 1800000把熄屏时间改成30分钟,否则脚本跑到一半手机锁屏,后面的操作基本全废。
5.4 避坑实录:那些折腾到深夜的问题
最后分享几个让我印象深刻的“坑”,也都是网上搜索热度很高的问题。
第一个是winsock初始化报错。有一回在Windows上跑自动化,突然所有adb命令都报error: adb: could not initialize winsock: a system call has failed. (10107)。这个报错看着像是adb本身出了问题,其实是系统winsock环境被某些软件改动或干扰了。我最后是用管理员权限打开命令行,执行adb kill-server和adb start-server,把adb拿到管理员权限下重新初始化才解决。如果还不行,可以试试在网络适配器设置里重置一下网络栈。
第二个是电视或盒子上的adb二维码问题。现在一些新款电视或机顶盒,开启adb后不再显示IP端口,而是显示一个二维码,需要用专门的计算工具去解码获取加密的adb连接信息。这种机制本质上是厂商为了安全做的限制。如果你遇到这种情况,只能去查对应型号的开启教程,或者借用同型号设备上已验证的校验码计算器,没有特别通用的办法。
第三个是真机连接时提示“手机无响应”。多数时候不是adb的问题,而是手机弹了一个授权对话框或者“是否允许USB调试”之类的系统弹窗,挡住了后续操作。脚本里遇到这种异常,建议先把设备状态打出来,人工确认屏幕上有没有弹窗,再决定是否继续。
还有一个小众但很实用的问题:有时候adb install提示低版本SDK限制,用--bypass-low-target-sdk-block参数可以强制安装。这个参数在自动化安装老版本APK到新系统上时相当有用,但注意它只是绕过了安装时的SDK版本检查,不保证安装后运行正常,所以装完最好再自动启动一次应用验证。
我个人在实际操作中最大的体会是:adb自动化脚本的价值不在于脚本本身有多花哨,而在于它能稳定、可重复地完成那些“手动操作完全可以做,但不想反复做”的事情。你越是把基础命令吃透,越是学会在脚本里加入状态判断和错误处理,你的自动化方案就越可靠。如果这篇文章让你少踩几个我踩过的坑,那就值了。最后再分享一个小技巧:给adb命令单独做一个shell函数或Python封装,统一处理设备选择、日志输出和异常退出,长期来看能省下非常多重复劳动。