玩Android开发或者做智能设备调试的同学,应该都跟adb打过交道。这玩意儿平时不起眼,但真要排查个问题、装个包、看个日志,少了它还真不行。我最早接触adb是刚入行那会儿,连环境变量都配不明白,后来被各种奇葩报错折磨了几轮,才把adb的常用命令摸清楚。其实adb没有想象中那么复杂,核心逻辑就一句话:通过一条USB线或网络通道,让电脑能对手机发号施令。今天这篇文章就从原理到实战,把平时用得上、踩过坑的adb命令一次性讲透,适合刚入门Android开发和测试的同学,也适合做智能电视、手表、车机等安卓设备调试的朋友收藏备用。
adb全称Android Debug Bridge,翻译过来是安卓调试桥。它之所以叫“桥”,是因为它的职责就是连接电脑端和安卓设备两端,帮你在中间传话。无论是安装APK、复制文件、查看日志、模拟点击,还是读取电池状态、系统信息,都可以通过adb完成。相比在屏幕上点点点,adb是命令行操作,效率高出不少,尤其是在批量处理、自动化测试、设备出厂调试这些场景下面,几乎是唯一选择。下面我按实际使用频率和操作顺序,把这一整套命令讲一遍。
1. adb的工作原理:搞懂它,你才知道命令为什么会生效
1.1 adb的三端架构
很多人用过adb devices,却不知道这背后其实是三部分在配合工作。第一部分是电脑端的adb客户端,也就是我们在终端里敲的命令行工具;第二部分是设备端常驻的adbd守护进程,它在安卓系统里后台运行,等待接收指令;第三部分是电脑端与设备端之间的adb server,它由客户端自动启动,监听本机端口并管理所有连接关系。你敲一条adb命令,流程是客户端告诉server,server再通过USB或网络转发给设备里的adbd,adbd执行完再把结果原路返回。
这套架构最直观的体验就是:server挂掉后,所有adb命令都会卡住或报错。所以遇到adb没反应,我第一反应就是先执行adb kill-server,再执行adb start-server,把中间这个传话筒重启一遍。80%的连接异常都能这么解决。
1.2 理解“调试桥”的逻辑,命令就好记了
记住一个关键点:adb命令的通用结构是“adb + 操作对象 + 动作”。操作对象主要是devices(设备)、shell(设备里的命令行)、install(安装器)、push/pull(文件传输)这些;动作就是具体做什么。比如adb devices是列出设备,adb shell是进入设备终端,adb install是安装应用。把这层逻辑捋顺后,很多命令根本不需要背,看到结构就能猜出七八分。
搞清楚原理之后,下面从环境配置开始,一步步把整套命令落地。环境这关过不去,后面全是空谈。
2. 环境搭建:把adb装好,少走一半弯路
2.1 不同系统下的安装方式
先说Windows。最简单的方案是直接下载Google官方的Platform Tools压缩包,解压到固定目录,比如D:\platform-tools,然后把目录路径加进系统环境变量Path里。这个包里有adb.exe、AdbWinApi.dll这些文件,一共也就十几MB,比装一整个Android Studio轻量太多。如果你想省事,也可以装一个带adb的集成工具,但我个人建议用官方包,干净且没有多余依赖。
macOS用户就简单了,有Homebrew的话直接执行brew install --cask android-platform-tools,安好后adb就在PATH里了。Linux用户同理,Ubuntu/Debian可以sudo apt install android-tools-adb,CentOS/RHEL可以用sudo yum install android-tools-adb。不同发行版包名可能略有差异,装不上就搜一下对应版本。
如果你已经在用Android Studio,其实它自带了adb,路径在SDK目录的platform-tools下。Windows默认在C:\Users\你的用户名\AppData\Local\Android\Sdk\platform-tools,macOS在~/Library/Android/sdk/platform-tools。但注意,这个路径下的adb不一定被全局识别,还是得手动配环境变量。
2.2 环境变量配置与验证
Windows配置环境变量,右键“此电脑→属性→高级系统设置→环境变量”,在系统变量里找到Path,新建一行,填入platform-tools的完整路径。改完之后一定要新开一个终端窗口再验证,不然不会生效。
验证命令很简单:
adb version如果输出了类似Android Debug Bridge version 1.0.41这样的信息,就说明装好了。输出版本号只是为了确认命令能执行;接下来执行adb devices,此时列表应该是空的,因为你还没插设备。这一步能通过就说明环境完全正常。
2.3 装好之后最常见的环境坑
我经常在群里看到有人问“adb不是内部或外部命令”,这个报错的本质就是系统找不到adb程序,也就是环境变量没配好或者没新开终端。另外Windows下还有一个高频报错:
adb: createfilew 'nul' failed: 系统找不到指定的文件这个我遇到过好几次,原因多半是系统环境变量里的Path被某些软件改坏了,导致adb调用系统空设备nul时失败。解决办法是检查Path变量,把缺失的%SystemRoot%\system32等基础项补回去,然后重启终端。如果还不行,就把platform-tools里的文件完整复制到另一个干净目录重配一次。
3. 设备连接:从USB到无线,以及各种稀奇古怪的连接问题
3.1 开启USB调试的正确姿势
设备端必须打开“开发者选项”里的USB调试。不同版本安卓打开开发者选项的方式略有不同,大部分是连续点击“版本号”7次。Android 9以下一般点完之后就出现开发者选项;Android 10以上可能还需要在设置里手动进入开发者选项界面,才能看到USB调试开关。
连接之后,手机会弹出“是否允许USB调试”的授权对话框,勾选“始终允许”再确认。如果没弹窗,多半是驱动问题或者数据线只能充电不能传数据。这里建议直接换一根原装数据线试试,很多人排查半天,最后发现是线的问题。
3.2 多设备场景下的目标指定
如果电脑连着多台设备,adb会直接报错说检测到多个设备,并要求你指定目标。列出所有设备用adb devices,结果里会显示每台设备的序列号和状态。序列号是唯一的,比如RK3566ABCDEF或emulator-5554这类的。
指定具体设备执行命令时,在adb后面加-s参数:
adb -s RK3566ABCDEF shell getprop ro.product.model这条命令的意思是,让序列号为RK3566ABCDEF的设备执行getprop,输出产品型号。多设备场景下,-s参数几乎每个命令都能配,建议养成习惯,避免操作错设备。我在同时调试两台开发板时,没加-s差点把演示机的应用给卸了,从那以后所有命令都老老实实带序列号。
3.3 无线调试实战
USB线不够用或者设备离电脑远的时候,无线调试是更好的选择。前提是手机和电脑在同一个局域网里。传统方式分两步,第一步先用USB连接手机,执行:
adb tcpip 5555这条命令让设备在5555端口开启adb监听。然后拔掉USB,找到手机的IP地址,在电脑上执行:
adb connect 192.168.1.100:5555返回connected to 192.168.1.100:5555就成功了。不过要注意,手机重启后需要重新用USB执行一次tcpip命令,因为你设置的端口不会永久保留。
Android 11及以上还有更便捷的无线调试方式,系统设置里直接就有“无线调试”选项,打开后可以生成配对码,执行:
adb pair 192.168.1.100:37623然后输入配对码,配对成功后就可以直接用adb connect连了。我实测下来这个方式比老的tcpip法更稳定,不需要插USB,适合调试智能手表、电视盒子这类不方便插线的设备。
3.4 unauthorized和找不到设备的排查思路
连接手机时,如果adb devices显示unauthorized,说明设备端没有确认授权,或者你点了“否”。这时候可以先重新插拔USB,再确认手机屏幕上的授权弹窗;如果弹窗不再出现,可以到开发者选项里选择“撤销USB调试授权”,重新插线再授权一次。
如果执行adb devices直接什么都没有,先检查驱动、换端口、换线,再杀server重启。特别注意,有些安卓设备(比如部分智能电视)默认隐藏了usb调试选项,需要先打开“ADB调试”开关。像小天才手表这类需要校验码的设备,虽然也是adb设备,但厂商会做一层额外的授权校验,需要在手表上查看校验码,配合厂商工具获取验证后才允许连接,不能直接用普通手机的授权流程硬来。
4. 应用管理:装、卸、查、杀一套带走
4.1 安装APK的几种方式与参数
应用安装是日常高频操作,基本命令是:
adb install 你应用的路径.apk但实际项目里我几乎不直接这样装,而是常用带参数的形式。-r表示覆盖安装,保留数据和旧版本覆盖升级;-d表示允许降级安装,也就是新版本号比旧的低也能装;-g表示安装时直接授予所有运行时权限,适合测试应用时省去一个个点授权的麻烦。组合起来一般是:
adb install -r -d -g 你应用的路径.apk如果你想验证应用安装到系统分区并常驻,可以用-s参数安装到SD卡,或者通过root后用adb remount配合adb push把APK放到系统目录。但这些都是特殊场景,普通调试用install就够了。
还有一点我之前踩过坑:adb install不支持安装那些写着“仅限特定系统”或者签名为testkey的APK到非root设备上,会提示INSTALL_FAILED_UPDATE_INCOMPATIBLE。这种一般是签名不一致导致的,先把旧包卸载再装新版就能解决。
4.2 卸载应用
卸载命令很简单:
adb uninstall 包名注意这里写的是包名,不是应用名字。想知道包名可以用下面的查询命令。如果想卸载的时候保留应用数据文件,加-k参数。比如要卸载微信但保留聊天记录及相关文件,就执行adb uninstall -k com.tencent.mm。当然,实际调试中大多数时候直接卸干净就好,-k只适合特殊情况。
如果只是想“禁用”某个应用而不是卸载,可以执行:
adb shell pm disable-user 包名恢复用pm enable 包名。这个操作在调试预装应用时非常有用,能模拟用户手动停用应用的效果,不用真的卸载。
4.3 查询应用信息与包名定位
要查到某个应用对应的包名,先列出设备上所有已安装应用:
adb shell pm list packages输出几百行,眼睛看不过来,更好用的是用-f参数查看包名和APK路径,用-3只看第三方应用:
adb shell pm list packages -3当你只记得应用名字里的某个关键词,比如要找“相机”,可以用:
adb shell pm list packages | grep cameraWindows的cmd不支持grep,可以用findstr:
adb shell pm list packages | findstr camera包名拿到后,启动应用就有了依据。想直接启动某个应用的主界面:
adb shell am start -n 包名/Activity完整路径Activity路径不好记的话,不固定写死,可以先在应用运行状态下执行:
adb shell dumpsys window | grep mCurrentFocus这条命令会返回当前处于前台的窗口组件,格式类似mCurrentFocus=Window{xxx 包名/Activity路径},直接复制到am start命令里就能重新拉起对应页面。
4.4 进程停止与缓存清理
调试时经常遇到应用卡死、数据残留的问题。强制停止应用:
adb shell am force-stop 包名相当于在设置里点“强行停止”,比杀进程更彻底,连后台服务也会一起停掉。如果你需要清理应用缓存目录但不卸载应用,可以用:
adb shell pm clear 包名这个命令会清空应用的数据和缓存,相当于恢复出厂状态。它和force-stop的区别是,pm clear连数据库、SharedPreferences这些数据都清干净,所以只适合在需要干净环境重现bug的时候使用,别随手就敲。
5. 文件传输与路径权限
5.1 push和pull的基本用法
往设备里放文件,用push;从设备里取文件,用pull。这两个命令的本质就是文件复制,和Linux的scp或者Windows的copy差不多,但走的是adb通道。
adb push 本地文件路径 设备目标路径 adb pull 设备文件路径 本地保存路径举个例子,我想把电脑上的test.apk放到手机的Download目录:
adb push E:\apk\test.apk /sdcard/Download/注意目标路径要以/结尾,表示放到这个目录下;如果不以/结尾,adb会认为它是完整文件名。这个细节我掉过坑,本来想放进目录,结果它直接创建了一个没有扩展名的文件,后面排查了半天才发现。
从设备往电脑拉日志文件同理:
adb pull /sdcard/logcat.txt C:\logs\5.2 常见存储路径与权限说明
安卓的存储路径分两大类。/sdcard/和/storage/emulated/0/这俩是外部存储,普通应用(在授权后)都可以读写,属于用户可见的区域。/data/data/包名/属于应用私有内部存储,默认情况下非root设备上普通用户无法直接访问,执行adb shell后也会提示permission denied。这也是为什么很多新手pull应用数据库文件时报错的原因。
如果你调试的是车机、电视盒子这类带root权限的设备,可以先用adb root或者adb remount提权,再访问系统目录。提权失败的话,退而求其次可以用adb backup命令备份应用数据,但这种方式的兼容性和限制比较多,不如直接root来得爽快。
另外补充一个东西,Android 7及以上引入了content URI机制。你在logcat里经常能看到类似content://com.baidu.searchbox.fileprovider/baiddpath/...这样的路径片段,这是应用通过FileProvider对外暴露文件访问地址,不是真实文件路径。adb pull不能直接用它,需要先在应用里把这个URI转成真实路径,或者用adb shell content query去查ContentProvider,这个属于进阶玩法,普通调试用不上,但知道它不是损坏路径就行,别浪费时间硬拉。
5.3 反向端口转发
调试手机里访问电脑本地服务时会用到reverse命令。例如手机里的浏览器要访问电脑上8080端口的开发者服务,可以执行:
adb reverse tcp:8080 tcp:8080这样手机访问localhost:8080就会转发到电脑的8080端口。这个命令在调试WebView、H5页面、模拟App调用本地接口的时候非常方便,不用改代码里的服务器地址,也不需要设备连到外网。
6. 日志排查:logcat与dumpsys的实战用法
6.1 logcat基础过滤与保存
看日志是adb最高频的用途。安卓系统日志全部走logcat输出,你可以理解为设备端有一个环形缓冲区,实时记录所有进程打印的日志。最简单的用法是实时看全部日志:
adb logcat但这样刷屏太严重,基本没法看。更实用的做法是按标签过滤,比如你只关心MainActivity相关的输出:
adb logcat -s MainActivity-s参数等于指定标签并隐藏其他所有内容。如果应用有多个标签,可以在-s后面用空格隔开连续加:
adb logcat -s MainActivity OkHttp保存日志到本地文件,方便回传分析:
adb logcat -v time > C:\logcat.txt-v time会在每行日志前面加上日期和时间,这个信息在排查问题时非常重要,能定位崩溃发生的时序。同样,Windows控制台输出重定向后实时显示会关掉,让命令跑一段时间然后按Ctrl+C停止,日志就已经写进文件里了。
6.2 logcat的进阶过滤技巧
如果日志太多了,想同时排除一些无关内容,可以用grep管道过滤。Windows下注意用findstr,且cmd对特殊字符处理比较麻烦,建议把所有日志先存文件再读取。
adb logcat -v time | findstr "error AndroidRuntime"Android自带的崩溃日志会打上AndroidRuntime标签,看到这个标签的内容基本就找到了崩溃栈。过滤ERROR级别的日志还可以用:
adb logcat -v time *:E*:E表示所有标签下只显示Error及以上级别的日志。这个组合适合快速扫描设备有没有明显异常。调试原生崩溃时,你甚至会把整个logcat按照进程区分,先执行adb ps -A | grep 包名找到进程PID,再用--pid=进程号只输出该进程的日志,这样干净得多。
6.3 dumpsys——系统服务的体检报告
dumpsys是adb shell下最强大的诊断工具之一,它把系统里各服务当前的状态全部导出。比如看电池电量与充电状态:
adb shell dumpsys battery返回内容包括电量百分比、充电状态、温度等。更厉害的是它还能统计每个进程的耗电情况,需要在设备上先开启完整统计:
adb shell dumpsys batterystats --enable full-wake-history开启后正常使用设备一段时间,最后导出报告分析。这个命令对排查待机异常耗电、唤醒锁占用问题非常有效,能清楚看到哪个应用长时间持有wakelock。虽然Android Studio自带的Profile工具也能做这事,但命令行的优势是能批量跑、能在无人值守的测试机上用。
其他常用的dumpsys服务还有:
adb shell dumpsys meminfo 包名 # 查看单个应用内存使用 adb shell dumpsys window # 查看窗口状态与焦点 adb shell dumpsys activity # 查看Activity任务栈 adb shell dumpsys package 包名 # 查看应用安装与权限详情这些命令输出都很长,可以配合grep/findstr过滤关键词。想查看完整的服务列表,执行adb shell dumpsys -l即可。
7. 屏幕调试与自动交互
7.1 截图与录屏
UI自动化或者bug复现的时候,截图和录屏是刚需。截图命令:
adb shell screencap -p /sdcard/screen.png adb pull /sdcard/screen.png C:\screen.png也可以更省事,利用Windows或macOS的命令管道直接把截图存到本地:
adb exec-out screencap -p > screen.png这个命令不走设备存储,直接字节流转到本地。Windows下注意要用cmd而不是PowerShell,否则容易遇到编码问题。录屏命令在Android 4.4以上可用:
adb shell screenrecord --time-limit 10 /sdcard/video.mp4--time-limit最大只能设180秒,超过会自动分段。录屏的分辨率默认是设备分辨率,也可以加--size 720x1280降低体积。录制结束会自动保存,再用pull拉回电脑。
7.2 input模拟触摸与按键
用input命令可以实现对设备的自动化操作。模拟点击屏幕的某个坐标:
adb shell input tap 540 1200坐标可以通过截图后用看图工具查看。模拟滑动:
adb shell input swipe 540 1500 540 300 500最后的500是滑动持续时间,单位毫秒。模拟键盘按键用keyevent,比如按Home键、返回键、菜单键:
adb shell input keyevent KEYCODE_HOME adb shell input keyevent KEYCODE_BACK adb shell input keyevent KEYCODE_MENU其实在讲input命令之前,有必要先说明一个关键前提:这些模拟交互命令,本质上是向系统注入InputEvent事件,不是真的触摸屏幕。所以即使手机锁屏或者有弹窗,事件照样可以注入到系统层,只要系统接收就会触发对应动作。这也让input命令成了做自动化回归测试的利器。
7.3 结合input实现自动化测试雏形
只有单一命令还不够,把它组合起来才是完全体。比如一个最简单的自动安装并启动应用的脚本,在Windows批处理里可以写成:
adb install -r test.apk adb shell monkey -p 包名 -c android.intent.category.LAUNCHER 1monkey的-p指定包名,后面的数字是随机事件数,设置成1就只会启动应用。要做简单的UI点击流程,就连续用input tap模拟用户点击。做长按、拖拽这类复杂手势,用input swipe多段组合也能勉强实现。
模拟器里控制游戏,本质上也是这套逻辑。很多手机游戏或模拟器可以通过adb的input命令直接注入点击和按键,比起图像识别加鼠标模拟,效率更高且不容易被游戏检测到。我自己就用这个方法给模拟器里的游戏分配了快捷键:先通过adb devices确定模拟器序列号,再用-s emulator-5554 input tap对指定模拟器输出点击,再配合命令行的循环结构,就能实现简单的自动刷本脚本。
7.4 修改系统设置与内核参数
input之外,adb shell还能直接改系统设置项。比如修改系统全局动画缩放,让设备看起来更流畅:
adb shell settings put global window_animation_scale 0 adb shell settings put global transition_animation_scale 0 adb shell settings put global animator_duration_scale 0再比如自动开启飞行模式:
adb shell settings put global airplane_mode_on 1 adb shell am broadcast -a android.intent.action.AIRPLANE_MODE --ez state true通过settings put能配置大部分系统设置,这比在设置界面里手工找到对应开关快得多。如果你要长时间跑性能测试,还可以顺手把屏幕超时调到最长或直接保持常亮。
8. 常见问题速查表与实战心得
整理了日常使用中频率最高的几个问题,可以直接对照排查:
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| adb不是内部或外部命令 | PATH未配置或终端未重启 | 重新配置环境变量后新开终端 |
| adb devices无设备 | 驱动问题/数据线不支持数据/授权未确认 | 换线换口、重装驱动、撤销授权重试 |
| 设备显示unauthorized | 电脑未获得授权 | 设备端确认弹窗,或撤销授权重新弹 |
| 多设备时命令报错 | 未指定目标设备 | 加-s 序列号参数 |
| createfilew 'nul' failed | Windows环境变量Path异常 | 修复系统变量,补齐System32路径 |
| 设备offline | adb server与设备连接不稳定 | 执行adb kill-server重启,或重新插拔 |
| pull权限不足 | 目标文件在应用私有目录 | root提权或用pm backup等方式迁移 |
最后说几个我这几年摸索出来的经验。第一,批量操作设备时,优先写一个shell脚本或批处理脚本,把devices的输出解析成列表再循环执行,比自己一台台手敲命令快几个数量级。第二,凡是涉及长时间运行的命令,比如logcat导出、dumpsys采集,一定要给输出文件加时间戳后缀,不然同一文件名覆盖后你根本不知道哪份是哪个时间段的。第三,adb命令虽然功能强,但它毕竟是一个调试工具,在出厂固件、生产测试、车机设备这类场景下,尽量把命令封装成脚本给同事使用,避免有人误操作把系统应用卸载或者把用户数据清空。
关于adb还有非常多的衍生玩法和调试技巧,比如通过adb shell获取设备底层传感器数据、修改屏幕密度、批量给不同设备安装不同应用等等。文章里提到的这些都是平时最基础、最常用、踩坑率最高的那批。你先照着用起来,等真正遇到具体问题的时候,再根据报错信息往深了查,慢慢就会有自己的命令工具箱了。我个人的体会是,adb用得好不好,不在于背了多少参数,而在于遇到问题时能不能快速定位出是哪一层的故障——环境、连接、权限还是设备本身。把这层思路理顺,adb真的就是一把趁手的螺丝刀,简单、可靠、离不开。