Android调试必用工具adb命令详解

前言 adb全称为Android Debug Bridge,译为安卓调试桥。是一个命令行工具,主要用于调试设备。adb.exe放置在/sdk/platform-tools目录下,可对设备进行各种操作,包括安装卸载应用、放置与拉取文件、shell交互等等。熟知adb的命令,对于应用调试与测试非常重要。
1.adb原理 adb是一种c(客户端)-s(服务端)架构的程序,包括三个组件客户端,守护进程(adbd),服务器。详细介绍可参考官方说明。
下面是我对于adb的个人理解,首先要分清楚两个物理设备,输入adb命令的个人电脑,接收adb命令的Android设备,他们的角色分工如下:

  • 个人电脑:包含客户端与服务器,客户端就是adb.exe,用于开发者交互,服务器是在电脑中的一个后台进程,管理电脑与Android设备的通信。
  • Android设备:包含一个做为后台进程运行的守护进程adbd,作用是在设备上运行命令。
接下来再捋清楚两者通信过程:
  • 个人电脑中运行adb客户端并启动adb服务器进程,进程端口号为本地TCP端口号5037。
  • 电脑中的adb服务器会扫描所有连到电脑上安卓设备的端口号,从5555查找到5585之间的所有奇数号端口,一旦发现adb守护进程adbd便会与设备建立连接。
  • Android设备的奇数号端口用于adb连接,偶数号端口用于控制台连接,换句话说就是奇数号端口用于数据传输,偶数号端口用于命令传输。
最后,成功建立连接,开始用命令控制Android设备。
2.adb命令大全
类型 命令 说明
通用命令 devices 所有已连接设备连接
- help 查看帮助
- version 查看adb客户端版本号
网络 connect HOST[:PORT] 通过TCP/IP方式连接设备
- disconnect [[HOST]:PORT] 断开某个或所有设备的连接
- forward --list 列出所有转发的端口
- forward [–no-rebind] LOCAL REMOTE 设备端口转发
- ppp TTY [PARAMETER…] 通过USB进行点对点连接
- reverse – list 列出设备的所有反向端口转发
- reverse [–no-rebind] REMOTE LOCAL 操作反向端口转发
文件传输 push [–sync] LOCAL… REMOTE 本地文件复制到设备
- pull [-a] REMOTE… LOCAL 设备文件复制到本地
- sync [all-data-odm-oem-product-system] 同步文件
shell shell [-e ESCAPE][-n][-Tt][-x] 远程运行脚本命令
- emu COMMAND 运行模拟器命令
app安装 install [-lrtsdg] [–instant] PACKAGE 安装一个程序包
- install-multiple [-lrtsdpg] [–instant] PACKAGE… 多个apk合成一个包安装
- install-multi-package [-lrtsdpg] [–instant] PACKAGE… 安装多个程序包
- uninstall [-k] PACKAGE 卸载应用包
调试 bugreport [PATH] 将错误报告写入指定的路径
- jdwp 列出托管JDWP传输的进程的pid
- logcat 查看设备的日志
安全 disable-verity 在userdebug版本上禁用dm-verity检查
- enable-verity 在userdebug版本上打开dm-verity检查
- keygen FILE 生成秘钥
脚本 wait-for[-TRANSPORT]-STATE 等待设备进入给定状态
- get-state 获取状态
- get-serialno 获取序列号
- get-devpath 获取设备路径
- remount [-R] 重新挂载文件系统
- reboot [bootloader-recovery] 重启设备
- sideload OTAPACKAGE 半加载给定的完整OTA软件包
- root 以root权限重启adbd守护进程
- unroot 用无root权限重启adbd守护进程
- usb 通过USB重启adbd监听
- tcpip PORT 通过TCP重启adbd监听
内部调试 start-server 开启adb客户端的服务器
- kill-server 停止服务器
- reconnect 主机端强制重连
- reconnect device 设备端强制重连
- reconnect offline 重置离线/未经授权的设备以强制重新连接
环境变量 $ADB_TRACE 以逗号分隔的调试信息列表,用于记录日志
- $ADB_VENDOR_KEYS 以冒号分隔的键列表(文件或目录)
- $ANDROID_SERIAL 要连接的设备序列号
- $ANDROID_LOG_TAGS logcat打印的tag
- $ADB_LOCAL_TRANSPORT_MAX_PORT 模拟器最大扫描端口
3.general commands:通用命令 3.1 devices
查看当前adb连接的所有设备,可选参数-l,输出如下信息。
  • 序列号
  • 连接状态
    • offline,设备未连接到 adb 或没有响应
    • device,设备现已连接到 adb 服务器
    • no device 未连接任何设备
  • 设备说明,-l选项输出的信息。
