Android调试——详细解剖adb的命令

"你知道adb怎么用吗"

Posted by Weiwq on November 3, 2019

写在前面

开始想将标题设置为“深度解剖adb命令,后来犹豫了一下,“深度”,何为 “深度” ? 如同“精通”一词,不敢随意挥写。但是本文会尽力列举adb的相关命令和说明,那就“详细”一词吧!

本文会比较长,各位读者可以挑选自己感兴趣的部分阅读即可。

1、adb官方介绍

Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令便于执行各种设备操作(例如安装和调试应用),并提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。它是一种客户端-服务器程序,包括以下三个组件:

  • 客户端:用于发送命令。客户端在开发计算机上运行。您可以通过发出 adb 命令从命令行终端调用客户端。
  • 守护进程 (adbd):在设备上运行命令。守护进程在每个设备上作为后台进程运行。
  • 服务器:管理客户端和守护进程之间的通信。服务器在开发计算机上作为后台进程运行。

本文不会列出如何搭建,连接adb的步骤,详细可以见 在硬件设备上运行应用

2、adb 基本用法

adb devices -l // 查看已经连接的设备详细信息
adb shell // 进入串口
adb kill-sever // 关闭adb
adb start-server //启动adb 
adb install helloWorld.apk //安装apk
adb connect $device_ip_address //通过网络连接设备IPs
adb pull remote local // 从设备上的文件(夹) 复制到本地 例如: adb pull /sdcard/foo.txt  foo.txt 
adb push local remote // 从本地复制文件(夹)到设备 例如: adb push foo.txt /sdcard/foo.txt
adb root // 获取root权限
adb unroot //    在不使用 root 权限的情况下重新启动 adbd。
adb remount // 挂载,配合adb root使用

比如查看已经连接的设备

  ~ adb devices
List of devices attached
172.19.135.22:5555    device
emulator-5554    device

最新版本的adb是带有port的。如果adb连接多个设备,需要对某一个设备执行操作怎么办?

比如adb shell 操作,可以用 “-s” 指定设备

  ~ adb devices
List of devices attached
172.19.135.22:5555    device
emulator-5554    device

  ~ adb -s 172.19.135.22:5555 shell
root@r34a5:/ #

或者 用“-t” 指定设备对应的transport_id,如下

//通过adb devices -l获取设备的transport_id,如emulator-5554 的transport_id是8
  ~ adb devices -l
List of devices attached
172.19.135.22:5555     device product:r34a5 model:SMART_TV device:r34a5 transport_id:7
emulator-5554          device product:sdk_google_atv_x86 model:sdk_google_atv_x86 device:generic_x86 transport_id:8

  ~ adb -t 8 shell
generic_x86:/ $

3、adb 其他命令解析

命令 说明
adb install [option] <apkFile> -r:替换现有的应用。
-d:降版本安装。
-g:授权所有运行时候需要的权限。
-s:在sdcard上安装。
--abi abi-identifier:针对特定 ABI 强制安装应用。
-t:允许安装测试软件包。如果使用开发者预览版 SDK
(如果 targetSdkVersion 是字母,而非数字)编译 APK,则安装测试 APK 时必须在 install 命令中包含 -t 选项。
adb uninstall [-k] <packageName> 从设备中移除此应用软件包。添加 -k 选项可保存数据和缓存目录。
adb usb 重新启动USB上的adbd监听
adb tcpip <PORT> 重新启动adbd侦听PORT上的TCP
adb reboot [bootloader] [recovery] [sideload] [sideload-auto-reboot] 重新启动设备; 默认启动系统映像,但是也支持引导加载程序和恢复。 侧载重启进入恢复状态并自动启动侧载模式,sideload-auto-reboot相同,但是在侧载后重新启动。
adb reconnect 从主机端剔除连接以强制重新连接
adb reconnect device 从设备强制重新连接。
adb reconnect offline 重置离线/未经授权的设备以强制重新连接
adb connect HOST[:PORT] 通过网络连接设备,默认端口是5555
adb disconnect [HOST[:PORT]] 断开指定的网络连接,不设置host,port,则断开全部
adb backup [option] … 可以通过该命令备份apk或者系统信息,
其中options包含:

-f <file>:指定备份的位置,如-f backup.ab

-all: 备份全部

