基本语法
基本语法
adb [-d|-e|-s <serialNumber>] <command>
# serialNumber表示设备序列号,也可以是ip地址
# 如果只有一个设备/模拟器连接时,可以省略掉 [-d|-e|-s <serialNumber>] 这一部分,直接使用 adb <command>。
为命令指定目标设备
上述三个参数(-d -s -e)用于指定设备,如果有多个设备/模拟器连接,需要为命令指定目标设备,否则鬼知道你要操作哪台设备。
- -d:指定当前唯一通过 USB 连接的 Android 设备为命令目标
- -e:指定当前唯一运行的模拟器为命令目标
- -s <serialNumber>:指定相应 serialNumber 号的设备/模拟器为命令目标
在多个设备/模拟器连接的情况下较常用的是-s <serialNumber>参数,serialNumber为设备到序列号,设备连接上电脑后可以通过 adb devices 命令获取
例如,我的设备为乐视1s,运行后可得到:
$ adb devices
List of devices attached
KFNJG68SQKAE7LQG device
xxxxx device # 手工伪造的设备号
yyyyy device # 手工伪造的设备号 # KFNJG68SQKAE7LQG 为乐视1s的设备号(serialNumber)
此时通过adb查看乐视1s的屏幕分辨率
adb -s KFNJG68SQKAE7LQG shell wm size
启动/停止adb
adb start-server # 启动(一般无需手动执行此命令,在运行 adb 命令时若发现 adb server 没有启动会自动调起。)
adb kill-server # 停止
adb version # 查看adb版本号
以 root 权限运行 adbd
adb 的运行原理是 PC 端的 adb server 与手机端的守护进程 adbd 建立连接,然后 PC 端的 adb client 通过 adb server 转发命令,adbd 接收命令后解析运行。
所以如果 adbd 以普通权限执行,有些需要 root 权限才能执行的命令无法直接用 adb xxx 执行。这时可以 adb xxx 然后 su 后执行命令,也可以让 adbd 以 root 权限执行,这样就能随意执行高权限命令了。
命令:
adb root # 正常输出:restarting adbd as root
adb unroot # 取消root权限
现在再运行 adb shell ,命令行提示符变成 # 即为root权限
有些手机 root 后也无法通过 adb root 命令让 adbd 以 root 权限执行,比如三星的部分机型,会提示 adbd cannot run as root in production builds,此时可以先安装 adbd Insecure,然后 adb root 试试。
adbd Insecure下载地址:戳这里,下载后打开应用将Enable insecure adbd 和 enable at boot 勾选上,设置好之后重进键入:adb root即可
指定 adb server 的网络端口
adb -P <port> start-server # 默认端口为 5037。
设备连接
设备连接的功能分为 查看设备连接 和 连接设备 ,其中 连接设备 又分为 有USB连接 和 无USB连接
- 有USB连接 —— 直接通过USB线连接
- 无USB连接
- 设备先前通过USB线连过电脑 —— 通过IP地址连接
- 设备从没连过电脑 —— 需要root权限,并且在安卓上安装一个模拟器如Terminal Emulator for Android Downloads
详细操作步骤:ADB——连接手机的三种方式
模拟按键输入
常用操作主要有电源键、菜单键、home键、返回键、触击屏幕、滑动屏幕等等。
adb shell input keyevent 26 # 电源键
adb shell input keyevent 82 # 菜单键
adb shell input keyevent 3 # HOME 键
adb shell input keyevent 4 # 返回键
adb shell input keyevent 24 # 音量+
adb shell input keyevent 25 # 音量-
adb shell input keyevent 164 # 静音
电源键、菜单键、HOME键、返回键、音量加减、静音
adb shell input keyevent 85 # 播放/暂停
adb shell input keyevent 86 # 停止播放
adb shell input keyevent 87 # 播放下一首
adb shell input keyevent 88 # 播放上一首
adb shell input keyevent 126 # 恢复播放
adb shell input keyevent 127 # 暂停播放
媒体播放、暂停、上下首
adb shell input keyevent 224 # 点亮屏幕
adb shell input keyevent 223 # 熄灭屏幕
亮屏、熄屏
# 触击屏幕
adb shell input tap <X> <Y> # x,y为坐标位置 # 滑动屏幕 四个参数:起始点x坐标 起始点y坐标 结束点x坐标 结束点y坐标。
adb shell input swipe 300 1000 300 500 # 向上滑动
adb shell input swipe 300 100 300 1000 # 向下滑动
adb shell input swipe 1000 500 200 500 # 向左滑动
adb shell input swipe 200 500 1000 500 # 向右滑动
触击、滑动
所有命令的篇幅较大,详细戳这里:ADB——模拟手机按键输入
查看手机设备信息
手机设备信息可以包括如下信息:
- 手机型号
- 电池状况
- 分辨率
- 屏幕密度
- 显示屏参数
- Android_id
- IMEI
- Android系统版本
- IP地址
- Mac地址
- CPU信息
- 内存信息
具体每个信息的查看方式见:ADB——查看手机设备信息
管理手机文件
这里只讲解手机和电脑之间的互相复制文件的功能
复制手机的文件到电脑
adb pull <设备里的文件路径> [电脑上的目录] # 电脑上的目录参数可忽略,默认为当前目录
# 例:
adb pull /sdcard/sr.mp4 ~/tmp/ # 将手机中的/sdcard/sr.mp4文件复制到电脑的~/tmp/ 所在的文件夹中 # 设备上的文件路径可能需要root权限才能访问,如果你的设备已经root过,可以先使用adb shell和su命令在adb shell里获取root 限后,
先cp /path/on/device /sdcard/filename
将文件复制到sdcard,然后adb pull /sdcard/filename /path/on/pc
复制电脑上的文件到手机
adb push <电脑上的文件路径> <设备里的目录>
# 例
adb push ~/sr.mp4 /sdcard/
# 设备上的文件路径普通权限可能无法直接写入,如果设备已经root过,可以先adb push /path/on/pc /sdcard/filename,
然后adb shell和su在 adb shell里获取root权限后,cp /sdcard/filename /path/on/device。
应用管理
- 查看应用列表
- 安装应用
- 卸载应用
- 清楚应用数据与缓存
- 查看前台Activity
- 查看应用信息
- 查看安装路径等等
具体操作见:ADB——管理应用
应用交互
- 启动应用 / 调起Activity:
- 调起Services:
- 停止Service
- 发送广播
- 强行停止应用
具体操作见:ADB——应用交互
查看日志
Android 系统的日志分为两部分,底层的 Linux 内核日志输出到 /proc/kmsg,Android 的日志输出到 /dev/log。
查看Android的日志
[adb] logcat [<option>] ... [<filter-spec>] ...
常用用法列举如下:
一、按级别过滤日志
Android 的日志分为如下几个优先级(priority):
- V —— Verbose(最低,输出得最多)
- D —— Debug
- I —— Info
- W —— Warning
- E —— Error
- F —— Fatal
- S —— Silent(最高,啥也不输出)
按某级别过滤日志则会将该级别及以上的日志输出。
比如,下面命令会将 Warning、Error、Fatal 和 Silent 日志输出。
adb logcat *:W # 注: 在 macOS 下需要给 *:W 这样以 * 作为 tag 的参数加双引号,如 adb logcat "*:W",不然会报错 no matches found: *:W
二、按 tag 和级别过滤日志
# <filter-spec> 可以由多个 <tag>[:priority] 组成。 # 比如,下面命令表示输出 tag ActivityManager 的 Info 以上级别日志,输出 tag MyApp 的 Debug 以上级别日志,及其它 tag 的 Silent 级别日志(即屏蔽其它 tag 日志)
adb logcat ActivityManager:I MyApp:D *:S
。
三、日志格式
可以用adb logcat -v <format>选项指定日志输出格式。
日志支持按以下几种<format>
-
brief——默认格式。格式为
<priority>/<tag>(<pid>): <message>
# 示例
D/HeadsetStateMachine( 1785): Disconnected process message: 10, size: 0 -
process——格式为:
<priority>(<pid>) <message>
# 示例:
D( 1785) Disconnected process message: 10, size: 0 (HeadsetStateMachine) -
tag——格式为:
<priority>/<tag>: <message>
# 示例:
D/HeadsetStateMachine: Disconnected process message: 10, size: 0 -
raw——格式为:
<message>
# 示例:
Disconnected process message: 10, size: 0 -
time——格式为:
<datetime> <priority>/<tag>(<pid>): <message>
# 示例:
08-28 22:39:39.974 D/HeadsetStateMachine( 1785): Disconnected process message: 10, size: 0 -
threadtime——格式为:
<datetime> <pid> <tid> <priority> <tag>: <message>
# 示例:
08-28 22:39:39.974 1785 1832 D HeadsetStateMachine: Disconnected process message: 10, size: 0 -
long——格式为:
[ <datetime> <pid>:<tid> <priority>/<tag> ]
<message>
# 示例:
[ 08-28 22:39:39.974 1785: 1832 D/HeadsetStateMachine ]
Disconnected process message: 10, size: 0
指定格式可与上面的过滤同时使用。比如:
adb logcat -v long ActivityManager:I *:S
四、清空日志
adb logcat -c
查看内核日志
通过内核日志我们可以做一些事情,比如衡量内核启动时间,在系统启动完毕后的内核日志里找到 Freeing init memory 那一行前面的时间就是。
adb shell dmesg
'''
<6>[14201.684016] PM: noirq resume of devices complete after 0.982 msecs
<6>[14201.685525] PM: early resume of devices complete after 0.838 msecs
<6>[14201.753642] PM: resume of devices complete after 68.106 msecs
<4>[14201.755954] Restarting tasks ... done.
<6>[14201.771229] PM: suspend exit 2016-08-28 13:31:32.679217193 UTC
<6>[14201.872373] PM: suspend entry 2016-08-28 13:31:32.780363596 UTC
<6>[14201.872498] PM: Syncing filesystems ... done.
'''
# 中括号里的 [14201.684016] 代表内核开始启动后的时间,单位为秒。
修改手机默认设置
修改设置的原理主要是通过 settings 命令修改 /data/data/com.android.providers.settings/databases/settings.db 里存放的设置值。
利用ADB的命令可以修改手机的一些默认设置,修改设置之后,运行恢复命令有可能显示仍然不太正常,可以运行 adb reboot 重启设备,或手动重启。
- 修改分辨率
- 修改屏幕密度
- 修改显示区域
- 关闭USB调试
- 允许 / 禁止访问非 SDK API:
- 状态栏和导航栏的显示隐藏
具体操作见:ADB——修改手机默认
其他实用功能
屏幕截图
adb exec-out screencap -p > sc.png # 截图保存到电脑
# 实测如果指定文件名以.png
结尾时可以省略 -p 参数;否则需要使用 -p 参数。如果不指定文件名,截图文件的内容将直接输出到 stdout。
# 如果 adb 版本较老,无法使用 exec-out 命令,建议更新 adb 版本。若无法更新使用如下步骤:
adb shell screencap -p /sdcard/sc.png # 先截图保存到设备里
adb pull /sdcard/sc.png # 然后将 png 文件导出到电脑:
可以使用 adb shell screencap -h 查看 screencap 命令的帮助信息,下面是两个有意义的参数及含义:
参数 | 含义 |
---|---|
-p | 指定保存文件为 png 格式 |
-d display-id | 指定截图的显示屏编号(有多显示屏的情况下) |
另外一种一行命令截图并保存到电脑的方法:
# Linux 和 Windows
adb shell screencap -p | sed "s/\r$//" > sc.png # Mac OS X
adb shell screencap -p | gsed "s/\r$//" > sc.png
上述方法需要用到 gnu sed 命令,在 Linux 下直接就有,在 Windows 下 Git 安装目录的 bin 文件夹下也有。如果确实找不到该命令,可以下载 sed for Windows 并将 sed.exe 所在文件夹添加到 PATH 环境变量里。
而在 Mac 下使用系统自带的 sed 命令会报错:
sed: RE error: illegal byte sequence
# 需要安装 gnu-sed,然后使用 gsed 命令:
brew install gnu-sed
录制屏幕
adb shell screenrecord /sdcard/filename.mp4 # 录制屏幕以 mp4 格式保存到 /sdcard
adb pull /sdcard/filename.mp4 # 导出到电脑: # 需要停止时按 Ctrl-C,默认录制时间和最长录制时间都是 180 秒。
可以使用 adb shell screenrecord --help 查看 screenrecord 命令的帮助信息,下面是常见参数及含义:
参数 | 含义 |
---|---|
--size WIDTHxHEIGHT | 视频的尺寸,比如 1280x720,默认是屏幕分辨率。 |
--bit-rate RATE | 视频的比特率,默认是 4Mbps。 |
--time-limit TIME | 录制时长,单位秒。 |
--verbose | 输出更多信息。 |
重新挂载 system 分区为可写
注:需要 root 权限。
/system 分区默认挂载为只读,但有些操作比如给 Android 系统添加命令、删除自带应用等需要对 /system 进行写操作,所以需要重新挂载它为可读写。
步骤:
# 1.进入 shell 并切换到 root 用户权限。
adb shell
su # 2.查看当前分区挂载情况。
mount 输出示例:
'''
rootfs / rootfs ro,relatime 0 0
tmpfs /dev tmpfs rw,seclabel,nosuid,relatime,mode=755 0 0
devpts /dev/pts devpts rw,seclabel,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,seclabel,relatime 0 0
selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
debugfs /sys/kernel/debug debugfs rw,relatime 0 0
none /var tmpfs rw,seclabel,relatime,mode=770,gid=1000 0 0
none /acct cgroup rw,relatime,cpuacct 0 0
none /sys/fs/cgroup tmpfs rw,seclabel,relatime,mode=750,gid=1000 0 0
none /sys/fs/cgroup/memory cgroup rw,relatime,memory 0 0
tmpfs /mnt/asec tmpfs rw,seclabel,relatime,mode=755,gid=1000 0 0
tmpfs /mnt/obb tmpfs rw,seclabel,relatime,mode=755,gid=1000 0 0
none /dev/memcg cgroup rw,relatime,memory 0 0
none /dev/cpuctl cgroup rw,relatime,cpu 0 0
none /sys/fs/cgroup tmpfs rw,seclabel,relatime,mode=750,gid=1000 0 0
none /sys/fs/cgroup/memory cgroup rw,relatime,memory 0 0
none /sys/fs/cgroup/freezer cgroup rw,relatime,freezer 0 0
/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/userdata /data ext4 rw,seclabel,nosuid,nodev,relatime,noauto_da_alloc,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/cache /cache ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/persist /persist ext4 rw,seclabel,nosuid,nodev,relatime,data=ordered 0 0
/dev/block/platform/msm_sdcc.1/by-name/modem /firmware vfat ro,context=u:object_r:firmware_file:s0,relatime,uid=1000,gid=1000,fmask=0337,dmask=0227,codepage=cp437,iocharset=iso8859-1,shortname=lower,errors=remount-ro 0 0
/dev/fuse /mnt/shell/emulated fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /mnt/shell/emulated/0 fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
''' # 3.找到其中我们关注的带 /system 的那一行:/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 ro,seclabel,relatime,data=ordered 0 0重新挂载。 mount -o remount,rw -t yaffs2 /dev/block/platform/msm_sdcc.1/by-name/system /system
# 这里的 /dev/block/platform/msm_sdcc.1/by-name/system 就是我们从上一步的输出里得到的文件路径。 # 如果输出没有提示错误的话,操作就成功了,可以对 /system 下的文件为所欲为了。
查看连接过的 WiFi 密码
注:需要 root 权限。
adb shell
su
cat /data/misc/wifi/*.conf
'''
输出示例:
network={
ssid="TP-LINK_9DFC"
scan_ssid=1
psk="123456789"
key_mgmt=WPA-PSK
group=CCMP TKIP
auth_alg=OPEN
sim_num=1
priority=13893
} network={
ssid="TP-LINK_F11E"
psk="987654321"
key_mgmt=WPA-PSK
sim_num=1
priority=17293
}
ssid 即为我们在 WLAN 设置里看到的名称,psk 为密码,key_mgmt 为安全加密方式。
'''
设置系统日期和时间
注:需要 root 权限。
adb shell
su
date -s 20160823.131500
# 表示将系统日期和时间更改为 2016 年 08 月 23 日 13 点 15 分 00 秒。
重启手机
adb reboot
检测设备是否已 root
adb shell
su
# 此时命令行提示符是 $ 则表示没有 root 权限,是 # 则表示已 root。
使用 Monkey 进行压力测试
Monkey 可以生成伪随机用户事件来模拟单击、触摸、手势等操作,可以对正在开发中的程序进行随机压力测试。
简单用法:
adb shell monkey -p <packagename> -v 500 # 表示向 <packagename> 指定的应用程序发送 500 个伪随机事件。
Monkey 的详细用法参考 官方文档。
开启/关闭 WiFi
注:需要 root 权限。
# 开启 WiFi:
adb root
adb shell svc wifi enable # 关闭 WiFi:
adb root
adb shell svc wifi disable # 若执行成功,输出为空;若未取得 root 权限执行此命令,将执行失败,输出 Killed。
刷机相关命令
重启到 Recovery 模式
adb reboot recovery
从 Recovery 重启到 Android
adb reboot
重启到 Fastboot 模式
adb reboot bootloader
通过 sideload 更新系统
如果我们下载了 Android 设备对应的系统更新包到电脑上,那么也可以通过 adb 来完成更新。
以 Recovery 模式下更新为例:
-
重启到 Recovery 模式。
adb reboot recovery
-
在设备的 Recovery 界面上操作进入 Apply update-Apply from ADB。
注:不同的 Recovery 菜单可能与此有差异,有的是一级菜单就有 Apply update from ADB。
-
通过 adb 上传和更新系统。
adb sideload <path-to-update.zip>
安全相关命令
启用 SELinux
adb root
adb shell setenforce 1
禁用 SELinux
adb root
adb shell setenforce 0
启用 dm_verity
adb root
adb enable-verity
禁用 dm_verity
adb root
adb disable-verity
其他ADB shell命令
Android 系统是基于 Linux 内核的,所以 Linux 里的很多命令在 Android 里也有相同或类似的实现,在 adb shell 里可以调用。本文档前面的部分内容已经用到了 adb shell 命令。
查看进程
adb shell ps
'''
输出示例: USER PID PPID VSIZE RSS WCHAN PC NAME
root 1 0 8904 788 ffffffff 00000000 S /init
root 2 0 0 0 ffffffff 00000000 S kthreadd
...
u0_a71 7779 5926 1538748 48896 ffffffff 00000000 S com.sohu.inputmethod.sogou:classic
u0_a58 7963 5926 1561916 59568 ffffffff 00000000 S org.mazhuang.boottimemeasure
...
shell 8750 217 10640 740 00000000 b6f28340 R ps
'''
各列含义:
列名 | 含义 |
---|---|
USER | 所属用户 |
PID | 进程 ID |
PPID | 父进程 ID |
NAME | 进程名 |
查看实时资源占用情况
命令:
adb shell top
'''
输出示例: User 0%, System 6%, IOW 0%, IRQ 0%
User 3 + Nice 0 + Sys 21 + Idle 280 + IOW 0 + IRQ 0 + SIRQ 3 = 307 PID PR CPU% S #THR VSS RSS PCY UID Name
8763 0 3% R 1 10640K 1064K fg shell top
131 0 3% S 1 0K 0K fg root dhd_dpc
6144 0 0% S 115 1682004K 115916K fg system system_server
132 0 0% S 1 0K 0K fg root dhd_rxf
1731 0 0% S 6 20288K 788K fg root /system/bin/mpdecision
217 0 0% S 6 18008K 356K fg shell /sbin/adbd
...
7779 2 0% S 19 1538748K 48896K bg u0_a71 com.sohu.inputmethod.sogou:classic
7963 0 0% S 18 1561916K 59568K fg u0_a58 org.mazhuang.boottimemeasure
'''
各列含义:
列名 | 含义 |
---|---|
PID | 进程 ID |
PR | 优先级 |
CPU% | 当前瞬间占用 CPU 百分比 |
S | 进程状态(R=运行,S=睡眠,T=跟踪/停止,Z=僵尸进程) |
#THR | 线程数 |
VSS | Virtual Set Size 虚拟耗用内存(包含共享库占用的内存) |
RSS | Resident Set Size 实际使用物理内存(包含共享库占用的内存) |
PCY | 调度策略优先级,SP_BACKGROUND/SPFOREGROUND |
UID | 进程所有者的用户 ID |
NAME | 进程名 |
top 命令还支持一些命令行参数,详细用法如下:
Usage: top [ -m max_procs ] [ -n iterations ] [ -d delay ] [ -s sort_column ] [ -t ] [ -h ]
- -m num 最多显示多少个进程
- -n num 刷新多少次后退出
- -d num 刷新时间间隔(单位秒,默认值 5)
- -s col 按某列排序(可用 col 值:cpu, vss, rss, thr)
- -t 显示线程信息
- -h 显示帮助文档
查看进程 UID
# 第一种方案:
adb shell dumpsys package <packagename> | grep userId= # 如:
$ adb shell dumpsys package org.mazhuang.guanggoo | grep userId=
userId=10394 # 第二种:通过 ps 命令找到对应进程的 pid 之后 adb shell cat /proc/<pid>/status | grep Uid # 如:
$ adb shell
gemini:/ $ ps | grep org.mazhuang.guanggoo
u0_a394 28635 770 1795812 78736 SyS_epoll_ 0000000000 S org.mazhuang.guanggoo
gemini:/ $ cat /proc/28635/status | grep Uid
Uid: 10394 10394 10394 10394
gemini:/ $
其它
如下是其它常用命令的简单描述,前文已经专门讲过的命令不再额外说明:
命令 | 功能 |
---|---|
cat | 显示文件内容 |
cd | 切换目录 |
chmod | 改变文件的存取模式/访问权限 |
df | 查看磁盘空间使用情况 |
grep | 过滤输出 |
kill | 杀死指定 PID 的进程 |
ls | 列举目录内容 |
mount | 挂载目录的查看和管理 |
mv | 移动或重命名文件 |
ps | 查看正在运行的进程 |
rm | 删除文件 |
top | 查看进程的资源占用情况 |
常见问题
启动 adb server 失败
出错提示:
error: protocol fault (couldn't read status): No error
可能原因:
adb server 进程想使用的 5037 端口被占用。
解决方案:
找到占用 5037 端口的进程,然后终止它。以 Windows 下为例:
netstat -ano | findstr LISTENING ...
TCP 0.0.0.0:5037 0.0.0.0:0 LISTENING 1548
...
这里 1548 即为进程 ID,用命令结束该进程:
taskkill /PID 1548
然后再启动 adb 就没问题了。
com.android.ddmlib.AdbCommandRejectedException
在 Android Studio 里新建一个模拟器,但是用 adb 一直连接不上,提示:
com.android.ddmlib.AdbCommandRejectedException: device unauthorized.
This adb server's $ADB_VENDOR_KEYS is not set
Try 'adb kill-server' if that seems wrong.
Otherwise check for a confirmation dialog on your device.
在手机上安装一个终端然后执行 su 提示没有该命令,这不正常。
于是删除该模拟器后重新下载安装一次,这次就正常了。
本文及文中所有引用连接均参考链接:https://github.com/mzlogin/awesome-adb