>adb devices -l List of devices attached 1e0aa136device product:natrium model:MI_5s_Plus device:natrium transport_id:1

3.2 version
查看当前adb的版本号与安装路径。
>adb version Android Debug Bridge version 1.0.41 Version 29.0.6-6198805 Installed as C:\android\sdk\platform-tools\adb.exe

3.3 help
帮助文档,可查看adb的所有命令用法。
4.networking:网络 4.1 connect HOST[:PORT] 与disconnect [[HOST]:PORT]
通过TCP/IP的方式连接设备。可通过此命令连接处于同一局域网下的android设备,只要电脑与手机连在同一上Wifi上就能使用此方式连接设备,需要知道手机设备的IP地址。
>adb connect 192.168.0.2 connected to 192.168.0.2:5555>adb devices List of devices attached 192.168.0.2:5555device

当想断开某个设备的Adb连接时,可通过disconnect命令实现,若不带任何参数,则表示断开所有连接。
>adb disconnect disconnected everything>adb devices List of devices attached

小提示:手机可以打开热点让电脑连接,手机热点的默认IP一般是192.168.43.1。
>adb connect 192.168.43.1 * daemon not running; starting now at tcp:5037 * daemon started successfully connected to 192.168.43.1:5555 >adb devices List of devices attached 192.168.43.1:5555device

4.2 forward --list
列出所有端口转发的socket连接,暂未明白如何使用。
5.文件传输:file transfer 5.1 push [–sync] LOCAL… REMOTE
将本地文件复制至设备中。
  • 可选参数sync,当与设备中有同名文件时只复制有新修改的文件
  • LOCAL… 本地文件目录,可同时复制多个文件
  • REMOTE 设备中放置复制文件的目录
示例如下:
C:\android>adb push D:\test\local.txt D:\test\local2.txt /sdcard/Download D:\test\local.txt: 1 file pushed, 0 skipped. 0.0 MB/s (3 bytes in 0.028s) D:\test\local2.txt: 1 file pushed, 0 skipped. 0.0 MB/s (3 bytes in 0.002s) 2 files pushed, 0 skipped. 0.0 MB/s (6 bytes in 0.043s)C:\android>adb shell //进入设备sdcard目录 generic_x86_arm:/ $ cd /sdcard/Download/ generic_x86_arm:/sdcard/Download $ ls -l total 8 -rw-rw---- 1 root sdcard_rw 3 2020-04-11 07:15 local.txt -rw-rw---- 1 root sdcard_rw 3 2020-04-11 07:15 local2.txt //查看文件内容 generic_x86_arm:/sdcard/Download $ cat local.txt abc//使用--sync参数,只复制有修改的文件 C:\android>adb push --sync D:\test\local.txt D:\test\local2.txt /sdcard/Download D:\test\local.txt: 0 files pushed, 1 skipped. D:\test\local2.txt: 1 file pushed, 0 skipped. 0.0 MB/s (5 bytes in 0.007s) //local.txt被跳过,local2.txt被复制,因为local2有经过修改 1 file pushed, 1 skipped. 0.0 MB/s (5 bytes in 0.032s)generic_x86_arm:/sdcard/Download $ ls -l total 8 -rw-rw---- 1 root sdcard_rw 3 2020-04-11 07:15 local.txt -rw-rw---- 1 root sdcard_rw 5 2020-04-11 07:20 local2.txt //与上面对比修改时间有更新

复制整个目录到设备,直接传入文件的路径,文件下的所有内容都会被复制到设备中,包括自身目录。
C:\android>adb push D:\test /sdcard/Movies D:\test\: 3 files pushed, 0 skipped. 0.0 MB/s (8 bytes in 0.020s) //查看设备中复制的目录,可以看到test目录也被一起复制进了设备中 generic_x86_arm:/sdcard/Movies/test $ ls -l total 12 -rw-rw---- 1 root sdcard_rw3 2020-04-11 15:15 local.txt -rw-rw---- 1 root sdcard_rw5 2020-04-11 15:20 local2.txt drwxrwx--x 2 root sdcard_rw 4096 2020-04-11 15:29 test2

