概述

Android调试桥(adb)是个很强大的工具,该工具可以管理设备或模拟器的状态。

当启动一个adb客户端时,客户端首先确认是否已有一个adb服务进程在运行。如果没有,则启动服务进程。服务器运行时,adb服务器会绑定本地的TCP端口5037并监听adb客户端发来的命令,所有的adb客户端都是用端口5037与adb服务器对话的。

接着服务器将与所有运行中的模拟器或设备实例建立连接。并通过扫描所有5555到5585范围内的奇数端口来定位所有的模拟器或设备。一旦服务器找到了 adb守护程序,它将建立一个到该端口的连接。任何模拟器或设备实例会取得两个连续的端口,一个偶数端口用来和相应控制台连接,一个奇数端口用来响应 adb连接。

比如说:

模拟器1:控制台端口5554
模拟器1:Adb端口5555
模拟器2:控制台端口 5556
模拟器2:Adb端口5557
……

如上所示,模拟器实例通过5555端口连接adb,就如同使用5554端口连接控制台一样。

一旦服务器与模拟器实例建立连接,就可以使用adb命令控制和访问该实例。因为服务器管理模拟器/设备实例的连接,并可以控制处理来自多个adb客户端来的命令,所以可以通过任何客户端(或脚本)来控制任何模拟器或设备实例。

要注意的是如果用装有ADT插件的Eclipse开发Android程序,就不需要通过命令行使用adb。ADT插件已经透明的把adb集成到Eclipse中了,当然,如果必要的话你也可以仍然直接使用adb,比如说调试。

ADB系统的组成

Android调试系统是一个面对客户服务系统,包括三个组成部分:

ADB-server

运行在PC端,是一个始终在后台运行的进程,作为与手机端交互的唯一接口。ADB-server处理ADB-client的请求,一部分请求无须与设备交 互,直接在PC本地完成;剩下的请求需要与设备端的adbd交互,ADB-server起到了一个switcher的作用。

ADB-client

运行在PC端,可以同时存在多个。每个ADB-client由用户启动,完成多种功能。其作用是与ADB-server交互,实现用户请求的功能。

adbd

运行在设备端的常驻进程,同时只存在一个。作用是接收PC端的ADB-server发来的请求,并作出对应操作。

以上三个可执行程序都是同一套代码编译出来的,位于<Android Source Dir>/system/core/adb/

ADB-client和ADB-server对应同一个可执行文件“adb(.exe)”,编译时有-DADB_HOST=1宏。而adbd对应目标设备上的可执行文件”adbd”,编译时的参数是-DADB_HOST=0。

ADB主要功能

Adb主要可以实现以下功能:

  • 在设备上运行shell命令
  • 通过端口转发来管理模拟器或设备
  • 在模拟器或设备上拷出或拷入文件

ADB命令详述

命令行格式

可以在开发机上的命令行或脚本上发布ADB命令,使用方法:

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

发出一个命令后,系统会启动ADB客户端。客户端并不与模拟器实例相关,所以如果双服务器/设备是运行中的,需要用-d选项去为应被控制的命令确定目标实例。关于使用这个选项的更多信息,可以查看模拟器/设备实例术语控制命令。

查询模拟器/设备实例

在发送adb命令之前,有必要知道什么样的模拟器/设备实例与adb服务器是相连的。可以通过使用devices命令来得到一系列相关联的模拟器/设备:

adb devices

作为回应,adb为每个实例都制定了相应的状态信息:

  • 序列号:由adb创建的一个字符串,这个字符串通过自己的控制端口<type>-<consolePort> 唯一地识别一个模拟器/设备实例。下面是一个序列号的例子:emulator-5554
  • 实例的连接状态有三种状态:
    • offline 此实例没有与adb相连接或者无法响应.
    • device 此实例正与adb服务器连接。注意这个状态并不能百分之百地表示在运行和操作Android系统,因此这个实例是当系统正在运行的时候与adb连接的。然而,在系统启动之后,就是一个模拟器/设备状态的正常运行状态了.

每个实例的输出都有如下固定的格式:

[serialNumber] [state]

下面是一个展示devices 命令和输出的例子 :

$ adb devices
List of devices attached 
emulator-5554  device
emulator-5556  device
emulator-5558  device

如果当前没有模拟器/设备运行,adb则返回 no device。

给特定的模拟器/设备实例发送命令

如果有多个模拟器/设备实例在运行,在发布adb命令时需要指定一个目标实例。这样做,需使用-s 选项的命令。在使用的-s 选项是

adb -s <serialNumber> <command> 

如上所示,给一个命令指定了目标实例,这个目标实例使用由adb分配的序列号。你可以使用devices命令来获得运行着的模拟器/设备实例的序列号。

示例如下:

adb -s emulator-5556 install helloWorld.apk

利用ADB安装软件

可以adb的install命令从开发电脑上复制一个应用程序,并且将其安装在一个模拟器/设备实例上。这个install命令要求指定所要安装的.apk文件的路径,命令格式如下:

adb install <path_to_apk>

如果使用Eclipse IDE并且已经安装过ADT插件,那么不需要直接使用adb(或者aapt)来安装模拟器/设备的应用程序,ADT插件将会全权处理应用程序的打包和安装。

在模拟器/设备上拷入或拷出文件

可以使用 adb pull 命令从一个模拟器/设备实例中拷出文件;使用 adb push 命令将文件复制到一个模拟器/设备实例中。install 命令是将一个.apk文件复制到一个特定的位置,而pull和push命令可以复制任意的目录和文件到一个模拟器/设备实例的任何位置。

