ADB 常用命令

安卓调试桥 (Android Debug Bridge, adb),是一种可以用来操作手机设备或模拟器的命令行工具。它存在于 sdk/platform-tools 目录下。虽然现在 Android Studio 已经将大部分 ADB 命令以图形化的形式实现了,但是了解一下还是有必要的。

如果记不住命令怎么办?推荐一个可以快速查看 ADB 命令的插件 adb-idea

find_actions

链接 ADB

有两种方式来启动 ADB,第一种就是直接进入 sdk/platform-tools 目录,在命令行中输入 adb devices 来验证设备是否连接。然而每次进入 platform-tools 目录很麻烦,因此有第二种方法,将 adb 地址写入环境变量,在 macOS 下面可以这样配置:

1
export PATH=$PATH:<path to Android SDK>/platform-tools

然后在命令行中输入 source ~/.bash_profile 或者 source ~/.zshrc 来更新配置文件。

现在,可以在任意路径中输入adb device,如果手机连接了电脑,并且在 开发者选择 中开启了 USB 调试模式,那么就能看见你所连接的设备序列号了:

1
2
3
➜  ~ adb devices
List of devices attached
80QBCNP234K3 device

其中,80QBCNP234K3 是设备序列号,device 是设备状态,设备状态有三种:

  • offline — 设备未连接到 adb 或者没有响应
  • device — 设备已连接到 adb
  • no device — 未连接模拟器/设备

安装和卸载

安装

我们可以使用 adb install [option] <path> 命令来将电脑上的一个 APP 安装到手机上,比如:

1
adb install game.apk

有时候你电脑上连接的设备不止一个,那么在做一些操作之前,需要指定我们要操作的设备的序列号,也就是需要执行 adb -s [serial_number] command 命令。

比如现在有两部 Android 手机连接了电脑并都打开了开发者模式,那么在安装 game.apk 的时候,命令就需要变一下:

1
adb -s 80QBCNP234K3 install game.apk

覆盖安装

如果重复安装一个 APP,那么就会得到一个错误信息:Failure [INSTALL_FAILED_ALREADY_EXISTS],这个时候就需要覆盖安装了:加上 -r (replace) 来替换当前应用:

1
adb install -r game.apk

卸载

卸载一个 APP 的命令是 adb uninstall [option] <packagename>

1
adb uninstall com.test.app

注意: 卸载 APP 时需要使用的是 APP 的包名(package name)。而从电脑安装 APP 到手机上只需要知道电脑中 APK 的文件名。

APP 卸载之后,其缓存文件一般也会被清除。如果我们想保留缓存文件,可以添加 -k,即:

1
adb uninstall -k com.test.app

文件操作

Android 手机中的文件路径

以前,手机的容量比较小的时候,一般都会有 SD 卡扩展,然后就把资源数据存放到 SD 卡目录下,到现在手机容量越来越大,很多手机已经取消了 SD 卡,但是为了做兼容,也会 mock 一个假的 SD 卡路径。因此,现在也有很多开发者将 APP 数据保存在 /sdcard 目录下。现在已经不推荐将文件存储在 /sdcard 目录下了。

当然,音频视频文件还是应该放在 SD 卡目录下。SD 卡的路径是 /mnt/sdcard/ 或者 /sdcard/sdcard/mnt/sdcard 的软链接。其中,/mnt/sdcard/DCIM 一般用于存放照片的,DCIM 是 Digital Camera IMages 的缩写,但是我们的截图及 APP 保存图片的位置,一般是在 /mnt/sdcard/Pictures。以此类推,可以知道视频文件存放在 /mnt/sdcard/Movies 等等。

当我们在手机上安装好了一个 APP 之后,相关的文件存放在下面两个地方:

  • APP 本身被存放在 /data/app 目录下。
  • 文件目录存放在 /data/data/<package name> 目录下,该目录下存放有数据库、SharedPreference 和其他缓存数据。

