Android* 操作系统上的应用程序远程调试


Android* 操作系统应用程序远程调试

Android* Debug Bridge

Android Debug Bridge (ADB) 是一种命令行工具,可处理主机上的调试程序(通常为 GDB* 或 DDMS*(Dalvik* 调试监测程序服务器)以及 ADT)和目标上运行的 Android* 映像之间的调试通信。 目标映像可运行在模拟设备上或实体开发设备(通过 USB-OTG (On-The-Go) 或 USB 转以太网适配器与其通信)上。 简而言之,ADB 是一座桥梁,让调试 Android* 上的应用程序成为可能。

您所连接或模拟的设备涉及大量形状因素。 通常设备可能是智能手机或平板电脑。 也可以是医疗用平板电脑或工业、家庭能源管理、仓储领域或任意数量智能系统应用程序的嵌入式设备。

设置 Android Debug Bridge 可让基于英特尔® 凌动TM处理器的平台的远程调试与其他架构上的调试不会有太大差别。

首先需要在开发主机上安装包含 ADB* 的 Android* SDK。 有关这方面的说明请参阅 http://developer.android.com/sdk/installing.html

设置 ADB*

如果目标映像运行在物理设备上,则首先需要支持 USB-OTG 或 USB 转以太网。 要支持 USB 转以太网,需要重新构建内核配置。 如果需要,您的原始设备制造商将为您提供必要信息。

远程应用程序调试的标准方法是使用大多数 Android 设备的现有 USB-OTG 接口。 在 Android* 开发人员网站上对该设置有详细说明: http://developer.android.com/guide/developing/device.html

在此概述一下主要步骤

1.      在 Android Manifest 中将您的应用程序声明为“可调试”。

在使用 Eclipse 时,可跳过该步骤,因为直接从 Eclipse IDE 运行应用程序时会自动启用调试。

AndroidManifest.xml 文件中将 android:debuggable="true" 添加至 <application> 元素。

注:如果在清单文件中手动启用调试,在进行构建以发布之前务必先禁用它(您发布的应用程序通常应该可调试)。

2.      打开设备上的“USB 调试”。

在设备上,转至“设置 > 应用程序 > 开发”并启用“USB 调试”(在 Android 4.0 设备上,设置路径为“设置 > 开发人员选项”)。

3.      设置系统以检测设备。

o   如果在 Windows 上开发,则需要安装 adb 的 USB 驱动程序。 有关安装指南和原始设备制造商驱动程序的链接,请参阅OEM USB Drivers文档。

o   如果在 Mac OS* X 上开发,则无需操作。 可直接跳过该步骤。

o   如果在 Ubuntu* Linux* 上开发,则需要添加一个 udev 规则文件,该文件包含要用于开发的每种设备的 USB 配置。 在规则文件中,通过唯一的供应商 ID 表示每个设备制造商,该 ID 通过 ATTR{idVendor} 属性指定。 要查看供应商 ID 的列表,请参阅 USB Vendor IDs。 要在 Ubuntu Linux 上设置设备检测:

以超级用户身份登录并创建该文件: /etc/udev/rules.d/51-android.rules

按照下列格式将厂商添加至文件:
SUBSYSTEM=="usb", ATTR{idVendor}=="<vendor id>", MODE="0666", GROUP="plugdev"

注: 该规则语法可能根据您的环境而稍有不同。 可根据需要参阅您所用系统的 udev 文档。 有关规则语法的概述,请参阅指南编写 udev 规则

现在执行:
chmod a+r /etc/udev/rules.d/51-android.rules

在通过 USB 插入时,可通过从 SDK platform-tools/ 目录执行 adb devices 验证设备是否已连接。 如果已连接,将看到设备名称作为“设备”列出。

对于 CDK 上引导的 Android 操作系统,将一根 USB-OTG 电缆连接至 CDK 上的(USB 微型 b)端口,将电缆的另一端 (USB A) 连接至开发主机。

如果一切都正常,就能够运行以下命令看到已连接设备:

$ adb devices

* daemon not running. starting it now *

* daemon started successfully *

List of devices attached

0123456789ABCDEF  device                                                       

