# ![Awesome Adb](./assets/title.png)
ADB,即 [Android Debug Bridge](https://developer.android.com/studio/command-line/adb.html),它是 Android 开发/测试人员不可替代的强大工具,也是 Android 设备玩家的好玩具。
持续更新中,欢迎提 PR 和 Issue 补充指正,觉得有用的可以将 [此 GitHub 仓库](https://github.com/mzlogin/awesome-adb) Star 收藏备用。
给本项目提建议和意见,或想与我交流,可关注微信公众号「闷骚的程序员」:
**注:** 文中有部分命令的支持情况可能与 Android 系统版本及定制 ROM 的实现有关。
Other languages: [:gb: English](./README.en.md)
# ![Table of Contents](./assets/toc.png)
* [基本用法](#基本用法)
* [命令语法](#命令语法)
* [为命令指定目标设备](#为命令指定目标设备)
* [启动/停止](#启动停止)
* [查看 adb 版本](#查看-adb-版本)
* [以 root 权限运行 adbd](#以-root-权限运行-adbd)
* [指定 adb server 的网络端口](#指定-adb-server-的网络端口)
* [设备连接管理](#设备连接管理)
* [查询已连接设备/模拟器](#查询已连接设备模拟器)
* [USB 连接](#usb-连接)
* [无线连接(Android11 及以上)](#无线连接Android11-及以上)
* [无线连接(需要借助 USB 线)](#无线连接需要借助-usb-线)
* [无线连接(无需借助 USB 线)](#无线连接无需借助-usb-线)
* [应用管理](#应用管理)
* [查看应用列表](#查看应用列表)
* [所有应用](#所有应用)
* [系统应用](#系统应用)
* [第三方应用](#第三方应用)
* [包名包含某字符串的应用](#包名包含某字符串的应用)
* [安装 APK](#安装-apk)
* [卸载应用](#卸载应用)
* [清除应用数据与缓存](#清除应用数据与缓存)
* [查看前台 Activity](#查看前台-activity)
* [查看正在运行的 Services](#查看正在运行的-services)
* [查看应用详细信息](#查看应用详细信息)
* [查看应用安装路径](#查看应用安装路径)
* [与应用交互](#与应用交互)
* [启动应用/ 调起 Activity](#启动应用-调起-activity)
* [调起 Service](#调起-service)
* [停止 Service](#停止-service)
* [发送广播](#发送广播)
* [强制停止应用](#强制停止应用)
* [收紧内存](#收紧内存)
* [文件管理](#文件管理)
* [复制设备里的文件到电脑](#复制设备里的文件到电脑)
* [复制电脑里的文件到设备](#复制电脑里的文件到设备)
* [模拟按键/输入](#模拟按键输入)
* [电源键](#电源键)
* [菜单键](#菜单键)
* [HOME 键](#home-键)
* [返回键](#返回键)
* [音量控制](#音量控制)
* [媒体控制](#媒体控制)
* [点亮/熄灭屏幕](#点亮熄灭屏幕)
* [滑动解锁](#滑动解锁)
* [输入文本](#输入文本)
* [查看日志](#查看日志)
* [Android 日志](#android-日志)
* [按级别过滤日志](#按级别过滤日志)
* [按 tag 和级别过滤日志](#按-tag-和级别过滤日志)
* [日志格式](#日志格式)
* [清空日志](#清空日志)
* [内核日志](#内核日志)
* [查看设备信息](#查看设备信息)
* [型号](#型号)
* [电池状况](#电池状况)
* [屏幕分辨率](#屏幕分辨率)
* [屏幕密度](#屏幕密度)
* [显示屏参数](#显示屏参数)
* [android\_id](#android_id)
* [IMEI](#imei)
* [Android 系统版本](#android-系统版本)
* [IP 地址](#ip-地址)
* [Mac 地址](#mac-地址)
* [CPU 信息](#cpu-信息)
* [内存信息](#内存信息)
* [更多硬件与系统属性](#更多硬件与系统属性)
* [修改设置](#修改设置)
* [分辨率](#分辨率)
* [屏幕密度](#屏幕密度-1)
* [显示区域](#显示区域)
* [关闭 USB 调试模式](#关闭-usb-调试模式)
* [允许/禁止访问非 SDK API](#允许禁止访问非-sdk-api)
* [状态栏和导航栏的显示隐藏](#状态栏和导航栏的显示隐藏)
* [实用功能](#实用功能)
* [屏幕截图](#屏幕截图)
* [录制屏幕](#录制屏幕)
* [重新挂载 system 分区为可写](#重新挂载-system-分区为可写)
* [查看连接过的 WiFi 密码](#查看连接过的-wifi-密码)
* [设置系统日期和时间](#设置系统日期和时间)
* [重启手机](#重启手机)
* [检测设备是否已 root](#检测设备是否已-root)
* [使用 Monkey 进行压力测试](#使用-monkey-进行压力测试)
* [开启/关闭 WiFi](#开启关闭-wifi)
* [刷机相关命令](#刷机相关命令)
* [重启到 Recovery 模式](#重启到-recovery-模式)
* [从 Recovery 重启到 Android](#从-recovery-重启到-android)
* [重启到 Fastboot 模式](#重启到-fastboot-模式)
* [通过 sideload 更新系统](#通过-sideload-更新系统)
* [安全相关命令](#安全相关命令)
* [启用/禁用 SELinux](#启用禁用-selinux)
* [启用/禁用 dm_verity](#启用禁用-dm_verity)
* [更多 adb shell 命令](#更多-adb-shell-命令)
* [查看进程](#查看进程)
* [查看实时资源占用情况](#查看实时资源占用情况)
* [查看进程 UID](#查看进程-uid)
* [其它](#其它)
* [常见问题](#常见问题)
* [启动 adb server 失败](#启动-adb-server-失败)
* [com.android.ddmlib.AdbCommandRejectedException](#comandroidddmlibadbcommandrejectedexception)
* [adb 的非官方实现](#adb-的非官方实现)
* [相关命令](#相关命令)
* [致谢](#致谢)
* [参考链接](#参考链接)
## 基本用法
### 命令语法
adb 命令的基本语法如下:
```sh
adb [-d|-e|-s ]
```
如果只有一个设备/模拟器连接时,可以省略掉 `[-d|-e|-s ]` 这一部分,直接使用 `adb `。
### 为命令指定目标设备
如果有多个设备/模拟器连接,则需要为命令指定目标设备。
| 参数 | 含义 |
|---------------------|----------------------------------------------------|
| -d | 指定当前唯一通过 USB 连接的 Android 设备为命令目标 |
| -e | 指定当前唯一运行的模拟器为命令目标 |
| `-s ` | 指定相应 serialNumber 号的设备/模拟器为命令目标 |
在多个设备/模拟器连接的情况下较常用的是 `-s ` 参数,serialNumber 可以通过 `adb devices` 命令获取。如:
```sh
$ adb devices
List of devices attached
cf264b8f device
emulator-5554 device
10.129.164.6:5555 device
```
输出里的 `cf264b8f`、`emulator-5554` 和 `10.129.164.6:5555` 即为 serialNumber。
比如这时想指定 `cf264b8f` 这个设备来运行 adb 命令获取屏幕分辨率:
```sh
adb -s cf264b8f shell wm size
```
又如想给 `10.129.164.6:5555` 这个设备安装应用(*这种形式的 serialNumber 格式为 `:`,一般为无线连接的设备或 Genymotion 等第三方 Android 模拟器*):
```sh
adb -s 10.129.164.6:5555 install test.apk
```
**遇到多设备/模拟器的情况均使用这几个参数为命令指定目标设备,下文中为简化描述,不再重复。**
### 启动/停止
启动 adb server 命令:
```sh
adb start-server
```
(一般无需手动执行此命令,在运行 adb 命令时若发现 adb server 没有启动会自动调起。)
停止 adb server 命令:
```sh
adb kill-server
```
### 查看 adb 版本
命令:
```sh
adb version
```
示例输出:
```sh
Android Debug Bridge version 1.0.36
Revision 8f855a3d9b35-android
```
### 以 root 权限运行 adbd
adb 的运行原理是 PC 端的 adb server 与手机端的守护进程 adbd 建立连接,然后 PC 端的 adb client 通过 adb server 转发命令,adbd 接收命令后解析运行。
所以如果 adbd 以普通权限执行,有些需要 root 权限才能执行的命令无法直接用 `adb xxx` 执行。这时可以 `adb shell` 然后 `su` 后执行命令,也可以让 adbd 以 root 权限执行,这个就能随意执行高权限命令了。
命令:
```sh
adb root
```
正常输出:
```sh
restarting adbd as root
```
现在再运行 `adb shell`,看看命令行提示符是不是变成 `#` 了?
有些手机 root 后也无法通过 `adb root` 命令让 adbd 以 root 权限执行,比如三星的部分机型,会提示 `adbd cannot run as root in production builds`,此时可以先安装 adbd Insecure,然后 `adb root` 试试。
相应地,如果要恢复 adbd 为非 root 权限的话,可以使用 `adb unroot` 命令。
### 指定 adb server 的网络端口
命令:
```sh
adb -P start-server
```
默认端口为 5037。
## 设备连接管理
### 查询已连接设备/模拟器
命令:
```sh
adb devices
```
输出示例:
```sh
List of devices attached
cf264b8f device
emulator-5554 device
10.129.164.6:5555 device
```
输出格式为 `[serialNumber] [state]`,serialNumber 即我们常说的 SN,state 有如下几种:
* `offline` —— 表示设备未连接成功或无响应。
* `device` —— 设备已连接。注意这个状态并不能标识 Android 系统已经完全启动和可操作,在设备启动过程中设备实例就可连接到 adb,但启动完毕后系统才处于可操作状态。
* `no device` —— 没有设备/模拟器连接。
以上输出显示当前已经连接了三台设备/模拟器,`cf264b8f`、`emulator-5554` 和 `10.129.164.6:5555` 分别是它们的 SN。从 `emulator-5554` 这个名字可以看出它是一个 Android 模拟器,而 `10.129.164.6:5555` 这种形为 `:` 的 serialNumber 一般是无线连接的设备或 Genymotion 等第三方 Android 模拟器。
常见异常输出:
1. 没有设备/模拟器连接成功。
```sh
List of devices attached
```
2. 设备/模拟器未连接到 adb 或无响应。
```sh
List of devices attached
cf264b8f offline
```
### USB 连接
通过 USB 连接来正常使用 adb 需要保证几点:
1. 硬件状态正常。
包括 Android 设备处于正常开机状态,USB 连接线和各种接口完好。
2. Android 设备的开发者选项和 USB 调试模式已开启。
可以到「设置」-「开发者选项」-「Android 调试」查看。
如果在设置里找不到开发者选项,那需要通过一个彩蛋来让它显示出来:在「设置」-「关于手机」连续点击「版本号」7 次。
3. 设备驱动状态正常。
这一点貌似在 Linux 和 Mac OS X 下不用操心,在 Windows 下有可能遇到需要安装驱动的情况,确认这一点可以右键「计算机」-「属性」,到「设备管理器」里查看相关设备上是否有黄色感叹号或问号,如果没有就说明驱动状态已经好了。否则可以下载一个手机助手类程序来安装驱动先。
4. 通过 USB 线连接好电脑和设备后确认状态。
```sh
adb devices
```
如果能看到
```sh
xxxxxx device
```
说明连接成功。
### 无线连接(Android11 及以上)
Android 11 及更高版本支持使用 Android 调试桥 (adb) 从工作站以无线方式部署和调试应用。例如,您可以将可调试应用部署到多台远程设备,而无需通过 USB 实际连接设备。这样就可以避免常见的 USB 连接问题,例如驱动程序安装方面的问题。
[官方文档](https://developer.android.com/studio/command-line/adb?hl=zh_cn#connect-to-a-device-over-wi-fi-android-11+)
操作步骤:
1. 更新到最新版本的 [SDK 平台工具](https://developer.android.com/studio/releases/platform-tools?hl=zh_cn)(至少30.0.0)。
2. 将 Android 设备与要运行 adb 的电脑连接到同一个局域网,比如连到同一个 WiFi。
3. 在开发者选项中启用**无线调试**。
4. 在询问要允许在此网络上进行无线调试吗?的对话框中,点击允许。
5. 选择使用配对码配对设备,使用弹窗中的 IP 地址和端口号。
```sh
adb pair ipaddr:port
```
6. 提示`Enter pairing code: `时输入弹窗中的配对码,成功后会显示`Successfully paired to ...`。
7. 使用无线调试下的 **IP 地址和端口**。
```sh
adb connect ipaddr:port
```
8. 确认连接状态。
```sh
adb devices
```
如果能看到
```sh
ipaddr:port device
```
说明连接成功。
### 无线连接(需要借助 USB 线)
除了可以通过 USB 连接设备与电脑来使用 adb,也可以通过无线连接——虽然连接过程中也有需要使用 USB 的步骤,但是连接成功之后你的设备就可以在一定范围内摆脱 USB 连接线的限制啦!
操作步骤:
1. 将 Android 设备与要运行 adb 的电脑连接到同一个局域网,比如连到同一个 WiFi。
2. 将设备与电脑通过 USB 线连接。
应确保连接成功(可运行 `adb devices` 看是否能列出该设备)。
3. 让设备在 5555 端口监听 TCP/IP 连接:
```sh
adb tcpip 5555
```
4. 断开 USB 连接。
5. 找到设备的 IP 地址。
一般能在「设置」-「关于手机」-「状态信息」-「IP地址」找到,也可以使用下文里 [查看设备信息 - IP 地址][1] 一节里的方法用 adb 命令来查看。
6. 通过 IP 地址连接设备。
```sh
adb connect
```
这里的 `` 就是上一步中找到的设备 IP 地址。
7. 确认连接状态。
```sh
adb devices
```
如果能看到
```sh
:5555 device
```
说明连接成功。
如果连接不了,请确认 Android 设备与电脑是连接到了同一个 WiFi,然后再次执行 `adb connect ` 那一步;
如果还是不行的话,通过 `adb kill-server` 重新启动 adb 然后从头再来一次试试。
**断开无线连接**
命令:
```sh
adb disconnect
```
### 无线连接(无需借助 USB 线)
**注:需要 root 权限。**
上一节「无线连接(需要借助 USB 线)」是官方文档里介绍的方法,需要借助于 USB 数据线来实现无线连接。
既然我们想要实现无线连接,那能不能所有步骤下来都是无线的呢?答案是能的。
1. 在 Android 设备上安装一个终端模拟器。
已经安装过的设备可以跳过此步。我使用的终端模拟器下载地址是:[Terminal Emulator for Android Downloads](https://jackpal.github.io/Android-Terminal-Emulator/)
2. 将 Android 设备与要运行 adb 的电脑连接到同一个局域网,比如连到同一个 WiFi。
3. 打开 Android 设备上的终端模拟器,在里面依次运行命令:
```sh
su
setprop service.adb.tcp.port 5555
```
4. 找到 Android 设备的 IP 地址。
一般能在「设置」-「关于手机」-「状态信息」-「IP地址」找到,也可以使用下文里 [查看设备信息 - IP 地址][1] 一节里的方法用 adb 命令来查看。
5. 在电脑上通过 adb 和 IP 地址连接 Android 设备。
```sh
adb connect
```
这里的 `` 就是上一步中找到的设备 IP 地址。
如果能看到 `connected to :5555` 这样的输出则表示连接成功。
*节注一:*
有的设备,比如小米 5S + MIUI 8.0 + Android 6.0.1 MXB48T,可能在第 5 步之前需要重启 adbd 服务,在设备的终端模拟器上运行:
```sh
restart adbd
```
如果 restart 无效,尝试以下命令:
```sh
stop adbd
start adbd
```
## 应用管理
### 查看应用列表
查看应用列表的基本命令格式是
```sh
adb shell pm list packages [-f] [-d] [-e] [-s] [-3] [-i] [-u] [--user USER_ID] [FILTER]
```
即在 `adb shell pm list packages` 的基础上可以加一些参数进行过滤查看不同的列表,支持的过滤参数如下:
| 参数 | 显示列表 |
|------------|----------------------------|
| 无 | 所有应用 |
| -f | 显示应用关联的 apk 文件 |
| -d | 只显示 disabled 的应用 |
| -e | 只显示 enabled 的应用 |
| -s | 只显示系统应用 |
| -3 | 只显示第三方应用 |
| -i | 显示应用的 installer |
| -u | 包含已卸载应用 |
| `` | 包名包含 `` 字符串 |
#### 所有应用
命令:
```sh
adb shell pm list packages
```
输出示例:
```sh
package:com.android.smoketest
package:com.example.android.livecubes
package:com.android.providers.telephony
package:com.google.android.googlequicksearchbox
package:com.android.providers.calendar
package:com.android.providers.media
package:com.android.protips
package:com.android.documentsui
package:com.android.gallery
package:com.android.externalstorage
...
// other packages here
...
```
#### 系统应用
命令:
```sh
adb shell pm list packages -s
```
#### 第三方应用
命令:
```sh
adb shell pm list packages -3
```
#### 包名包含某字符串的应用
比如要查看包名包含字符串 `mazhuang` 的应用列表,命令:
```sh
adb shell pm list packages mazhuang
```
当然也可以使用 grep 来过滤:
```sh
adb shell pm list packages | grep mazhuang
```
### 安装 APK
命令格式:
```sh
adb install [-lrtsdg]
```
参数:
`adb install` 后面可以跟一些可选参数来控制安装 APK 的行为,可用参数及含义如下:
| 参数 | 含义 |
|------|-----------------------------------------------------------------------------------|
| -l | 将应用安装到保护目录 /mnt/asec |
| -r | 允许覆盖安装 |
| -t | 允许安装 AndroidManifest.xml 里 application 指定 `android:testOnly="true"` 的应用 |
| -s | 将应用安装到 sdcard |
| -d | 允许降级覆盖安装 |
| -g | 授予所有运行时权限 |
运行命令后如果见到类似如下输出(状态为 `Success`)代表安装成功:
```sh
[100%] /data/local/tmp/1.apk
pkg: /data/local/tmp/1.apk
Success
```
上面是当前最新版 v1.0.36 的 adb 的输出,会显示 push apk 文件到手机的进度百分比。
使用旧版本 adb 的输出则是这样的:
```sh
12040 KB/s (22205609 bytes in 1.801s)
pkg: /data/local/tmp/SogouInput_android_v8.3_sweb.apk
Success
```
而如果状态为 `Failure` 则表示安装失败,比如:
```sh
[100%] /data/local/tmp/map-20160831.apk
pkg: /data/local/tmp/map-20160831.apk
Failure [INSTALL_FAILED_ALREADY_EXISTS]
```
常见安装失败输出代码、含义及可能的解决办法如下:
| 输出 | 含义 | 解决办法 |
|---------------------------------------------------------------------|--------------------------------------------------------------------------|------------------------------------------------------------------------------------|
| INSTALL\_FAILED\_ALREADY\_EXISTS | 应用已经存在,或卸载了但没卸载干净 | `adb install` 时使用 `-r` 参数,或者先 `adb uninstall ` 再安装 |
| INSTALL\_FAILED\_INVALID\_APK | 无效的 APK 文件 | |
| INSTALL\_FAILED\_INVALID\_URI | 无效的 APK 文件名 | 确保 APK 文件名里无中文 |
| INSTALL\_FAILED\_INSUFFICIENT\_STORAGE | 空间不足 | 清理空间 |
| INSTALL\_FAILED\_DUPLICATE\_PACKAGE | 已经存在同名程序 | |
| INSTALL\_FAILED\_NO\_SHARED\_USER | 请求的共享用户不存在 | |
| INSTALL\_FAILED\_UPDATE\_INCOMPATIBLE | 以前安装过同名应用,但卸载时数据没有移除;或者已安装该应用,但签名不一致 | 先 `adb uninstall ` 再安装 |
| INSTALL\_FAILED\_SHARED\_USER\_INCOMPATIBLE | 请求的共享用户存在但签名不一致 | |
| INSTALL\_FAILED\_MISSING\_SHARED\_LIBRARY | 安装包使用了设备上不可用的共享库 | |
| INSTALL\_FAILED\_REPLACE\_COULDNT\_DELETE | 替换时无法删除 | |
| INSTALL\_FAILED\_DEXOPT | dex 优化验证失败或空间不足 | |
| INSTALL\_FAILED\_OLDER\_SDK | 设备系统版本低于应用要求 | |
| INSTALL\_FAILED\_CONFLICTING\_PROVIDER | 设备里已经存在与应用里同名的 content provider | |
| INSTALL\_FAILED\_NEWER\_SDK | 设备系统版本高于应用要求 | |
| INSTALL\_FAILED\_TEST\_ONLY | 应用是 test-only 的,但安装时没有指定 `-t` 参数 | |
| INSTALL\_FAILED\_CPU\_ABI\_INCOMPATIBLE | 包含不兼容设备 CPU 应用程序二进制接口的 native code | |
| INSTALL\_FAILED\_MISSING\_FEATURE | 应用使用了设备不可用的功能 | |
| INSTALL\_FAILED\_CONTAINER\_ERROR | 1. sdcard 访问失败;
2. 应用签名与 ROM 签名一致,被当作内置应用。 | 1. 确认 sdcard 可用,或者安装到内置存储;
2. 打包时不与 ROM 使用相同签名。 |
| INSTALL\_FAILED\_INVALID\_INSTALL\_LOCATION | 1. 不能安装到指定位置;
2. 应用签名与 ROM 签名一致,被当作内置应用。 | 1. 切换安装位置,添加或删除 `-s` 参数;
2. 打包时不与 ROM 使用相同签名。 |
| INSTALL\_FAILED\_MEDIA\_UNAVAILABLE | 安装位置不可用 | 一般为 sdcard,确认 sdcard 可用或安装到内置存储 |
| INSTALL\_FAILED\_VERIFICATION\_TIMEOUT | 验证安装包超时 | |
| INSTALL\_FAILED\_VERIFICATION\_FAILURE | 验证安装包失败 | |
| INSTALL\_FAILED\_PACKAGE\_CHANGED | 应用与调用程序期望的不一致 | |
| INSTALL\_FAILED\_UID\_CHANGED | 以前安装过该应用,与本次分配的 UID 不一致 | 清除以前安装过的残留文件 |
| INSTALL\_FAILED\_VERSION\_DOWNGRADE | 已经安装了该应用更高版本 | 使用 `-d` 参数 |
| INSTALL\_FAILED\_PERMISSION\_MODEL\_DOWNGRADE | 已安装 target SDK 支持运行时权限的同名应用,要安装的版本不支持运行时权限 | |
| INSTALL\_PARSE\_FAILED\_NOT\_APK | 指定路径不是文件,或不是以 `.apk` 结尾 | |
| INSTALL\_PARSE\_FAILED\_BAD\_MANIFEST | 无法解析的 AndroidManifest.xml 文件 | |
| INSTALL\_PARSE\_FAILED\_UNEXPECTED\_EXCEPTION | 解析器遇到异常 | |
| INSTALL\_PARSE\_FAILED\_NO\_CERTIFICATES | 安装包没有签名 | |
| INSTALL\_PARSE\_FAILED\_INCONSISTENT\_CERTIFICATES | 已安装该应用,且签名与 APK 文件不一致 | 先卸载设备上的该应用,再安装 |
| INSTALL\_PARSE\_FAILED\_CERTIFICATE\_ENCODING | 解析 APK 文件时遇到 `CertificateEncodingException` | |
| INSTALL\_PARSE\_FAILED\_BAD\_PACKAGE\_NAME | manifest 文件里没有或者使用了无效的包名 | |
| INSTALL\_PARSE\_FAILED\_BAD\_SHARED\_USER\_ID | manifest 文件里指定了无效的共享用户 ID | |
| INSTALL\_PARSE\_FAILED\_MANIFEST\_MALFORMED | 解析 manifest 文件时遇到结构性错误 | |
| INSTALL\_PARSE\_FAILED\_MANIFEST\_EMPTY | 在 manifest 文件里找不到找可操作标签(instrumentation 或 application) | |
| INSTALL\_FAILED\_INTERNAL\_ERROR | 因系统问题安装失败 | |
| INSTALL\_FAILED\_USER\_RESTRICTED | 用户被限制安装应用 | 在开发者选项里将「USB安装」打开,如果已经打开了,那先关闭再打开。 |
| INSTALL\_FAILED\_DUPLICATE\_PERMISSION | 应用尝试定义一个已经存在的权限名称 | |
| INSTALL\_FAILED\_NO\_MATCHING\_ABIS | 应用包含设备的应用程序二进制接口不支持的 native code | |
| INSTALL\_CANCELED\_BY\_USER | 应用安装需要在设备上确认,但未操作设备或点了取消 | 在设备上同意安装 |
| INSTALL\_FAILED\_ACWF\_INCOMPATIBLE | 应用程序与设备不兼容 | |
| INSTALL_FAILED_TEST_ONLY | APK 文件是使用 Android Studio 直接 RUN 编译出来的文件 | 通过 Gradle 的 assembleDebug 或 assembleRelease 重新编译,或者 Generate Signed APK |
| does not contain AndroidManifest.xml | 无效的 APK 文件 | |
| is not a valid zip file | 无效的 APK 文件 | |
| Offline | 设备未连接成功 | 先将设备与 adb 连接成功 |
| unauthorized | 设备未授权允许调试 | |
| error: device not found | 没有连接成功的设备 | 先将设备与 adb 连接成功 |
| protocol failure | 设备已断开连接 | 先将设备与 adb 连接成功 |
| Unknown option: -s | Android 2.2 以下不支持安装到 sdcard | 不使用 `-s` 参数 |
| No space left on device | 空间不足 | 清理空间 |
| Permission denied ... sdcard ... | sdcard 不可用 | |
| signatures do not match the previously installed version; ignoring! | 已安装该应用且签名不一致 | 先卸载设备上的该应用,再安装 |
参考:[PackageManager.java](https://github.com/android/platform_frameworks_base/blob/master/core%2Fjava%2Fandroid%2Fcontent%2Fpm%2FPackageManager.java)
*`adb install` 内部原理简介*
`adb install` 实际是分三步完成:
1. push apk 文件到 /data/local/tmp。
2. 调用 pm install 安装。
3. 删除 /data/local/tmp 下的对应 apk 文件。
所以,必要的时候也可以根据这个步骤,手动分步执行安装过程。
### 卸载应用
命令:
```sh
adb uninstall [-k]
```
`` 表示应用的包名,`-k` 参数可选,表示卸载应用但保留数据和缓存目录。
命令示例:
```sh
adb uninstall com.qihoo360.mobilesafe
```
表示卸载 360 手机卫士。
### 清除应用数据与缓存
命令:
```sh
adb shell pm clear
```
`` 表示应用名包,这条命令的效果相当于在设置里的应用信息界面点击了「清除缓存」和「清除数据」。
命令示例:
```sh
adb shell pm clear com.qihoo360.mobilesafe
```
表示清除 360 手机卫士的数据和缓存。
### 查看前台 Activity
命令:
```sh
adb shell dumpsys activity activities | grep mResumedActivity
```
输出示例:
```sh
mResumedActivity: ActivityRecord{8079d7e u0 com.cyanogenmod.trebuchet/com.android.launcher3.Launcher t42}
```
其中的 `com.cyanogenmod.trebuchet/com.android.launcher3.Launcher` 就是当前处于前台的 Activity。
*在 Windows 下以上命令可能不可用,可以尝试 `adb shell dumpsys activity activities | findstr mResumedActivity` 或 `adb shell "dumpsys activity activities | grep mResumedActivity"`。*
### 查看正在运行的 Services
命令:
```sh
adb shell dumpsys activity services []
```
`` 参数不是必须的,指定 `` 表示查看与某个包名相关的 Services,不指定表示查看所有 Services。
`` 不一定要给出完整的包名,比如运行 `adb shell dumpsys activity services org.mazhuang`,那么包名 `org.mazhuang.demo1`、`org.mazhuang.demo2` 和 `org.mazhuang123` 等相关的 Services 都会列出来。
### 查看应用详细信息
命令:
```sh
adb shell dumpsys package
```
输出中包含很多信息,包括 Activity Resolver Table、Registered ContentProviders、包名、userId、安装后的文件资源代码等路径、版本信息、权限信息和授予状态、签名版本信息等。
`` 表示应用包名。
输出示例:
```sh
Activity Resolver Table:
Non-Data Actions:
android.intent.action.MAIN:
5b4cba8 org.mazhuang.guanggoo/.SplashActivity filter 5ec9dcc
Action: "android.intent.action.MAIN"
Category: "android.intent.category.LAUNCHER"
AutoVerify=false
Registered ContentProviders:
org.mazhuang.guanggoo/com.tencent.bugly.beta.utils.BuglyFileProvider:
Provider{7a3c394 org.mazhuang.guanggoo/com.tencent.bugly.beta.utils.BuglyFileProvider}
ContentProvider Authorities:
[org.mazhuang.guanggoo.fileProvider]:
Provider{7a3c394 org.mazhuang.guanggoo/com.tencent.bugly.beta.utils.BuglyFileProvider}
applicationInfo=ApplicationInfo{7754242 org.mazhuang.guanggoo}
Key Set Manager:
[org.mazhuang.guanggoo]
Signing KeySets: 501
Packages:
Package [org.mazhuang.guanggoo] (c1d7f):
userId=10394
pkg=Package{55f714c org.mazhuang.guanggoo}
codePath=/data/app/org.mazhuang.guanggoo-2
resourcePath=/data/app/org.mazhuang.guanggoo-2
legacyNativeLibraryDir=/data/app/org.mazhuang.guanggoo-2/lib
primaryCpuAbi=null
secondaryCpuAbi=null
versionCode=74 minSdk=15 targetSdk=25
versionName=1.1.74
splits=[base]
apkSigningVersion=2
applicationInfo=ApplicationInfo{7754242 org.mazhuang.guanggoo}
flags=[ HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
privateFlags=[ RESIZEABLE_ACTIVITIES ]
dataDir=/data/user/0/org.mazhuang.guanggoo
supportsScreens=[small, medium, large, xlarge, resizeable, anyDensity]
timeStamp=2017-10-22 23:50:53
firstInstallTime=2017-10-22 23:50:25
lastUpdateTime=2017-10-22 23:50:55
installerPackageName=com.miui.packageinstaller
signatures=PackageSignatures{af09595 [53c7caa2]}
installPermissionsFixed=true installStatus=1
pkgFlags=[ HAS_CODE ALLOW_CLEAR_USER_DATA ALLOW_BACKUP ]
requested permissions:
android.permission.READ_PHONE_STATE
android.permission.INTERNET
android.permission.ACCESS_NETWORK_STATE
android.permission.ACCESS_WIFI_STATE
android.permission.READ_LOGS
android.permission.WRITE_EXTERNAL_STORAGE
android.permission.READ_EXTERNAL_STORAGE
install permissions:
android.permission.INTERNET: granted=true
android.permission.ACCESS_NETWORK_STATE: granted=true
android.permission.ACCESS_WIFI_STATE: granted=true
User 0: ceDataInode=1155675 installed=true hidden=false suspended=false stopped=true notLaunched=false enabled=0
gids=[3003]
runtime permissions:
android.permission.READ_EXTERNAL_STORAGE: granted=true
android.permission.READ_PHONE_STATE: granted=true
android.permission.WRITE_EXTERNAL_STORAGE: granted=true
User 999: ceDataInode=0 installed=false hidden=false suspended=false stopped=true notLaunched=true enabled=0
gids=[3003]
runtime permissions:
Dexopt state:
[org.mazhuang.guanggoo]
Instruction Set: arm64
path: /data/app/org.mazhuang.guanggoo-2/base.apk
status: /data/app/org.mazhuang.guanggoo-2/oat/arm64/base.odex [compilation_filter=speed-profile, status=kOatUpToDa
te]
```
### 查看应用安装路径
命令:
```
adb shell pm path
```
输出应用安装路径
输出示例:
```
adb shell pm path ecarx.weather
package:/data/app/ecarx.weather-1.apk
```
## 与应用交互
主要是使用 `am ` 命令,常用的 `` 如下:
| command | 用途 |
|-----------------------------------|---------------------------------|
| `start [options] ` | 启动 `` 指定的 Activity |
| `startservice [options] ` | 启动 `` 指定的 Service |
| `broadcast [options] ` | 发送 `` 指定的广播 |
| `force-stop ` | 停止 `` 相关的进程 |
`` 参数很灵活,和写 Android 程序时代码里的 Intent 相对应。
用于决定 intent 对象的选项如下:
| 参数 | 含义 |
|------------------|---------------------------------------------------------------------------------------------|
| `-a ` | 指定 action,比如 `android.intent.action.VIEW` |
| `-c ` | 指定 category,比如 `android.intent.category.APP_CONTACTS` |
| `-n ` | 指定完整 component 名,用于明确指定启动哪个 Activity,如 `com.example.app/.ExampleActivity` |
`` 里还能带数据,就像写代码时的 Bundle 一样:
| 参数 | 含义 |
|---------------------------------------------------------------|----------------------------------------|
| `--esn ` | null 值(只有 key 名) |
| `-e|--es ` | string 值 |
| `--ez ` | boolean 值 |
| `--ei ` | integer 值 |
| `--el ` | long 值 |
| `--ef ` | float 值 |
| `--eu ` | URI |
| `--ecn ` | component name |
| `--eia [, [, 指定Activity名称启动
命令格式:
```sh
adb shell am start [options]
```
例如:
```sh
adb shell am start -n com.tencent.mm/.ui.LauncherUI
```
表示调起微信主界面。
```sh
adb shell am start -n org.mazhuang.boottimemeasure/.MainActivity --es "toast" "hello, world"
```
表示调起 `org.mazhuang.boottimemeasure/.MainActivity` 并传给它 string 数据键值对 `toast - hello, world`。
> 不指定Activity名称启动(启动主Activity)
命令格式:
```sh
adb shell monkey -p -c android.intent.category.LAUNCHER 1
```
例如:
```sh
adb shell monkey -p com.tencent.mm -c android.intent.category.LAUNCHER 1
```
表示调起微信主界面。
### 调起 Service
命令格式:
```sh
adb shell am startservice [options]
```
例如:
```sh
adb shell am startservice -n com.tencent.mm/.plugin.accountsync.model.AccountAuthenticatorService
```
表示调起微信的某 Service。
另外一个典型的用例是如果设备上原本应该显示虚拟按键但是没有显示,可以试试这个:
```sh
adb shell am startservice -n com.android.systemui/.SystemUIService
```
### 停止 Service
命令格式:
```sh
adb shell am stopservice [options]
```
### 发送广播
命令格式:
```sh
adb shell am broadcast [options]
```
可以向所有组件广播,也可以只向指定组件广播。
例如,向所有组件广播 `BOOT_COMPLETED`:
```sh
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED
```
又例如,只向 `org.mazhuang.boottimemeasure/.BootCompletedReceiver` 广播 `BOOT_COMPLETED`:
```sh
adb shell am broadcast -a android.intent.action.BOOT_COMPLETED -n org.mazhuang.boottimemeasure/.BootCompletedReceiver
```
这类用法在测试的时候很实用,比如某个广播的场景很难制造,可以考虑通过这种方式来发送广播。
既能发送系统预定义的广播,也能发送自定义广播。如下是部分系统预定义广播及正常触发时机:
| action | 触发时机 |
|-------------------------------------------------|-----------------------------------------------|
| android.net.conn.CONNECTIVITY_CHANGE | 网络连接发生变化 |
| android.intent.action.SCREEN_ON | 屏幕点亮 |
| android.intent.action.SCREEN_OFF | 屏幕熄灭 |
| android.intent.action.BATTERY_LOW | 电量低,会弹出电量低提示框 |
| android.intent.action.BATTERY_OKAY | 电量恢复了 |
| android.intent.action.BOOT_COMPLETED | 设备启动完毕 |
| android.intent.action.DEVICE_STORAGE_LOW | 存储空间过低 |
| android.intent.action.DEVICE_STORAGE_OK | 存储空间恢复 |
| android.intent.action.PACKAGE_ADDED | 安装了新的应用 |
| android.net.wifi.STATE_CHANGE | WiFi 连接状态发生变化 |
| android.net.wifi.WIFI_STATE_CHANGED | WiFi 状态变为启用/关闭/正在启动/正在关闭/未知 |
| android.intent.action.BATTERY_CHANGED | 电池电量发生变化 |
| android.intent.action.INPUT_METHOD_CHANGED | 系统输入法发生变化 |
| android.intent.action.ACTION_POWER_CONNECTED | 外部电源连接 |
| android.intent.action.ACTION_POWER_DISCONNECTED | 外部电源断开连接 |
| android.intent.action.DREAMING_STARTED | 系统开始休眠 |
| android.intent.action.DREAMING_STOPPED | 系统停止休眠 |
| android.intent.action.WALLPAPER_CHANGED | 壁纸发生变化 |
| android.intent.action.HEADSET_PLUG | 插入耳机 |
| android.intent.action.MEDIA_UNMOUNTED | 卸载外部介质 |
| android.intent.action.MEDIA_MOUNTED | 挂载外部介质 |
| android.os.action.POWER_SAVE_MODE_CHANGED | 省电模式开启 |
*(以上广播均可使用 adb 触发)*
### 强制停止应用
命令:
```sh
adb shell am force-stop
```
命令示例:
```sh
adb shell am force-stop com.qihoo360.mobilesafe
```
表示停止 360 安全卫士的一切进程与服务。
### 收紧内存
命令:
```sh
adb shell am send-trim-memory
```
pid: 进程 ID
level:
HIDDEN、RUNNING_MODERATE、BACKGROUND、
RUNNING_LOW、MODERATE、RUNNING_CRITICAL、COMPLETE
命令示例:
```sh
adb shell am send-trim-memory 12345 RUNNING_LOW
```
表示向 pid=12345 的进程,发出 level=RUNNING_LOW 的收紧内存命令。
## 文件管理
### 复制设备里的文件到电脑
命令:
```sh
adb pull <设备里的文件路径> [电脑上的目录]
```
其中 `电脑上的目录` 参数可以省略,默认复制到当前目录。
例:
```sh
adb pull /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`。
### 复制电脑里的文件到设备
命令:
```sh
adb push <电脑上的文件路径> <设备里的目录>
```
例:
```sh
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`。
## 模拟按键/输入
在 `adb shell` 里有个很实用的命令叫 `input`,通过它可以做一些有趣的事情。
`input` 命令的完整 help 信息如下:
```sh
Usage: input [