如果你想把手机中的文件拷贝到电脑中,使用 adb pull <remote> [local] 命令,如果 local 地址为空,则会拷贝到电脑当前目录下:

1
adb pull /sdcard/game.apk

如果要把电脑中的文件拷贝到手机里,使用 adb push <local> <remote> 命令:

1
adb push game.apk /sdcard/data/data

清除 APP 数据

在开发过程中,经常会遇到这么一种情况:清空 APP 缓存数据,然后进行一些列请求。清空 APP 缓存数据可以使用下面的命令:

1
adb shell pm clear com.example.packagename

该命令不仅能清除 APP 的缓存,还能把 APP 的数据给清空。

查看所有 APP 的名称

1
adb shell pm list packages

该命令可以查看手机上的 APP 名称。可以在后面加上 -f,这样还能显示该 APP 的路径

事件输入

input

可以在命令行中使用 adb shell input 向屏幕输入一些信息,比如:

1
adb shell input text "insert%syour%stext%shere"

其中,%s 表示空格

也可以使用 adb shell input tap 命令来模拟屏幕点击事件,比如:

1
adb shell input tap 500 1450

该命令表示在屏幕 (500, 1450) 的坐标点上进行一次点击

也可以使用 adb shell input swipe 命令来模拟手势滑动事件,比如:

1
adb shell input swipe 100 500 100 1450 100

该命令表示从屏幕坐标 (100, 500) 开始,滑动到 (100, 1450) 结束,整个过程耗时 100ms。

上面的命令还可以模拟”长按”(Long Press) 操作,也就是两个坐标点相同,耗时超过 500ms

1
adb shell input swipe 100 500 100 500 500

可以使用 adb shell input keyevent 命令来模拟点按实体按钮的命令,比如

1
adb shell input keyevent 25

该命令表示调低音量。这个数字 25 是在 AOSP 源码中的 KeyEvent 类里面定义的一个事件常量。该类定义了将近 300 个事件常量。

am

am (Activity Manager) 命令用来启动一个 APP、启动 Activity、启动广播和服务等等。

启动一个 Activity,最简单的命令可以使用 adb shell am start com.package.name/com.package.name.ActivityName 比如:

1
adb shell am start qiushui.me.test/qiushui.me.test.MainActivity

如果启动带有参数,则需要使用 -e 标签,比如有一个 SecondActivity 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class SecondActivity : AppCompatActivity() {

companion object {
private val ARGUS_NAME = "argus_name"
fun launch(activity: Activity, content: String): Intent {
val intent = Intent(activity, SecondActivity::class.java)
intent.putExtra(ARGUS_NAME, content)
return intent
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_second)

val name = intent.getStringExtra(ARGUS_NAME)
nameTv.text = "Hello, $name"
}
}

也就是说,启动 SecondActivity 的话需要传入一个 argus_name 参数,那么在命令行中可以执行如下:

1
adb shell am start qiushui.me.test/qiushui.me.test.SecondActivity -e argus_name Qiushui

启动带的参数一般是 Key-Value 形式,这里的 Key 是 argus_name,Value 是 Qiushui。

除了默认启动的 Activity 以外,打开其他的 Activity 时,需要在 AndroidManifest 文件中添加 android:exported="true" 属性。

如果我们要启动一个隐式的 Intent,也就是说我们需要传入 action 等参数,在 ADB 调试桥 中可以得知 Intent 的参数规范,比如 -a 表示 action-c 表示 category-d 表示 data_uri-e 表示添加额外 Key-Value 信息。比如:

1
am start -a "android.intent.action.VIEW" -d "https://www.google.com"

上面这个命令会启动一个浏览器打开 https://www.google.com 页面 (如果有多个浏览器,会让用户进行选择) 。

am 也能发送广播和启动服务。比如启动一个广播,一般需要添加一个 -a

1
adb shell am broadcast -a "our.specified.action"

