Android Debug Bridge

Android Debug Bridge

XIANZHEZ: 关于ADB的工作方式简介其实看developer的介绍(https://developer.android.com/studio/command-line/adb.html#howadbworks)就足够了。
本文基于developer上的介绍以及开发经验做一个简单的总结,用于备忘查阅。

基本介绍

Android Debug Bridge(adb)是一个功能强大的命令行工具,可以用于连接Android设备或emulator。尤其是在Android开发过程中可以起到很大的帮助作用。Android Studio等IDE以及一些常用工具(如DDMS)都会用到adb。

adb是一个CS结构的程序,它包括三部分:

  • Client: 用于发送命令。client运行在host上,即开发机上。实际上,使用adb命令时,就可以视为一个client。IDE、DDMS都可以视为一个client。
  • Daemon:运行在Android设备中。Daemon作为后台线程运行于Android设备中。
  • Server:运行在host上,用于管理client和daemon之间的通讯。

工作方式

当开启一个client时, client会去检查是否有server线程在运行,如果没有,则开启server线程。当server开启后,server会绑定本地TCP端口5037,并监听所有client发往5037端口的所有命令。也就是说,所有的client都是通过5037端口和server进行通讯。

Server会和所有连接的Android设备建立通讯连接。它会扫描 5555 ~ 5585之间所有的奇数端口(也就是说最多可以连接16台设备)。如果在奇数端口发现有daemon进程,则和该端口建立通讯。每台Android设备会同时占用两个端口,相邻的一奇一偶端口,偶数端口用于console的连接,奇数端口用于adb连接。如:

  • Emulator 1, console: 5554
  • Emulator 1, adb: 5555
  • Emulator 2, console: 5556
  • Emulator 2, adb: 5557
  • ...

当运行emulator时我们可以看到默认的设备名称为5554等等。

使用ADB

使用adb时,首先要在Android设备上打开开发者选项中的USB debugging。

语法

adb [-d|-e|-s <serialNumber>] <command>

如果只有一台android设备连接到host,则不需要指定serialNumber,否则就需要先使用adb devices查看当前已连接的设备,并通过-s或-e或-s指明需要建立通讯的设备。

命令

Target device

一般-s会用的比较多

Command Description Comments
-d Direct an adb command to the only attached USB device. Returns an error if more than one USB device is attached.
-e Direct an adb command to the only running emulator instance. Returns an error if more than one emulator instance is running.
-s <serialNumber> Direct an adb command a specific emulator/device instance, referred to by its adb-assigned serial number (such as "emulator-5556").

General

一般只会用到adb devices

Command Description Comments
devices Prints a list of all attached emulator/device instances.
help Prints a list of supported adb commands.
version Prints the adb version number.

Debug

平常用的最多的就是logcat命令,在后面详细介绍

Command Description Comments
logcat [option] [filter-specs] Prints log data to the screen.
bugreport Prints dumpsys, dumpstate, and logcat data to the screen, for the purposes of bug reporting.
jdwp Prints a list of available JDWP processes on a given device.

Data

这些命令可以很方便地用于在host和device之间传输文件,安装apk。

Command Description Comments
install <path-to-apk> Pushes an Android application (specified as a full path to an .apk file) to an emulator/device.
pull <remote> <local> Copies a specified file from an emulator/device instance to your development computer.
push <local> <remote> Copies a specified file from your development computer to an emulator/device instance.

Ports and Networking

这部分用到较少,会在一些特殊的情境中使用,如模拟两台device之间的连接通讯。更多的可以去查阅官方文档。之前在做MultiDevice项目时用到过,使两台emulator进行互相通讯。

Command Description Comments
forward <local> <remote> Forwards socket connections from a specified local port to a specified remote port on the emulator/device instance. Port specifications can use these schemes: tcp:<portnum>, local:<UNIX domain socket name>, dev:<character device name>, jdwp:<pid>
ppp <tty> [parm]...

Scripting

用到的较少。

Command Description Comments
get-serialno Prints the adb instance serial number string.
get-state Prints the adb state of an emulator/device instance.
wait-for-device Blocks execution until the device is online — that is, until the instance state is device.

Server

用于启动和关闭server,当感觉adb工作不太正常时,可以尝试kill掉server,然后重启server。

Command Description Comments
start-server Checks whether the adb server process is running and starts it, if not.
kill-server Terminates the adb server process.

Shell

这部分使用较多,也可以利用shell获取很多有用的信息,后面会简单介绍dumsys命令。更多的可以查阅adb shell命令介绍

Command Description Comments
shell Starts a remote shell in the target emulator/device instance.
shell [shellCommand] Issues a shell command in the target emulator/device instance and then exits the remote shell.

实用命令简介

adb logcat

可以看到adb logcat的帮助介绍如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Usage: logcat [options] [filterspecs]
options include:
-s Set default filter to silent.
Like specifying filterspec '*:s'
-f <filename> Log to file. Default to stdout
-r [<kbytes>] Rotate log every kbytes. (16 if unspecified). Requires -f
-n <count> Sets max number of rotated logs to <count>, default 4
-v <format> Sets the log print format, where <format> is one of:
brief process tag thread raw time threadtime long
-c clear (flush) the entire log and exit
-d dump the log and then exit (don't block)
-t <count> print only the most recent <count> lines (implies -d)
-g get the size of the log's ring buffer and exit
-b <buffer> Request alternate ring buffer, 'main', 'system', 'radio'
or 'events'. Multiple -b parameters are allowed and the
results are interleaved. The default is -b main -b system.
-B output the log in binary
filterspecs are a series of
<tag>[:priority]
where <tag> is a log component tag (or * for all) and priority is:
V Verbose
D Debug
I Info
W Warn
E Error
F Fatal
S Silent (supress all output)
'*' means '*:d' and <tag> by itself means <tag>:v
If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.
If no filterspec is found, filter defaults to '*:I'
If not specified with -v, format is set from ANDROID_PRINTF_LOG
or defaults to "brief"

可能最有用的就是-f-v-f命令在shell中也可以用>来代替(我更习惯这么做)。下面简单介绍下-v

可以看到介绍中写到,-v后可以接一个format,format可以是以下几种形式,其中threadtime较为有用:

  • brief
  • process
  • tag
  • thread
  • raw
  • time
  • threadtime :较为常用,可以打印log的时间和线程信息
  • long

adb shell dumpsys

使用shell的dumsys命令可以获取很多信息。可以使用命令:

adb shell dumpsys | grep "DUMP OF SERVICE"

使用该命令可以列出dumsys可以获取的所有信息,大致形式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
... ...
DUMP OF SERVICE AtCmdFwd:
DUMP OF SERVICE CustomFrequencyManagerService:
DUMP OF SERVICE DirEncryptService:
DUMP OF SERVICE Exynos.HWCService:
DUMP OF SERVICE Exynos.IPService:
DUMP OF SERVICE FMPlayer:
DUMP OF SERVICE LEDService:
DUMP OF SERVICE SecTVOutService:
DUMP OF SERVICE SurfaceFlinger:
DUMP OF SERVICE TvoutService_C:
DUMP OF SERVICE accessibility:
DUMP OF SERVICE account:
DUMP OF SERVICE activity:
DUMP OF SERVICE alarm:
DUMP OF SERVICE android.security.keystore:
DUMP OF SERVICE application_policy:
DUMP OF SERVICE appops:
DUMP OF SERVICE appwidget:
DUMP OF SERVICE audio:
DUMP OF SERVICE backup:
DUMP OF SERVICE battery:
DUMP OF SERVICE batteryinfo:
... ...

我们可以使用以下格式来获取我们想要的信息:

adb shell dumsys [option]

option可以是上面列出所有选项,也都可以在后面加-h查看帮助介绍,常用的一些选项有:

option 介绍
account 显示accounts信息
activity 显示所有的activities的信息
cpuinfo 显示CPU信息
window 显示键盘,窗口和它们的关系
wifi 显示wifi信息
batteryinfo $package_name 电量信息及CPU 使用时长
package packagename 获取安装包信息
usagestats 每个界面启动的时间
statusbar 显示状态栏相关的信息
meminfo 内存信息(meminfo $package_name or $pid 使用程序的包名或者进程id显示内存信息)
diskstats 磁盘相关信息
battery 电池信息
alarm 显示Alarm信息

尤其是activity、window、package、meminfo等这些较为常用,也可以给开发带来很多便利。比如,在想要查看刚刚在设备上启动的是哪一个activity以及它具体的名称,就可以很快的通过activity来获取栈信息,并且能查看到启动它的intent信息。会有很多便利。