复制目录下的所有文件到设备指定目录,不复制目录本身,只须在目录后加上一个.即可
C:\android>adb push D:\test\. /sdcard/Music D:\test\.\: 3 files pushed, 0 skipped. 0.0 MB/s (8 bytes in 0.031s) //test目录本身并没有被一起复制进来,只复制test目录下的所有文件 generic_x86_arm:/sdcard/Music $ ls -l total 12 -rw-rw---- 1 root sdcard_rw3 2020-04-11 15:15 local.txt -rw-rw---- 1 root sdcard_rw5 2020-04-11 15:20 local2.txt drwxrwx--x 2 root sdcard_rw 4096 2020-04-11 15:41 test2

5.2 pull [-a] REMOTE… LOCAL
从设备中拉取文件到本地。
  • 可选参数-a,保留文件的时间戳和模式
  • REMOTE… 要拉取的设备文件,可同时摘取多个
  • LOCAL 放置设备文件的本地目录
示例:
//同时拉取两个不同目录的文件到本地目录中 C:\android>adb pull /sdcard/Download/local.txt /sdcard/Music/local2.txt D:/test/pull /sdcard/Download/local.txt: 1 file pulled, 0 skipped. 0.0 MB/s (3 bytes in 0.006s) /sdcard/Music/local2.txt: 1 file pulled, 0 skipped. 0.0 MB/s (5 bytes in 0.002s) 2 files pulled, 0 skipped. 0.0 MB/s (8 bytes in 0.022s) //查看本地目录pull中的文件 C:\android>dir D:\test\pull D:\test\pull 的目录 //文件属性时间就是拉取时的时间点 2020/04/1116:083 local.txt 2020/04/1116:085 local2.txt 2 个文件8 字节

带参数-a拉取文件,并指定新的文件名
//带参数拉取文件,并指定文件名为local_a C:\android>adb pull -a /sdcard/Download/local.txt D:\test\pull\local_a.txt /sdcard/Download/local.txt: 1 file pulled, 0 skipped. 0.0 MB/s (3 bytes in 0.010s)//查看文件 D:\test\pull>dir D:\test\pull 的目录2020/04/1116:083 local.txt 2020/04/1116:085 local2.txt //local_a的时间还是设备中文件属性时间,即是保留了文件的时间戳 2020/04/1115:153 local_a.txt 3 个文件11 字节 2 个目录 205,634,908,160 可用字节

5.3 sync [all|data|odm|oem|product|system|system_ext|vendor]
同步一个设定好的本地目录到设备中,暂未研究明白如何使用。
6.shell 在设备中远程运行shell命令,会单独用一篇文章来介绍可在shell中运行的android命令。
7.app安装 7.1 install [-lrtsdg] [–instant] PACKAGE
向设备中安装单个应用
  • 参数l,前向锁定应用
  • 参数r,覆盖安装应用
  • 参数t,允许测试应用安装,一般是在as上直接点运行生成的apk
  • 参数s,在sdcard上安装应用程序
  • 参数d,允许应用降级安装,versioncode低于已安装的应用时可使用
  • 参数g,授予应用所有运行时权限
  • 参数–instant,作为临时应用安装
示例:
//安装apidemos.apk到设备中 >adb installD:\test\ApiDemos.apk Performing Streamed Install Success //再次安装会报错 Performing Streamed Install adb: failed to install D:\test\ApiDemos.apk: Failure [INSTALL_FAILED_ALREADY_EXISTS: Attempt to re-install com.example.android.apis without first uninstalling.] //加上参数-r可实现覆盖安装 >adb install -rD:\test\ApiDemos.apk Performing Streamed Install Success

7.1.1 关于参数g是否能跳过应用运行时授权的探究 如果安装时加上参数-g是否代表着所有运行时权限都被自动获取了,下面用一个打开相机的案例进行测试。
正常安装,没有进行运行时授权,打开相机时会报错,提示程序没有CAMERA权限。
java.lang.SecurityException: Permission Denial: starting Intent { act=android.media.action.IMAGE_CAPTURE cmp=com.android.camera/.Camera } from ProcessRecord{4a11c78 6853:com.andrognito.pinlockviewapp/u0a356} (pid=6853, uid=10356) with revoked permission android.permission.CAMERA