当然,我们可以在上面的命令后面添加 -e 来添加额外信息。

甚至,我们可以直接让手机重启:

1
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED

启动一个服务也是类似的:

1
adb shell am startservice "qiushui.me.test/qiushui.me.test.MyService"

事件输出

日志信息

使用 adb logcat 可以显示日志信息,使用 command + C(Windows 下是 Ctrl + C) 来停止日志输出。

当然,比起原生的 adb logcat ,JakeWharton 大神的 pidcat 显示效果更好:

虽然现在 Android Studio 的日志功能已经非常完善了,但是如果遇到不方便打开 Android Studio 的话,使用命令行也是一种选择。

dumpsys

dumpsys 是一个非常强大的命令,它可以提供非常多的系统信息。可以通过 adb shell service list 来查看 dumpsys 能提供查询信息的服务,常用的有如下几个:

服务名 类名 功能
activity ActivityManagerService AMS相关信息
package PackageManagerService PMS相关信息
window WindowManagerService WMS相关信息
input InputManagerService IMS相关信息
power PowerManagerService PMS相关信息
procstats ProcessStatsService 进程统计
battery BatteryService 电池信息
alarm AlarmManagerService 闹钟信息
meminfo MemBinder 内存

比如想要查看电池信息,命令行中输入 adb shell dumpsys battery,可以得到如下信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Current Battery Service state:
AC powered: false
USB powered: true
Wireless powered: false
status: 2
status: 1
health: 2
present: true
present: false
level: 95
level: 50
scale: 100
voltage: 4296
temperature: 290
technology: Li-ion

如果直接使用 adb shell dumpsys activity 来查看信息的话,会得到非常长的代码,其结构大概如下所示:

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
39
40
41
ACTIVITY MANAGER PENDING INTENTS (dumpsys activity intents)
* PendingIntentRecord{19e4491 com.google.android.googlequicksearchbox startService}
......

ACTIVITY MANAGER BROADCAST STATE (dumpsys activity broadcasts)
Historical broadcasts [foreground]:
#0: BroadcastRecord{313a73e u-1 android.intent.action.TIME_TICK}
act=android.intent.action.TIME_TICK flg=0x50000014 (has extras)
extras: Bundle[{android.intent.extra.ALARM_COUNT=1}]
......

ACTIVITY MANAGER CONTENT PROVIDERS (dumpsys activity providers)
Published single-user content providers (by class):
* ContentProviderRecord{dc31380 u0 com.android.providers.settings/.SettingsProvider}
......

ACTIVITY MANAGER URI PERMISSIONS (dumpsys activity permissions)
(nothing)

ACTIVITY MANAGER SERVICES (dumpsys activity services)
User 0 active services:
* ServiceRecord{24fc267 u0 com.android.systemui/.keyguard.KeyguardService}
......
ACTIVITY MANAGER RECENT TASKS (dumpsys activity recents)
Recent tasks:
* Recent #0: TaskRecord{9d18590 #15 A=qiushui.me.test U=0 StackId=1 sz=2}
......

ACTIVITY MANAGER ACTIVITIES (dumpsys activity activities)
Display #0 (activities from top to bottom):
......
ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)
Isolated process list (sorted by uid):
Isolated # 0: ProcessRecord{1ed43fb 1654:WebViewLoader-x86/1037}

UID states:
UID 1000: UidRecord{bde9c18 1000 P procs:1}
......
UID validation:
UID 1001: UidRecord{70352bf 1001 P procs:0}
......

从上面的目录结构中可以看出,dumpsys activity 得到的信息可以拆分为以下八个命令所得到的信息和:

1
2
3
4
5
6
7
8
dumpsys activity intents
dumpsys activity broadcasts
dumpsys activity providers
dumpsys activity permissions
dumpsys activity services
dumpsys activity recents
dumpsys activity activities
dumpsys activity processes