`-apk
adb restore 恢复应用数据,例如:adb restore backup.ab
adb jdwp 列出可以调试的apk进程

4、shell 命令解析

可以使用如下进入设备

adb [-d | -e | -s serial_number] shell

或者在不进入设备的情况下发出shell命令

adb [-d | -e | -s serial_number] shell shell_command

如果需要退出远程shell命令,可以使用 Ctrl + D 或输入 exit。

shell 命令二进制文件存储在设备的文件系统中,其路径为 /system/bin/。

5、am 命令解析

在shell下,您可以使用 Activity 管理器 (am) 工具发出命令以执行各种系统操作,如启动某项 Activity、强行停止某个进程、广播 intent、修改设备屏幕属性等等。例如发送一个action

am start -a  android.intent.action.VIEW

或者无需进入shell命令

adb shell am start -a  android.intent.action.VIEW

am 更多命令如下

命令 说明
start [options] <intent> 启动 intent 指定的 Activity。 请参阅intent规范
其中options包括

-D:启用调试。

-N: 打开native debug

-W: 获取activity的启动时间

--start-profiler <FILE>:启动分析器并将结果发送到 file

-P <FILE>:类似于 --start-profiler,但当应用进入空闲状态时分析停止。

-R <COUNT>:重复启动 Activity count 次。在每次重复前,将完成顶层 Activity。

-S:启动 Activity 前强行停止目标应用。

--opengl-trace:启用对 OpenGL 函数的跟踪。

--track-allocation: 启用对象分配的跟踪
startservice <intent> 启动 intent 指定的 Service。请参阅intent规范
stopservice <intent> 停止intent指定的service。请参阅intent规范
force-stop <package> 强行停止与 package(应用的软件包名称)关联的所有进程。
kill-all 终止所有后台进程
broadcast [options] <intent> 发出广播 intent。请参阅intent规范
instrument [options] <component> 使用 Instrumentation 实例启动监控。通常情况下,目标 componenttest_package/runner_class 格式。
具体options选项包括:

-r:输出原始结果(否则对 report_key_streamresult 进行解码)。与 [-e perf true] 结合使用以生成性能测量值的原始输出。

-e <NAME> <VALUE>:将参数 name 设为 value。对于测试运行器,通用格式为 -e testrunner_flag value[,value...]

-p <FILE>:将分析数据写入 FILE。

-w:先等待插桩完成,然后再返回。测试运行器需要使用此选项。
profile start process <file> 启动 process 的分析器,将结果写入 file
profile stop process 停止 process 的分析器。
dumpheap [options] process <file> 转储 process 的堆,写入 file
具体options选项包括:
-n:转储原生堆,而非托管堆。
--user [user_id
monitor [options] 开始监控崩溃或 ANR。
具体options选项包括:
--gdb:在崩溃/ANR 时在指定端口上启动 gdbserv。
screen-compat [on|off] <package> 屏幕兼容性
set-debug-app [-w] [--persistent] <PACKAGE> 设置为debug模式。
具体options选项包括:
-w: 当应用起来的时候,等待调试
--persistent: 保留此值
clear-debug-app 清除掉之前设置的debug应用包名
display-size [reset|<width>x<height>] 设置屏幕分辨率的大小
display-density <dpi> 替换设备显示密度。此命令支持使用低密度屏幕在高密度屏幕环境上进行测试(反之亦然),对于在不同密度的屏幕上测试应用非常有用。示例:
am display-density 480
crash <PACKAGE|PID> 获取指定包的crash信息
monitor [--gdb <port>] 开始监视崩溃或ANR。
–gdb:在崩溃/ ANR的给定端口上启动gdbserv
restart 重新启动用户空间系统
to-uri [INTENT] 将指定的intent规范打印为uri
stack [COMMAND] [...] 用于在活动堆栈上运行的子命令。
具体command选项如下:
list:列举所有activity的stack和他们的大小

resize <STACK_ID> <LEFT,TOP,RIGHT,BOTTOM>:改变 STACK_ID的大小到<LEFT,TOP,RIGHT,BOTTOM>,例如:am stack resize 1 0 0 500 500 // STACK_ID可以通过am stack list 获取

remove <STACK_ID>: 从stack list中删除 .
task [COMMAND] [...] 用于操作activity task的子命令。
具体command如下:

lock <TASK_ID> : 将TASK_ID置为前台,并且不让其他stask工作(转为前台),即锁上TASK_ID

lock stop : 将当前的task 锁解锁

resizeable <TASK_ID>
update-appinfo <USER_ID> <PACKAGE_NAME> [...] 为USER_ID更新列举包名的应用信息对象,不需要重新启动包名对应的任何进程

备注

  • USER_ID:可以通过/data/system/users/userlist.xml获取 ,当手机使用者(即User)下载你(即开发者)的应用程序,在安装(Install)时,Android就会给予一个UID。
  • STACK_ID,TASK_ID:可以通过am stack list命令获取
intent规范
命令 说明
-a <action> 指定 intent 操作,例如 android.intent.action.VIEW(只能声明一次)。
-d  指定 intent 数据 URI,例如 content://contacts/people/1(只能声明一次)。
-t <mime_type> 指定 intent MIME 类型,例如 image/png(只能声明一次)。
-c <category> 指定 intent 类别,例如 android.intent.category.APP_CONTACTS
-n <component> 指定带有软件包名称前缀的组件名称以创建显式 intent,例如 com.example.app/.ExampleActivity
-f <flags> 将标记添加到 setFlags() 支持的 intent。
-e|--es <extra_key> <extra_string_value> 将string数据作为键值对添加进来。
--ez <extra_key> <extra_boolean_value> 将布尔型数据作为键值对添加进来。
-ei <extra_key> <extra_int_value> 将整型数据作为键值对添加进来。
--el <extra_key> <extra_long_value> 将长整型数据作为键值对添加进来。
--ef <extra_key> <extra_float_value> 将浮点型数据作为键值对添加进来。
--ecn <extra_key> <component_name_value> 添加组件名称,将其作为 ComponentName 对象进行转换和传递。
--eia <EXTRA_KEY> <INT1,INT2...> 添加int[] 数组。例如:--eia key 1,2,3
--eial <EXTRA_KEY> <INT1,INT2...> 添加List。例如:`--eia key 1,2,3`
--ela <EXTRA_KEY> <LONG1,LONG2...> 添加long类型数组。
--elal <EXTRA_KEY> <LONG1,LONG2...> 添加long类型List。
--efa <EXTRA_KEY> <FLOAT1,FLOAT2..> 添加float数组。
--efal <EXTRA_KEY> <FLOAT1,FLOAT2..> 添加float list。
--esa <EXTRA_KEY> <STRING1,STRING2...> 添加string 数组,例如:--esa key string1,string2
--esal <EXTRA_KEY> <STRING1,STRING2...> 添加string list,例如:--esa key string1,string2
--eu <extra_key> <extra_uri_value> 将 URI 数据作为键值对添加进来。
URI component package 如果不受上述某一选项的限制,您可以直接指定 URI 或软件包名称 或者组件名称。当某个参数不受限制时,如果该参数包含一个“:”(冒号),则该工具会假定参数是一个 URI;如果该参数包含一个“/”(正斜线),则该工具会假定参数是一个组件名称;如果并非这两种情况,则该工具会假定参数是一个软件包名称。
--activity-clear-task 包含标记 FLAG_ACTIVITY_CLEAR_TASK
--activity-single-top 包含标记 FLAG_ACTIVITY_SINGLE_TOP

6、pm 命令解析

跟am命令一样,需要在shell环境下执行

  ~ adb shell
generic_x86:/ # pm uninstall com.example.MyApp //卸载apk

获取已经安装的apk列表

generic_x86_64:/ $ pm -lf
package:/system/priv-app/ProxyHandler/ProxyHandler.apk=com.android.proxyhandler
......

pm详细命令如下:

命令 说明
list packages [options] <filter> 输出所有软件包,或者,仅输出软件包名称包含 filter 中的文本的软件包。
具体options选项:
-f:查看它们的关联文件。
-d:进行过滤以仅显示已停用(disable)的应用。
-e:进行过滤以仅显示已启用(enable)的应用。
-s:进行过滤以仅显示系统应用。
-3:进行过滤以仅显示第三方应用。
-i:查看软件包的安装程序。
-u:还包括卸载的软件包。
--user user_id:要查询的用户空间。
示例:
pm list packages -3 demo // 列举包名包含“demo”的第三方应用
list permission-groups 输出所有已知的权限组。
list permissions [options] <group> 输出所有已知的权限,或者,仅输出 group 中的权限。
具体options选项:
-g:按组进行整理。
-f:输出所有信息。
-s:简短摘要。
-d:仅列出危险权限。
-u:仅列出用户将看到的权限。
示例:
pm list permissions -d // 列举危险权限
list features 列举系统所有功能
list libraries 输出当前设备支持的所有库。
path <package> 输出指定 package APK的安装路径。
示例:
pm path com.demo.mydemo
install [options] <apkPath> 将软件包(通过 path 指定)安装到系统。
具体options选项参考adb install命令
uninstall [options] <package> 从系统中移除软件包。具体选项:
-k:移除软件包后保留数据和缓存目录。
clear <package> 删除与软件包关联的所有数据。
enable <package_or_component> 启用指定软件包或组件(表示为“package/class”,需要root权限)。示例:
pm enable com.cvte.demotv/com.cvte.demotv.MainActivity
disable <package_or_component> 停用指定软件包或组件(表示为“package/class”,需要root权限)。示例:
pm disable com.cvte.demotv/com.cvte.demotv.MainActivity
grant <package_name> <permission> 向应用授予权限。在搭载 Android 6.0(API 级别 23)及更高版本的设备上,该权限可以是应用清单中声明的任何权限。在搭载 Android 5.1(API 级别 22)及更低版本的设备上,该权限必须是应用定义的可选权限。
revoke <package_name> <permission> 从应用中撤消权限。在搭载 Android 6.0(API 级别 23)及更高版本的设备上,该权限可以是应用清单中声明的任何权限。在搭载 Android 5.1(API 级别 22)及更低版本的设备上,该权限必须是应用定义的可选权限。
trim-caches <desired_free_space> 减少缓存文件以达到指定的可用空间。
dump <PACKAGE> 打印与指定包名相关的应用信息
比如查看com.demo.apk 应用的版本号:pm dump com.demo.apk
resolve-activity [–brief] [–components] [–user USER_ID] <INTENT> 通过指定的INTENT 打印对应的activity信息
query-activities [–brief] [–components] [–user USER_ID] <INTENT> 打印所有能处理INTENT 的activities信息
query-services [–brief] [–components] [–user USER_ID] <INTENT> 打印所有能处理INTENT 的service信息
query-receivers [–brief] [–components] [–user USER_ID] <INTENT> 打印所有能处理INTENT 的广播接收者信息
query-services [–brief] [–components] [–user USER_ID] <INTENT> 打印所有能处理INTENT 的service信息
query-receivers [–brief] [–components] [–user USER_ID] <INTENT> 打印所有能处理INTENT 的广播接收者信息
hide/unhide [–user USER_ID] <PACKAGE_OR_COMPONENT> 隐藏/显示 指定的包名(组件名)
reset-permissions 重置所有运行时的权限到默认状态
set-permission-enforced <PERMISSION> [true | false] 设置权限强制执行
uninstall-system-updates 删除系统应用的更新,并回滚应用版本
set-home-activity [–user USER_ID] <TARGET-COMPONENT> 设置home的activity
dump-profiles <TARGET-PACKAGE> 存储 method/class 信息到:
/data/misc/profman/TARGET-PACKAGE.txt
snapshot-profile <TARGET-PACKAGE> [–code-path path] 将指定包名的性能快照文件保存到:
/data/misc/profman/TARGET-PACKAGE[-code-path].prof
如果 TARGET-PACKAGE=android,系统将保存boot 镜像的快照。

7、dpm 命令解析

dmp 即调用设备政策管理器,为便于您开发和测试设备管理(或其他企业)应用,您可以向设备政策管理器 (dpm) 工具发出命令。使用该工具可控制 Active Admin 应用,或更改设备上的政策状态数据。在 shell 中,相应的语法为:

dmp command

或者直接从 adb 发出设备政策管理器命令,无需进入远程 shell:

adb shell dmp command

dmp详细命令如下:

命令 说明
set-active-admin [options] <component> 将组件设置为 Active Admin。具体options选项包括:
--user user_id:指定目标用户。您也可以传递 --user current 以选择当前用户。
set-profile-owner [options] <component> 将组件设置为 Active Admin,并将其软件包设置为现有用户的配置文件所有者。具体options选项包括:
--user user_id:指定目标用户。您也可以传递 --user current 以选择当前用户。
--name name:指定简单易懂的组织名称。
set-device-owner [options] <component> 将组件设置为 Active Admin,并将其软件包设置为设备所有者。具体options选项包括:
--user user_id:指定目标用户。您也可以传递 --user current 以选择当前用户。
--name name:指定简单易懂的组织名称。
remove-active-admin [options] <component> 停用 Active Admin。应用必须在清单中声明 android:testOnly。该命令还会移除设备所有者和配置文件所有者。具体选项包括:
--user user_id:指定目标用户。您也可以传递 --user current 以选择当前用户。

8、其他命令解析

1)截图

screencap` 命令是一个用于对设备显示屏进行屏幕截图的 shell 实用程序。相应的语法为