按下来用adb带-g参数进行安装。
>adb install -r -g D:\test\app-debug.apk Performing Streamed Install adb: failed to install D:\test\app-debug.apk: Security exception: You need the android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flagjava.lang.SecurityException: You need the android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag at com.android.server.pm.PackageInstallerService.createSessionInternal(PackageInstallerService.java:624) at com.android.server.pm.PackageInstallerService.createSession(Package

安装时会报一个错,提示安全异常,需要另一个权限,android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS,下面把这个权限加到清单文件中再次安装。
Android调试必用工具adb命令详解
文章图片

>adb install -g D:\test\app-debug.apk Performing Streamed Install adb: failed to install D:\test\app-debug.apk: Security exception: You need the android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flagjava.lang.SecurityException: You need the android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag at com.android.server.pm.PackageInstallerService.createSessionInternal(PackageInstallerService.java:624) at com.android.server.pm.PackageInstallerService.createSession(Package

依然还是报同样的错误,android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS是一个系统应用才能使用的权限,普通应用是没法获得此权限的,所以除非是系统应用,否则无法用adb install -g绕过应用运行时权限申请的限制。
7.1.2 直接运行as生成的APK为什么别人无法安装 有一种情况是在开发过程中直接在build里边输出的apk文件发给别人是无法安装的,提示的错误如下:
>adb install -r D:\test\test2\app-debug.apk Performing Streamed Install adb: failed to install D:\test\test2\app-debug.apk: Failure [INSTALL_FAILED_TEST_ONLY: installPackageLI]

无法安装的原因在于build中生成的apk是测试专用的,在清单文件的application中多添加了一个属性android:testOnly="true",如下图所示:
Android调试必用工具adb命令详解
文章图片

所以这个应用在别的设备上是无法正常安装的,但可以通过adb添加-t参数进行安装。
>adb install -r -tD:\test\test2\app-debug.apk Performing Streamed Install Success

7.2 install-multiple [-lrtsdpg] [–instant] PACKAGE…
安装一个应用分包成的多个apk,适用于将一个完整的apk分成多个子apk一起安装的场景。
7.3 install-multi-package [-lrtsdpg] [–instant] PACKAGE…
一次性同时安装多个不同的apk。
>adb install-multi-package ApiDemos.apk app-debug.apk adb: failed to create multi-package session Exception occurred while executing: java.lang.IllegalArgumentException: Unknown option --multi-package at com.android.server.pm.PackageManagerShellCommand.makeInstallParams(PackageManagerShellCommand.java:1229) at com.android.server.pm.PackageManagerShellCommand.runInstallCreate(PackageManagerShellCommand.java:273) at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:116) at android.os.ShellCommand.exec(ShellCommand.java:96) at com.android.server.pm.PackageMan D:\test>

多应用安装一直报错,暂时未找到原因。
7.4 uninstall [-k] PACKAGE
卸载应用,参数-k表示保留应用的数据(/data/data/)与缓存(/sdcard/Android/包名).
>adb uninstall com.andrognito.pinlockviewapp Success

8.调试debugging 8.1 bugreport [PATH]
抓取设备的运行日志到本地特定的路径中,默认名是bugreport.zip。
关于此工具的详细说明可参考此篇博客:https://blog.csdn.net/createchance/article/details/51954142
//生成日志数据抓取到本地D盘中的test目录 adb bugreport D:/test/ //默认生成的运行日志在设备上的存放目录如下所示 /data/user_de/0/com.android.shell/files/bugreports/bugreport-natrium-OPR1.170623.032-2020-05-17-15-44-12.zip

Android调试必用工具adb命令详解
文章图片

8.2 jdwp
列出托管JDWP传输的进程的pid。
JDWP: Java Debug Wire Protocol 的缩写,它定义了调试器(debugger)和被调试的 Java 虚拟机(target vm)之间的通信协议,主要用以远程调试JVM。
8.3 logcat
查看设备的日志,与android studio上的logcat工具一样的作用。
可使用logcat --help查看更多的参数。
adb logcat *:E //打印等级为E以上的所有日志

9.安全 security 9.1 disable-verity
在userdebug版本上禁用dm-verity检查
dm-verity是dm(device mapper)的一个target,是一个虚拟块设备,专门用于文件系统的校验
>adb disable-verity disable-verity only works for userdebug builds verity cannot be disabled/enabled - USER build

只能在userdebug版本上使用此命令,android系统编译时可选三种模式
  • user(发行版本),adb默认关闭,无法调试,手机不能root
  • userdebug(调试版本),认打开adb功能,也能调试
  • eng(工程版本),最高权限root
官方详细解释
eng This is the default flavor. A plain make is the same as make eng. *Installs modules tagged with: eng, debug, user, and/or development. *Installs non-APK modules that have no tags specified. *Installs APKs according to the product definition files, in addition to tagged APKs. *ro.secure=0 *ro.debuggable=1 *ro.kernel.android.checkjni=1 *adb is enabled by default. *Setupwizard is optionaluser This is the flavor intended to be the final release bits. *Installs modules tagged with user. *Installs non-APK modules that have no tags specified. *Installs APKs according to the product definition files; tags are ignored for APK modules. *ro.secure=1 *ro.debuggable=0 *adb is disabled by default. *Enable dex pre-optimization for all TARGET projects in default to speed up device first boot-upuserdebug The same as user, except: *Also installs modules tagged with debug. *ro.debuggable=1 *adb is enabled by default.

9.2 enable-verity
在userdebug版本上重新启用dm-verity检查
9.3 keygen FILE
生成adb公钥/私钥; 存储在FILE中的私钥。
>adb keygen D:/test/a.key adb I 05-17 16:19:1781242280 auth.cpp:64] generate_key(D:/test/a.key)...