因此,一般根据所需,选择这八个中的一个命令进行查询。比如查看广播相关的,使用 adb shell dumpsys activity broadcasts 命令,查看界面相关的,使用 adb shell dumpsys activity activities 命令。

当然,这八种信息类型,可以分别用缩略来表示,即 adb shell dumpsys activity a 等同于 adb shell dumpsys activity activitiesadb shell dumpsys activity s 等同于 adb shell dumpsys activity services 等等。这里有两个需要注意的是,providers 的缩略是 prov 以及 permissions 的缩略是 perm

如果还是嫌输出内容太多,我只关心运行的 Activity 结构层次其他的无所谓怎么办?可以使用 grep 命令来过滤:

1
adb shell dumpsys activity | grep -i 'run'

这样,得到的信息就非常精炼了:

1
2
3
4
5
6
7
8
9
  * ContentProviderRecord{978680e u0 qiushui.me.test/com.android.tools.fd.runtime.InstantRunContentProvider}
authority=qiushui.me.test.com.android.tools.fd.runtime.InstantRunContentProvider
Running activities (most recent first):
Run #1: ActivityRecord{304ded1 u0 qiushui.me.test/.SecondActivity t14}
Run #0: ActivityRecord{19b9e16 u0 qiushui.me.test/.MainActivity t14}
Running activities (most recent first):
Run #0: ActivityRecord{f9bafb7 u0 com.google.android.apps.nexuslauncher/.NexusLauncherActivity t13}
ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)
User #0: state=RUNNING_UNLOCKED

从上面可以得出一些信息:屏幕正在显示的界面是 SecondActivity,然后是 MainActivity。而 NexusLauncherActivity 是处于最底层,其实就是 Launcher。

以 “今日头条” APP 为例,看看如何获取该 APP 的相关信息:

打开今日头条 APP,使用 adb shell dumpsys activity a | grep -i 'run' 命令查看,得到信息如下:

1
2
3
4
Running activities (most recent first):
Run #0: ActivityRecord{898e01f u0 com.ss.android.article.news/.activity.MainActivity t3117}
Running activities (most recent first):
Run #0: ActivityRecord{1d58a20 u0 com.huawei.android.launcher/.Launcher t2980}

可以知道今日头条的包名为com.ss.android.article.news

查看 APP 有哪些进程,使用 adb shell dumpsys activity p com.ss.android.article.news | grep -i 'ProcessRecord' | grep -i 'PID',得到信息如下:

1
2
3
4
PID #7081: ProcessRecord{dd9a2d0 7081:com.ss.android.article.news/u0a157}
PID #7095: ProcessRecord{e4bee94 7095:com.ss.android.article.news:push/u0a157}
PID #7261: ProcessRecord{306b8b6 7261:com.ss.android.article.news:pushservice/u0a157}
PID #7405: ProcessRecord{cd5fe38 7405:com.ss.android.article.news:ad/u0a157}

可知一共有 4 个进程。还可知道分别的进程名和 PID 等等。

查看 APP 使用了哪些服务,使用 adb shell dumpsys activity s com.ss.android.article.news | grep -i 'ServiceRecord' 显示结果如下:

1
2
3
4
5
6
7
* ServiceRecord{885e1bf u0 euid: 0 com.ss.android.article.news/com.ss.android.message.NotifyService}
* ServiceRecord{2dcef97 u0 euid: 0 com.ss.android.article.news/com.ss.android.push.daemon.PushService}
* ServiceRecord{532ef96 u0 euid: 0 com.ss.android.article.news/com.taobao.accs.data.MsgDistributeService}
* ServiceRecord{d65319e u0 euid: 0 com.ss.android.article.news/org.android.agoo.accs.AgooService}
* ServiceRecord{3ba5a9b u0 euid: 0 com.ss.android.article.news/com.ss.android.ad.impl.AdService}
* ServiceRecord{716d0a8 u0 euid: 0 com.ss.android.article.news/com.bytedance.common.wschannel.server.WsChannelService}
* ServiceRecord{99e9a1b u0 euid: 0 com.ss.android.article.news/com.taobao.accs.ChannelService}