screencap /sdcard/screen.png // 在shell使用
adb shell screencap /sdcard/screen.png // 通过adb使用

可以使用pull命令将截图文件拉到本地

2)录制视频

screenrecord 命令是一个用于录制设备(搭载 Android 4.4(API 级别 19)及更高版本)显示屏的 shell 实用程序。该实用程序将屏幕 Activity 录制为 MPEG-4 文件。您可以使用此文件创建宣传视频或培训视频,或将其用于调试或测试。

screenrecord /sdcard/demo.mp4 // shell 环境下的命令
adb shell screenrecord /sdcard/demo.mp4 //adb命令

按 Ctrl + C(在 Mac 上为 Command+C)停止屏幕录制,否则,到三分钟或 --time-limit 设置的时间限制时,录制将自动停止。

同理,可以通过pull命令拉取文件

screenrecord 实用程序的局限性:

  • 音频不与视频文件一起录制。
  • 无法在搭载 Wear OS 的设备上录制视频。
  • 某些设备可能无法以它们的本机显示分辨率进行录制。如果在录制屏幕时遇到问题,请尝试使用较低的屏幕分辨率。
  • 不支持在录制时旋转屏幕。如果在录制期间屏幕发生了旋转,则部分屏幕内容在录制时将被切断。

screenrecord命令解析

