ADB(2)(字数限制拆分)
## 与应用交互
主要是使用 `am <command>` 命令,常用的 `<command>` 如下:
| command | 用途 |
|-----------------------------------|---------------------------------|
| `start [options] <INTENT>` | 启动 `<INTENT>` 指定的 Activity |
| `startservice [options] <INTENT>` | 启动 `<INTENT>` 指定的 Service |
| `broadcast [options] <INTENT>` | 发送 `<INTENT>` 指定的广播 |
| `force-stop <packagename>` | 停止 `<packagename>` 相关的进程 |
`<INTENT>` 参数很灵活,和写 Android 程序时代码里的 Intent 相对应。
用于决定 intent 对象的选项如下:
| 参数 | 含义 |
|------------------|---------------------------------------------------------------------------------------------|
| `-a <ACTION>` | 指定 action,比如 `android.intent.action.VIEW` |
| `-c <CATEGORY>` | 指定 category,比如 `android.intent.category.APP_CONTACTS` |
| `-n <COMPONENT>` | 指定完整 component 名,用于明确指定启动哪个 Activity,如 `com.example.app/.ExampleActivity` |
`<INTENT>` 里还能带数据,就像写代码时的 Bundle 一样:
| 参数 | 含义 |
|---------------------------------------------------------------|----------------------------------------|
| `--esn <EXTRA_KEY>` | null 值(只有 key 名) |
| `-e|--es <EXTRA_KEY> <EXTRA_STRING_VALUE>` | string 值 |
| `--ez <EXTRA_KEY> <EXTRA_BOOLEAN_VALUE>` | boolean 值 |
| `--ei <EXTRA_KEY> <EXTRA_INT_VALUE>` | integer 值 |
| `--el <EXTRA_KEY> <EXTRA_LONG_VALUE>` | long 值 |
| `--ef <EXTRA_KEY> <EXTRA_FLOAT_VALUE>` | float 值 |
| `--eu <EXTRA_KEY> <EXTRA_URI_VALUE>` | URI |
| `--ecn <EXTRA_KEY> <EXTRA_COMPONENT_NAME_VALUE>` | component name |
| `--eia <EXTRA_KEY> <EXTRA_INT_VALUE>[,<EXTRA_INT_VALUE...]` | integer 数组 |
| `--ela <EXTRA_KEY> <EXTRA_LONG_VALUE>[,<EXTRA_LONG_VALUE...]` | long 数组 |
### 启动应用/ 调起 Activity
命令格式:
```sh
adb shell am start [options] <INTENT>
```
例如:
```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`。
### 调起 Service
命令格式:
```sh
adb shell am startservice [options] <INTENT>
```
例如:
```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] <INTENT>
```
### 发送广播
命令格式:
```sh
adb shell am broadcast [options] <INTENT>
```
可以向所有组件广播,也可以只向指定组件广播。
例如,向所有组件广播 `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 <packagename>
```
命令示例:
```sh
adb shell am force-stop com.qihoo360.mobilesafe
```
表示停止 360 安全卫士的一切进程与服务。
### 收紧内存
命令:
```sh
adb shell am send-trim-memory <pid> <level>
```
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 [<source>] <command> [<arg>...]
The sources are:
mouse
keyboard
joystick
touchnavigation
touchpad
trackball
stylus
dpad
gesture
touchscreen
gamepad
The commands and default sources are:
text <string> (Default: touchscreen)
keyevent [--longpress] <key code number or name> ... (Default: keyboard)
tap <x> <y> (Default: touchscreen)
swipe <x1> <y1> <x2> <y2> [duration(ms)] (Default: touchscreen)
press (Default: trackball)
roll <dx> <dy> (Default: trackball)
```
比如使用 `adb shell input keyevent <keycode>` 命令,不同的 keycode 能实现不同的功能,完整的 keycode 列表详见 [KeyEvent](https://developer.android.com/reference/android/view/KeyEvent.html),摘引部分我觉得有意思的如下:
| keycode | 含义 |
|---------|--------------------------------|
| 3 | HOME 键 |
| 4 | 返回键 |
| 5 | 打开拨号应用 |
| 6 | 挂断电话 |
| 24 | 增加音量 |
| 25 | 降低音量 |
| 26 | 电源键 |
| 27 | 拍照(需要在相机应用里) |
| 64 | 打开浏览器 |
| 82 | 菜单键 |
| 85 | 播放/暂停 |
| 86 | 停止播放 |
| 87 | 播放下一首 |
| 88 | 播放上一首 |
| 122 | 移动光标到行首或列表顶部 |
| 123 | 移动光标到行末或列表底部 |
| 126 | 恢复播放 |
| 127 | 暂停播放 |
| 164 | 静音 |
| 176 | 打开系统设置 |
| 187 | 切换应用 |
| 207 | 打开联系人 |
| 208 | 打开日历 |
| 209 | 打开音乐 |
| 210 | 打开计算器 |
| 220 | 降低屏幕亮度 |
| 221 | 提高屏幕亮度 |
| 223 | 系统休眠 |
| 224 | 点亮屏幕 |
| 231 | 打开语音助手 |
| 276 | 如果没有 wakelock 则让系统休眠 |
下面是 `input` 命令的一些用法举例。
### 电源键
命令:
```sh
adb shell input keyevent 26
```
执行效果相当于按电源键。
### 菜单键
命令:
```sh
adb shell input keyevent 82
```
### HOME 键
命令:
```sh
adb shell input keyevent 3
```
### 返回键
命令:
```sh
adb shell input keyevent 4
```
### 音量控制
增加音量:
```sh
adb shell input keyevent 24
```
降低音量:
```sh
adb shell input keyevent 25
```
静音:
```sh
adb shell input keyevent 164
```
### 媒体控制
播放/暂停:
```sh
adb shell input keyevent 85
```
停止播放:
```sh
adb shell input keyevent 86
```
播放下一首:
```sh
adb shell input keyevent 87
```
播放上一首:
```sh
adb shell input keyevent 88
```
恢复播放:
```sh
adb shell input keyevent 126
```
暂停播放:
```sh
adb shell input keyevent 127
```
### 点亮/熄灭屏幕
可以通过上文讲述过的模拟电源键来切换点亮和熄灭屏幕,但如果明确地想要点亮或者熄灭屏幕,那可以使用如下方法。
点亮屏幕:
```sh
adb shell input keyevent 224
```
熄灭屏幕:
```sh
adb shell input keyevent 223
```
### 滑动解锁
如果锁屏没有密码,是通过滑动手势解锁,那么可以通过 `input swipe` 来解锁。
命令(参数以机型 Nexus 5,向上滑动手势解锁举例):
```sh
adb shell input swipe 300 1000 300 500
```
参数 `300 1000 300 500` 分别表示`起始点x坐标 起始点y坐标 结束点x坐标 结束点y坐标`。
### 输入文本
在焦点处于某文本框时,可以通过 `input` 命令来输入文本。
命令:
```sh
adb shell input text hello
```
现在 `hello` 出现在文本框了。
## 查看日志
Android 系统的日志分为两部分,底层的 Linux 内核日志输出到 /proc/kmsg,Android 的日志输出到 /dev/log。
### Android 日志
命令格式:
```sh
[adb] logcat [<option>] ... [<filter-spec>] ...
```
常用用法列举如下:
#### 按级别过滤日志
Android 的日志分为如下几个优先级(priority):
* V —— Verbose(最低,输出得最多)
* D —— Debug
* I —— Info
* W —— Warning
* E —— Error
* F —— Fatal
* S —— Silent(最高,啥也不输出)
按某级别过滤日志则会将该级别及以上的日志输出。
比如,命令:
```sh
adb logcat *:W
```
会将 Warning、Error、Fatal 和 Silent 日志输出。
(**注:** 在 macOS 下需要给 `*:W` 这样以 `*` 作为 tag 的参数加双引号,如 `adb logcat "*:W"`,不然会报错 `no matches found: *:W`。)
#### 按 tag 和级别过滤日志
`<filter-spec>` 可以由多个 `<tag>[:priority]` 组成。
比如,命令:
```sh
adb logcat ActivityManager:I MyApp:D *:S
```
表示输出 tag `ActivityManager` 的 Info 以上级别日志,输出 tag `MyApp` 的 Debug 以上级别日志,及其它 tag 的 Silent 级别日志(即屏蔽其它 tag 日志)。
#### 日志格式
可以用 `adb logcat -v <format>` 选项指定日志输出格式。
日志支持按以下几种 `<format>`:
* brief
默认格式。格式为:
```sh
<priority>/<tag>(<pid>): <message>
```
示例:
```sh
D/HeadsetStateMachine( 1785): Disconnected process message: 10, size: 0
```
* process
格式为:
```sh
<priority>(<pid>) <message>
```
示例:
```sh
D( 1785) Disconnected process message: 10, size: 0 (HeadsetStateMachine)
```
* tag
格式为:
```sh
<priority>/<tag>: <message>
```
示例:
```sh
D/HeadsetStateMachine: Disconnected process message: 10, size: 0
```
* raw
格式为:
```sh
<message>
```
示例:
```sh
Disconnected process message: 10, size: 0
```
* time
格式为:
```sh
<datetime> <priority>/<tag>(<pid>): <message>
```
示例:
```sh
08-28 22:39:39.974 D/HeadsetStateMachine( 1785): Disconnected process message: 10, size: 0
```
* threadtime
格式为:
```sh
<datetime> <pid> <tid> <priority> <tag>: <message>
```
示例:
```sh
08-28 22:39:39.974 1785 1832 D HeadsetStateMachine: Disconnected process message: 10, size: 0
```
* long
格式为:
```sh
[ <datetime> <pid>:<tid> <priority>/<tag> ]
<message>
```
示例:
```sh
[ 08-28 22:39:39.974 1785: 1832 D/HeadsetStateMachine ]
Disconnected process message: 10, size: 0
```
指定格式可与上面的过滤同时使用。比如:
```sh
adb logcat -v long ActivityManager:I *:S
```
#### 清空日志
```sh
adb logcat -c
```
### 内核日志
命令:
```sh
adb shell dmesg
```
输出示例:
```sh
<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]` 代表内核开始启动后的时间,单位为秒。
通过内核日志我们可以做一些事情,比如衡量内核启动时间,在系统启动完毕后的内核日志里找到 `Freeing init memory` 那一行前面的时间就是。
## 查看设备信息
### 型号
命令:
```sh
adb shell getprop ro.product.model
```
输出示例:
```sh
Nexus 5
```
### 电池状况
命令:
```sh
adb shell dumpsys battery
```
输入示例:
```sh
Current Battery Service state:
AC powered: false
USB powered: true
Wireless powered: false
status: 2
health: 2
present: true
level: 44
scale: 100
voltage: 3872
temperature: 280
technology: Li-poly
```
其中 `scale` 代表最大电量,`level` 代表当前电量。上面的输出表示还剩下 44% 的电量。
### 屏幕分辨率
命令:
```sh
adb shell wm size
```
输出示例:
```sh
Physical size: 1080x1920
```
该设备屏幕分辨率为 1080px * 1920px。
如果使用命令修改过,那输出可能是:
```sh
Physical size: 1080x1920
Override size: 480x1024
```
表明设备的屏幕分辨率原本是 1080px * 1920px,当前被修改为 480px * 1024px。
### 屏幕密度
命令:
```sh
adb shell wm density
```
输出示例:
```sh
Physical density: 420
```
该设备屏幕密度为 420dpi。
如果使用命令修改过,那输出可能是:
```sh
Physical density: 480
Override density: 160
```
表明设备的屏幕密度原来是 480dpi,当前被修改为 160dpi。
### 显示屏参数
命令:
```sh
adb shell dumpsys window displays
```
输出示例:
```sh
WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)
Display: mDisplayId=0
init=1080x1920 420dpi cur=1080x1920 app=1080x1794 rng=1080x1017-1810x1731
deferred=false layoutNeeded=false
```
其中 `mDisplayId` 为 显示屏编号,`init` 是初始分辨率和屏幕密度,`app` 的高度比 `init` 里的要小,表示屏幕底部有虚拟按键,高度为 1920 - 1794 = 126px 合 42dp。
### android\_id
命令:
```sh
adb shell settings get secure android_id
```
输出示例:
```sh
51b6be48bac8c569
```
### IMEI
在 Android 4.4 及以下版本可通过如下命令获取 IMEI:
```sh
adb shell dumpsys iphonesubinfo
```
输出示例:
```sh
Phone Subscriber Info:
Phone Type = GSM
Device ID = 860955027785041
```
其中的 `Device ID` 就是 IMEI。
而在 Android 5.0 及以上版本里这个命令输出为空,得通过其它方式获取了(需要 root 权限):
```sh
adb shell
su
service call iphonesubinfo 1
```
输出示例:
```sh
Result: Parcel(
0x00000000: 00000000 0000000f 00360038 00390030 '........8.6.0.9.'
0x00000010: 00350035 00320030 00370037 00350038 '5.5.0.2.7.7.8.5.'
0x00000020: 00340030 00000031 '0.4.1... ')
```
把里面的有效内容提取出来就是 IMEI 了,比如这里的是 `860955027785041`。
参考:[adb shell dumpsys iphonesubinfo not working since Android 5.0 Lollipop](http://stackoverflow.com/questions/27002663/adb-shell-dumpsys-iphonesubinfo-not-working-since-android-5-0-lollipop)
### Android 系统版本
命令:
```sh
adb shell getprop ro.build.version.release
```
输出示例:
```sh
5.0.2
```
### IP 地址
每次想知道设备的 IP 地址的时候都得「设置」-「关于手机」-「状态信息」-「IP地址」很烦对不对?通过 adb 可以方便地查看。
命令:
```sh
adb shell ifconfig | grep Mask
```
输出示例:
```sh
inet addr:10.130.245.230 Mask:255.255.255.252
inet addr:127.0.0.1 Mask:255.0.0.0
```
那么 `10.130.245.230` 就是设备 IP 地址。
在有的设备上这个命令没有输出,如果设备连着 WiFi,可以使用如下命令来查看局域网 IP:
```sh
adb shell ifconfig wlan0
```
输出示例:
```sh
wlan0: ip 10.129.160.99 mask 255.255.240.0 flags [up broadcast running multicast]
```
或
```sh
wlan0 Link encap:UNSPEC
inet addr:10.129.168.57 Bcast:10.129.175.255 Mask:255.255.240.0
inet6 addr: fe80::66cc:2eff:fe68:b6b6/64 Scope: Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:496520 errors:0 dropped:0 overruns:0 frame:0
TX packets:68215 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3000
RX bytes:116266821 TX bytes:8311736
```
如果以上命令仍然不能得到期望的信息,那可以试试以下命令(部分系统版本里可用):
```sh
adb shell netcfg
```
输出示例:
```sh
wlan0 UP 10.129.160.99/20 0x00001043 f8:a9:d0:17:42:4d
lo UP 127.0.0.1/8 0x00000049 00:00:00:00:00:00
p2p0 UP 0.0.0.0/0 0x00001003 fa:a9:d0:17:42:4d
sit0 DOWN 0.0.0.0/0 0x00000080 00:00:00:00:00:00
rmnet0 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rmnet1 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rmnet3 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rmnet2 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rmnet4 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rmnet6 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rmnet5 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rmnet7 DOWN 0.0.0.0/0 0x00000000 00:00:00:00:00:00
rev_rmnet3 DOWN 0.0.0.0/0 0x00001002 4e:b7:e4:2e:17:58
rev_rmnet2 DOWN 0.0.0.0/0 0x00001002 4e:f0:c8:bf:7a:cf
rev_rmnet4 DOWN 0.0.0.0/0 0x00001002 a6:c0:3b:6b:c4:1f
rev_rmnet6 DOWN 0.0.0.0/0 0x00001002 66:bb:5d:64:2e:e9
rev_rmnet5 DOWN 0.0.0.0/0 0x00001002 0e:1b:eb:b9:23:a0
rev_rmnet7 DOWN 0.0.0.0/0 0x00001002 7a:d9:f6:81:40:5a
rev_rmnet8 DOWN 0.0.0.0/0 0x00001002 4e:e2:a9:bb:d0:1b
rev_rmnet0 DOWN 0.0.0.0/0 0x00001002 fe:65:d0:ca:82:a9
rev_rmnet1 DOWN 0.0.0.0/0 0x00001002 da:d8:e8:4f:2e:fe
```
可以看到网络连接名称、启用状态、IP 地址和 Mac 地址等信息。
### Mac 地址
命令:
```sh
adb shell cat /sys/class/net/wlan0/address
```
输出示例:
```sh
f8:a9:d0:17:42:4d
```
这查看的是局域网 Mac 地址,移动网络或其它连接的信息可以通过前面的小节「IP 地址」里提到的 `adb shell netcfg` 命令来查看。
### CPU 信息
命令:
```sh
adb shell cat /proc/cpuinfo
```
输出示例:
```sh
Processor : ARMv7 Processor rev 0 (v7l)
processor : 0
BogoMIPS : 38.40
processor : 1
BogoMIPS : 38.40
processor : 2
BogoMIPS : 38.40
processor : 3
BogoMIPS : 38.40
Features : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt
CPU implementer : 0x51
CPU architecture: 7
CPU variant : 0x2
CPU part : 0x06f
CPU revision : 0
Hardware : Qualcomm MSM 8974 HAMMERHEAD (Flattened Device Tree)
Revision : 000b
Serial : 0000000000000000
```
这是 Nexus 5 的 CPU 信息,我们从输出里可以看到使用的硬件是 `Qualcomm MSM 8974`,processor 的编号是 0 到 3,所以它是四核的,采用的架构是 `ARMv7 Processor rev 0 (v71)`。
### 内存信息
命令:
```sh
adb shell cat /proc/meminfo
```
输出示例:
```sh
MemTotal: 1027424 kB
MemFree: 486564 kB
Buffers: 15224 kB
Cached: 72464 kB
SwapCached: 24152 kB
Active: 110572 kB
Inactive: 259060 kB
Active(anon): 79176 kB
Inactive(anon): 207736 kB
Active(file): 31396 kB
Inactive(file): 51324 kB
Unevictable: 3948 kB
Mlocked: 0 kB
HighTotal: 409600 kB
HighFree: 132612 kB
LowTotal: 617824 kB
LowFree: 353952 kB
SwapTotal: 262140 kB
SwapFree: 207572 kB
Dirty: 0 kB
Writeback: 0 kB
AnonPages: 265324 kB
Mapped: 47072 kB
Shmem: 1020 kB
Slab: 57372 kB
SReclaimable: 7692 kB
SUnreclaim: 49680 kB
KernelStack: 4512 kB
PageTables: 5912 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 775852 kB
Committed_AS: 13520632 kB
VmallocTotal: 385024 kB
VmallocUsed: 61004 kB
VmallocChunk: 209668 kB
```
其中,`MemTotal` 就是设备的总内存,`MemFree` 是当前空闲内存。
### 更多硬件与系统属性
设备的更多硬件与系统属性可以通过如下命令查看:
```sh
adb shell cat /system/build.prop
```
这会输出很多信息,包括前面几个小节提到的「型号」和「Android 系统版本」等。
输出里还包括一些其它有用的信息,它们也可通过 `adb shell getprop <属性名>` 命令单独查看,列举一部分属性如下:
| 属性名 | 含义 |
|---------------------------------|-------------------------------|
| ro.build.version.sdk | SDK 版本 |
| ro.build.version.release | Android 系统版本 |
| ro.build.version.security_patch | Android 安全补丁程序级别 |
| ro.product.model | 型号 |
| ro.product.brand | 品牌 |
| ro.product.name | 设备名 |
| ro.product.board | 处理器型号 |
| ro.product.cpu.abilist | CPU 支持的 abi 列表[*节注一*] |
| persist.sys.isUsbOtgEnabled | 是否支持 OTG |
| dalvik.vm.heapsize | 每个应用程序的内存上限 |
| ro.sf.lcd_density | 屏幕密度 |
*节注一:*
一些小厂定制的 ROM 可能修改过 CPU 支持的 abi 列表的属性名,如果用 `ro.product.cpu.abilist` 属性名查找不到,可以这样试试:
```sh
adb shell cat /system/build.prop | grep ro.product.cpu.abi
```
示例输出:
```sh
ro.product.cpu.abi=armeabi-v7a
ro.product.cpu.abi2=armeabi
```