会在test目录下生成两个文件,一个是a.key,另一个是a.key.pub
10.脚本 scripting 10.1 wait-for[-TRANSPORT]-STATE…
等待设备进入指定的状态中。
STATE 设备状态
  • device, 正常连接设备
  • recovery, 设备复写状态
  • rescue, 系统救援状态
  • sideload, 数据线刷机模式
  • bootloader, 系统启动加载器
  • disconnect,断开连接状态
TRANSPORT 传输协议
  • usb,USB连接
  • local, 连接的端口
  • any [default=any],任意连接
10.2 get-state
获取连接设备的状态,
  • offline离线
  • bootloader加载系统
  • device在线
>adb get-state device

10.3 get-serialno
获取连接设备的序列号
>adb get-serialno 1d0a2131

10.4 get-devpath
获取连接设备的路径
>adb get-devpath unknown

10.5 remount [-R]
重新挂载设备,必须要有root权限才能使用
>adb remount Not running as root. Try "adb root" first

10.6 root/unroot
获取root权限/取消root权限
10.7 reboot [bootloader|recovery|sideload|sideload-auto-reboot]
重启设备,可以选定重启的模式
  • bootloader,系统加载器
  • recovery,恢复出厂设备
  • sideload,线刷模式
  • sideload-auto-reboot
10.8 usb/ tcpip PORT
重启设备adbd的监听端口
11.内部调试 internal debugging 11.1 start-server/kill-server
启动adb服务/杀掉adb服务
11.2 reconnect
【Android调试必用工具adb命令详解】重新连接设备,可选参数
  • device,从设备侧断开连接以强制重新连接
  • offline ,重置离线/未经授权的设备以强制重新连接
>adb kill-server //服务被干掉后,调用adb命令会重新启动服务 >adb devices * daemon not running; starting now at tcp:5037 * daemon started successfully List of devices attached 1d0a2131offline//设备是离线状态,进行重连 >adb reconnect reconnecting 1d0a2131 [offline]>adb devices List of devices attached 1d0a2131device

12.环境变量 environment variables
变量名 说明
$ADB_TRACE 以逗号分隔的调试信息列表,用于记录日志:
$ADB_VENDOR_KEYS 以冒号分隔的键列表(文件或目录)
$ANDROID_SERIAL 要连接的序列号(请参阅-s)
$ANDROID_LOG_TAGS logcat使用的标签(请参阅logcat --help)
$ADB_LOCAL_TRANSPORT_MAX_PORT 最大模拟器扫描端口(默认5585,16个emus)
$ADB_MDNS_AUTO_CONNECT 逗号分隔的mdns服务列表,以允许自动连接(默认为adb-tls-connect)
13.通用选项
参数名 说明
-a 监听所有网络接口,而不仅是本地主机
-d 使用USB设备
-e 使用TCP/IP设备
-s SERIAL 使用特定序列号对应的设备 (覆盖 $ANDROID_SERIAL)
-t ID 使用特定tcp id对应的设备
-H 服务端口名 [default=localhost]
-P 服务端口号 [default=5037]
-L SOCKET 在给定套接字上侦听adb服务器[default = tcp:localhost:5037]

    推荐阅读