命令 说明
–size <width>x<height> 设置视频大小:1280x720。默认值是设备的本机显示分辨率(如果支持);如果不支持,则使用 1280x720。为获得最佳效果,请使用设备的 Advanced Video Coding (AVC) 编码器支持的大小。
–bit-rate <rate> 设置视频的视频比特率(以 MB/秒为单位)。默认值为 4Mbps。您可以增加比特率以提升视频品质,但这么做会导致视频文件变大。下面的示例将录制比特率设为 6Mbps:
screenrecord --bit-rate 6000000 /sdcard/demo.mp4
–time-limit <time> 置最大录制时长(以秒为单位)。默认值和最大值均为 180(3 分钟)。
–rotate 将输出旋转 90 度。此功能处于实验阶段。
–verbose 在命令行屏幕显示日志信息。如果您不设置此选项,则该实用程序在运行时不会显示任何信息。

3)获取其他shell命令

可以通过以下命令获取当前系统支持的shell命令

adb shell ls ls system/bin

其他常用shell命令列举

shell命令 说明
dumpsys 将系统数据转储到屏幕。要详细了解此命令行工具,请阅读 dumpsys
dumpstate 将状态转储到文件。
logcat [option]… [filter-spec]… 启用系统和应用日志记录,并将输出显示到屏幕上。另请参阅 android调试——logcat详解
dmesg 将内核调试消息输出到屏幕。
start 启动(重启)设备。
stop 停止执行设备。
sqlite3 启动 sqlite3 命令行程序。sqlite3 工具包含用于输出表格内容的 .dump 以及用于输出现有表格的 SQL CREATE 语句的 .schema 等命令。您也可以随时执行 SQLite 命令。SQLite3 数据库存储在文件夹 /data/data/package_name/databases/ 中。例如:
adb -s emulator-5554 shell
sqlite3 /data/data/com.example.app/databases/rssitems.db
SQLite version 3.3.12
Enter “.help” for instructions

4)打开Wi-Fi连接

在用USB连接设备后,执行如下命令,其中 5555 为端口,可以替换成其他的

adb tcpip 5555 

到设置中查看IP(比如172.18.88.22),然后连接该设备

adb connect 172.18.88.22:5555

9、后记

读者看到最后,心中不免会犯嘀咕——标题不是adb的命令解析吗,怎么会牵扯到am,pm甚至dpm这个听都没有听过的工具?

犯嘀咕是正常的,adb这个工具确实需要我们Android开发者好好学习学习,其本身提供了一些强大的命令,但是更多的命令工具是放在系统system/bin下的,那如何使用系统中的命令工具呢?笔者个人觉得adb shell更像是提供了与系统 交互的窗口,我们可以通过这个窗口,去执行系统中的命令,去让我们的系统更加完美(在我们自己的角度来看)。

—— Weiwq 于 2019.11 广州