可以看到该 APP 使用了阿里云推送 com.taobao.accs.ChannelService

比如我想看今日头条的内存使用情况?可以使用 adb shell dumpsys meminfo com.ss.android.article.news 命令,显示结果如下:

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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Applications Memory Usage (kB):
Uptime: 32966919 Realtime: 276529459

** MEMINFO in pid 22601 [com.ss.android.article.news] **
Pss Private Private Swapped Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 18352 17856 0 48 29068 28997 70
Dalvik Heap 31310 31244 0 540 26944 26374 570
Dalvik Other 3135 3132 0 0
Stack 1072 1072 0 0
Ashmem 154 120 0 0
Gfx dev 7084 6840 0 0
Other dev 10 0 8 0
.so mmap 2906 376 288 1416
.apk mmap 14072 104 12684 0
.ttf mmap 1018 0 716 0
.dex mmap 15979 968 11644 0
.oat mmap 4823 0 2116 4
.art mmap 2523 1764 276 4
Other mmap 743 8 688 0
EGL mtrack 25920 25920 0 0
Unknown 2525 2524 0 68
TOTAL 131626 91928 28420 2080 56012 55371 640

App Summary
Pss(KB)
------
Java Heap: 33284
Native Heap: 17856
Code: 28896
Stack: 1072
Graphics: 32760
Private Other: 6480
System: 11278

TOTAL: 131626 TOTAL SWAP (KB): 2080

Objects
Views: 666 ViewRootImpl: 3
AppContexts: 5 Activities: 2
Assets: 5 AssetManagers: 3
Local Binders: 65 Proxy Binders: 41
Parcel memory: 26 Parcel count: 104
Death Recipients: 3 OpenSSL Sockets: 15

SQL
MEMORY_USED: 1940
PAGECACHE_OVERFLOW: 1227 MALLOC_SIZE: 62

DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 20 25 14/20/3 /data/user/0/com.ss.android.article.news/databases/ss_app_monitor.db
4 48 15 0/18/1 /data/user/0/com.ss.android.article.news/databases/MsgLogStore.db
4 20 35 4/22/5 /data/user/0/com.ss.android.article.news/databases/lib_log_queue.db
4 40 124 56/38/17 /data/user/0/com.ss.android.article.news/databases/ss_app_log.db
4 20 30 1/19/2 /data/user/0/com.ss.android.article.news/databases/accs.db
4 20 49 5/20/4 /data/user/0/com.ss.android.article.news/databases/feedback.db
4 1596 462 96/48/25 /data/user/0/com.ss.android.article.news/databases/article.db
4 36 26 4/20/3 /data/user/0/com.ss.android.article.news/databases/MessageStore.db

Asset Allocations
zip:/data/app/com.ss.android.article.news-1/base.apk:/resources.arsc: 632K

给出的内存使用信息非常详细!

关于 dumpsys 的介绍就到这里,dumpsys 的强大可见一斑!

屏幕截图

可以使用 screemcap <filename> 命令来进行手机屏幕截图,比如:

1
adb shell screencap /sdcard/screen.png

录制视频

可以使用 screenrecord [options] filename 命令来录制屏幕视频,比如

1
adb shell screenrecord /sdcard/demo.mp4

这个命令适用于 Android 4.4 及以上的设备中。

录制视频也有很多参数选项,比如 --size 用来设置视频大小,--time-limit 用来设置最大录制时长等等。

系统命令

查看进程信息

使用 adb shell ps 命令查看进程信息。通常会在该命令后面添加包名,来查看某个应用程序的进程信息

查看 CPU 使用情况

使用 adb shell top 命令查看系统 CPU 使用情况。

参考资料:ADB 调试桥

如果觉得文章对你有帮助,请我喝杯可乐吧