从模拟器或者设备中复制文件或目录,使用(如下命):

adb pull <remote> <local>

将文件或目录复制到模拟器或者设备,使用(如下命令)

adb push <local> <remote>

在这些命令中,<local>和<remote>分别自己的开发机(本地)和模拟器/设备实例(远程)上的目标文件/目录的路径。

下面是一个例子::

adb push foo.txt /sdcard/foo.txt

利用ADB重启设备

可以使用reboot重启设备:

adb reboot [bootloader|recovery] 

利用ADB转发端口

可以使用forward命令进行任意端口的转发。即通过模拟器/设备实例的某一特定主机端口向另一不同端口的转发请求。下面演示了如何建立从主机端口6100到模拟器/设备端口7100的转发。

adb forward tcp:6100 tcp:7100

同样地,也可以使用adb来建立命名为抽象的UNIX域套接口,如:

adb forward tcp:6100 local:logd 有待验证

转发过程说明

PCDevice
[ADB-client]↔[Port A:] [:Port A']↔[Program A]
[ADB-client]↔[Port B:] ADB-server↔adbd [:Port B']↔[Program B]
[ADB-client]↔[Port C:] [:Port C']↔(empty)
← Android Debug Bridge →

ADB提供了PC与设备交互的桥梁,结构上清晰明了。其中adb forward功能提供了端口映射,希望给用户提供透明的socket通信。但可惜,这与真实的网络socket有点区别。

在TCP网络编程中,Client的Socket如果调用Connect()成功,就说明已经和Server端的Socket连接上,可以通讯了。但是如果使用adb forward做端口映射就有些不同了。

这里端口映射的实质,是让ADB-server作为一个switcher转发ADB-client的数据包,送给adbd,adbd再发给设备端的对应端 口。因此一旦建立了映射,就相当于ADB-server开始监听这个目标端口。而此时如果有客户端去尝试Connect这个端口,是一定会成功的,因为与 客户端连接的是ADB-server,而非真正的设备上的目标程序。这就出现了即使Connect()成功,却完全无法知道究竟是否成功连接到设备上的服 务程序的情况。

因此,判断真正连接成功的方法,只有收发握手数据包。程序中约定好事先做个交互:客户端发送一个数据包,等待设备上的服务程序回复。客户端如果收到了回复 包,说明连通,如果接收超时,则认为没有连通。在没有连通的情况下,需要重新建立Socket,并Connect(),然后再尝试握手。

ADB命令列表

分类命令描述说明
选项 -d 仅仅通过USB接口来管理abd。 如果不只是用USB接口来管理则返回错误。
-e 仅仅通过模拟器实例来管理adb。 如果不是仅仅通过模拟器实例管理则返回错误。
-s <serialNumber> 通过模拟器/设备的标识号码来发送命令来管理adb (比如: “emulator-5556”)。 如果没有指定号码,则会报错
通用 devices 查看所有连接模拟器/设备的清单。 查看Querying for Emulator/Device Instances 获取更多相关信息。
help 查看adb所支持的所有命令。
version 查看adb的版本序列号。
调试 logcat [<option>] [<filter-specs>] 将日志数据输出到屏幕上。
bugreport 查看bug的报告,如dumpsys,dumpstate,和logcat信息。
jdwp 查看指定的设备可用的JDWP信息。 可以用forward jdwp:<pid> 端口映射信息来连接指定的JDWP进程.例如:
adb forward tcp:8000 jdwp:472
jdb -attach localhost:8000
数据 install <path-to-apk> 安装Android应用
pull <remote> <local> 将指定的文件从模拟器/设备的拷贝到电脑上
push <local> <remote> 将指定的文件从电脑上拷贝到模拟器/设备中
网络 forward <local> <remote> 用本地指定的端口通过socket方法远程连接模拟器/设备 端口 需要描述下列信息:
* tcp:<portnum>
* local:<UNIX domain socket name>
* dev:<character device name>
* jdwp:<pid>
ppp <tty> [parm]… 通过USB运行ppp * <tty> — the tty for PPP stream. For example dev:/dev/omap_csmi_ttyl
* [parm]… &mdash zero or more PPP/PPPD options, such as defaultroute , local , notty , etc.
注:不能自动启动PDP连接.
脚本 get-serialno 查看adb实例的序列号。 查看Querying for Emulator/Device Instances可以获得更多信息
get-state 查看模拟器/设备的当前状态。
wait-for-device 如果设备不联机就不让执行,也就是实例状态是device时,可以提前把命令转载在adb的命令器中,命令器中的命令在模拟器/设备连接之前不会执行其它命令。 示例如下:
adb wait-for-device shell getprop
注:这些命令在所有的系统启动起来之前不会启动adb,所以在所有的系统启动起来之前也不能执行其它的命令。比如:运用install的时候就需要Android包,这些包需要系统完全启动。例如:
adb wait-for-device install <app>.apk
上面的命令只有模拟器/设备连接上了adb服务才会被执行,而在Android系统完全启动前执行就会有错误发生。
服务器 start-server 启动adb服务进程
kill-server 终止adb服务进程
Shell shell 通过远程shell命令来控制模拟器/设备实例
shell [<shellCommand>] 连接模拟器/设施执行shell命令,执行完毕后退出远程shell。
posted on 2011-10-21 10:12  情定诺坎普  阅读(371)  评论(0编辑  收藏  举报