注: 要了解将哪个设备名分配给了 Linux 开发主机上的该连接,可查看 dmesg 查找“usb-storage: device found at <num>”的地址然后进行“ls -l /dev/bus/usb/*”列表来查找该数字。

 

Windows 上的 ADB*

http://www.eclipse.org/downloads/ 下载并安装 Eclipse Classic

http://developer.android.com/sdk/index.html 下载用于 Windows* 的 Android* SDK 包。 (android-sdk_r18-windows.zip 或 installer_r18-windows.exe)。

在安装 Android* SDK 后,adb.exe 将位于 <install-dir>\android-sdk\platform-tools

 

ADB 主机-客户端通信

至此我们关注的是在开发主机上安装 ADB。 在现实中,它是客户端-服务器程序,具有三个组件:

一个客户端,运行于开发主机上。 可通过执行 adb 命令从 shell 调用客户端。 其他诸如 ADT 插件和 DDMS 的 Android 工具也能创建 adb 客户端。

一个服务器,作为后台进程运行于开发主机上。 服务器管理客户端和运行于模拟器或设备上的 adb 守护程序之间的通信。

一个守护程序,作为后台进程运行于每个模拟器或设备实例上。

在启动 adb 客户端时,客户端会先检查是否已经有 adb 服务器进程正在运行。 如果没有,则会启动服务器进程。 当服务器启动时,它会绑定至本地 TCP 端口 5037 并监听从 adb 客户端发出的命令,所有 adb 客户端都使用端口 5037 与 adb 服务器通信。

然后服务器会建立与所有正在运行的模拟器/设备实例的连接。 它会通过在范围 5555 至 5585(模拟器/设备使用的范围)中扫描奇数编号的端口找到模拟器/设备实例。 在找到 adb 守护程序处,建立与该端口之间的连接。 请注意,每个模拟器/设备实例获取一对序列端口 - 一个偶数编号的端口用于控制台连接,一个奇数编号的端口用于 adb 连接。 例如:

 Emulator 1, console: 5554

 Emulator 1, adb: 5555

 Emulator 2, console: 5556

 Emulator 2, adb: 5557 ...

如示例所示,在端口 5555 上连接至 adb 的模拟器实例与控制台监听端口 5554 的实例相同。

一旦服务器建立与所有模拟器实例之间的连接,就可使用 adb 命令来控制和访问那些实例。 由于服务器会管理指向模拟器/设备实例的连接并处理来自多个 adb 客户端的命令,您可通过任何客户端(或脚本)控制任何模拟器/设备实例。

 

启动 ADB 

键入 "adb shell"。 将得到一个 # 号来指示连接成功。

$ adb shell

 

主要 ADB 设备命令 

下面所列的命令可帮助将接受调试的应用程序从命令行转移至目标设备或模拟设备。 这点非常有用,尤其是在没有 ssh 终端连接可用时。

  adb push <local> <remote>    - copy file/dir to device

  adb pull <remote> [<local>]  - copy file/dir from device

  adb sync [ <directory> ]     - copy host->device only if changed

                                 (-l means list but don't copy)

                                 (see 'adb help all')

  adb shell                    - run remote shell interactively

  adb shell <command>          - run remote shell command<

  adb emu <command>            - run emulator console command<

  adb logcat [ <filter-spec> ] - View device log

  adb forward <local> <remote> - forward socket connections forward specs are one of:<tcp:<port>>

                                  localabstract:<unix domain socket name>

                                  localreserved:<unix domain socket name>

                                  localfilesystem:<unix domain socket name>

                                   dev:<character device name>

                                   jdwp:<process pid> (remote only)

  adb jdwp                     - list PIDs of processes hosting a JDWP transport

  adb install [-l] [-r] [-s] <file> - push this package file to the device and install it

                                 ('-l' means forward-lock the app)

                                 ('-r' means reinstall the app, keeping its data)

                                 ('-s' means install on SD card instead of internal storage)

  adb uninstall [-k] <package> - remove this app package from device

                                 ('-k' means keep the data and cache directories)

有关 adb 设置和使用的详细信息请参阅 http://developer.android.com/guide/developing/tools/adb.html

 

借助 GDB* - The GNU Project Debugger 调试 C/C++ 原生代码 

在使用 GDB 进行调试时,运行于设备上的 gdbserver 用于处理调试通信,但您仍可将基本 USB 转以太网适配器用于 ADB 以处理通信传输层,在该层上 gdbserver 借助 tcp/ip 协议并在 GDB 运行于开发主机上的情况下进行通信。

有一个 gdbclient 应用程序,其可设置调试通信环境并在进行程序调试的设备上启动 gdbserver。

usage: gdbclient EXECUTABLE :PORT [PROG_PATH]

EXECUTABLE  executable name (default app_process)

PORT  commection port (default :1234)

PROG_PATH   executable full path on target (ex /system/bin/mediaserver)

如果设置了 PROG_PATH,gdclient 会尝试启动 gdbserver 并将其附加至运行的 PROG_PATH

要明确启动 gdbserver,可使用以下命令

# gdbserver :1234 --attach 269

Attached; pid = 269

Listening on port 1234

 

下面的逐步调试会话启动指令展示了 ADB 如何在将 GDB 而非 ADT 或 DDMS 用于调试的情况下仍然作为调试通信的基础。 让我们假定使用的是端口 1234。

启动进程:

gdbserver :1234 /system/bin/executable

或附加至现有进程:

gdbserver :1234 --attach pid

在您的工作站上,使用 adb 将端口 1234 转发至设备:

adb forward tcp:1234 tcp:1234


启动位于源代码树 "prebuilt" 区域中的特殊版本 gdb:

prebuilt/Linux/toolchain-eabi-4.x.x/bin/i686-android-linux-gdb (for Linux)

prebuilt/darwin-x86/toolchain-eabi-4.x.x/bin/i686-android-linux-gdb (for Darwin)

 

如果两个特殊版本的 gdb 都无法找到,运行 find prebuilt -name i686-android-linux-gdbin your source tree 来查找并运行最新版本。

务必使用符号目录中而非主要 android 目录中可执行文件的副本,因为主要目录中的副本已去除了符号信息。

在 GDB 中,告知 GDB 何处查找将要加载的共享库:

set solib-absolute-prefix /absolute-source-path/out/target/product/product-name/symbols

set solib-search-path /absolute-source-path/out/target/product/product-name/symbols/system/lib

absolute-source-path 为您的源代码树的路径。

 

确保指定正确的目录 – 如果您弄错目录 GDB 可能不会告知您。

通过发出 GDB 命令连接至设备:

(gdb) target remote :1234

:1234 告知 gdb 连接至本地主机端口 1234,后者通过 adb 桥接至设备。

现在可以用和之前相同的方式使用 GDB 开始调试运行于 Android* 上的 C/C++ 代码。

有关详细信息,请参阅文档 GDB* - The GNU Project Debugger

 

使用 Eclipse* 的 ADT* 插件来调试 Android* 应用程序

对于基于英特尔® 架构的设备,设置流程可参照下列类似链接:http://developer.android.com/sdk/eclipse-adt.html#installing。 

对于基于英特尔® 架构的模拟器以及目标设备,ADT* 插件可提供完整的集成 Eclipse* IDE 的应用程序调试。 它使用不同的功能集提供两种不同的调试视图。

您可根据需要选用其中一个,在调试应用程序时二者都可提供不同的强度。



Eclipse 中的调试视图*  

Eclipse 中调试视图可让您访问以下选项卡:

调试 – 显示之前和当前调试的 Android 应用程序及其当前运行的线程

变量 – 在设置了断点时,显示代码执行期间的变量值

断点 – 显示您的应用程序代码中设置的断点列表

LogCat – 可让您实时查看系统日志信息。 LogCat 选项卡也可在 DDMS 视图中使用。

 

通过单击 Window(窗口)> Open Perspective(打开视图)> Debug(调试)可访问调试视图。 有关 Eclipse 调试程序的详细信息,请参阅相应文档。

 

DDMS 视图

Eclipse 中的 DDMS 视图可让您在 Eclipse IDE 中访问 DDMS 的所有功能。 您可使用 DDMS 的以下部分:

设备 – 显示连接至 ADB 的设备和 AVD 列表。

模拟器控制 – 让您执行设备功能。

LogCat – 让您实时查看系统日志信息。

线程 – 显示虚拟机中当前运行的线程。

堆区 – 显示虚拟机的堆区使用。

分配跟踪器 – 显示对象的内存分配。

文件管理器 – 可让您探索设备的文件系统。

 

用于调试的应用程序运行时环境

调试为基于英特尔® 架构的设备设计的 Android* 应用程序的不同之处在于何时设置调试目标设备。

使用属于 Android* SDK 一部分的 Android* 虚拟设备管理器选择目标设备,转到 Eclipse* IDE 下拉菜单中的 Window(窗口)> AVD Manager(AVD 管理器)。 在此您需要确保选择英特尔凌动作为操作系统镜像和设备模拟的 EABI 目标。

avd_intel.jpg

如果遵照本文开始概述的有关设置 ADB* 和建立指向物理设备的调试桥的步骤,就会看到 Eclipse IDE 中的设备选择器界面,从中可选择用于应用程序开发和调试的目标。

device_chooser.jpg

除此之外,为基于英特尔® 架构的设备设计的 Android* 应用程序和为 ARM* 架构设计的 Android* 应用程序在调试上确实存在着差别。

http://developer.android.com/guide/developing/debugging/index.html 中概述的内容都适合供您参考。