学而实习之 不亦乐乎

Android:adb shell 命令用法详解(三)

2022-01-07 08:15:29

三、实例(接 Android:adb shell 命令用法详解(二))

8.日志打印

Android 系统的日志分为两部分,底层的 Linux 内核日志输出到 /proc/kmsg,Android 的日志输出到 /dev/log。

8.1 Android 日志
查看 Android 设备系统属性的基本命令格式是:
adb logcat [option] [filter-specs]
如果需要停止 logcat 日志打印,可以按 Ctrl + C 停止日志监控。

8.1.1 按级别过滤日志
按级别过滤日志的基本命令格式是:
adb logcat [filter-specs]
Android 的日志分为如下几个优先级(priority):

*:V:过滤只显示 Verbose 及以上级别(优先级最低)
*:D:过滤只显示 Debug 及以上级别
*:I:过滤只显示 Info 及以上级别
*:W:过滤只显示 Warning 及以上级别
*:E:过滤只显示 Error 及以上级别
*:F:过滤只显示 Fatal 及以上级别
*:S:过滤只显示 Silent 及以上级别(优先级最高,什么也不输出)

按某级别过滤日志则会将该级别及以上的日志输出。
比如,命令:adb logcat *:W 会将 Warning、Error、Fatal 和 Silent 日志输出。
(注: 在 macOS 下需要给 *:W 这样以 * 作为 tag 的参数加双引号,如 adb logcat "*:W",不然会报错 no matches found: *:W。)

8.1.2 按 tag 和级别过滤日志
按 tag 和级别过滤日志的基本命令格式是:
adb logcat [tag:level] [tag:level] ...
比如,命令:
adb logcat ActivityManager:I MyApp:D *:S
表示输出 tag ActivityManager 的 Info 以上级别日志,输出 tag MyApp 的 Debug 以上级别日志,及其它 tag 的 Silent 级别日志(即屏蔽其它 tag 日志)。

8.1.3 将日志格式化输出
可以用 adb logcat -v <format> 选项指定日志输出格式。
日志支持按以下几种 <format>:

brief:<priority>/<tag>(<pid>): <message>
process:<priority>(<pid>) <message>
tag:<priority>/<tag>: <message>
raw:<message>
time:<datetime> <priority>/<tag>(<pid>): <message>
threadtime:<datetime> <pid> <tid> <priority> <tag>: <message>
long:[ <datetime> <pid>:<tid> <priority>/<tag> ] <message>

日志格式默认为 brief,指定格式可与上面的过滤同时使用。比如:
adb logcat -v long ActivityManager:I *:S

8.1.4 清空已存在的日志
adb logcat -c

8.1.5 将日志显示在控制台
adb logcat -d

8.1.6 将日志输出到文件
adb logcat -f <file-path>

8.1.7 加载一个可使用的日志缓冲区供查看
adb logcat -b <Buffer>
Android log 输出量巨大,特别是通信系统的log,因此,Android把log输出到不同的缓冲区中,目前定义了四个log缓冲区:

Radio:输出通信系统的 log
System:输出系统组件的 log
Event:输出 event 模块的 log
Main:所有 java 层的 log 以及不属于上面3层的 log

缓冲区主要给系统组件使用,一般的应用不需要关心,应用的log都输出到main缓冲区中。默认log输出(不指定缓冲区的情况下)是输出System和Main缓冲区的log。

8.1.8 打印指定日志缓冲区的大小
adb logcat -g

8.2 内核日志

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] 代表内核开始启动后的时间,单位为秒。
通过内核日志我们可以做一些事情,比如衡量内核启动时间,在系统启动完毕后的内核日志里找到 Freeing init memory 那一行前面的时间就是。

9 查看 Android 设备系统属性

查看 Android 设备系统属性的基本命令格式是:
adb shell getprop [options]

除了可以查看 Android 设备系统属性之外,还可以设置系统属性,设置系统属性的基本命令格式是:
adb shell setprop <key> <value>

9.1 查看设备型号
adb shell getprop ro.product.model
输出示例:
Nexus 5

9.2 查看设备电池状况
adb shell dumpsys battery
输出示例:

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% 的电量。

9.3 查看设备屏幕分辨率
adb shell wm size
输出示例:
Physical size: 1080x1920
该设备屏幕分辨率为 1080px * 1920px。
如果使用命令修改过,那输出可能是:
Physical size: 1080x1920
Override size: 480x1024
表明设备的屏幕分辨率原本是 1080px * 1920px,当前被修改为 480px * 1024px。

9.4 查看设备屏幕密度
adb shell wm density
输出示例:
Physical density: 420
该设备屏幕密度为 420dpi。
如果使用命令修改过,那输出可能是:
Physical density: 480
Override density: 160
表明设备的屏幕密度原来是 480dpi,当前被修改为 160dpi。

9.5 查看设备显示屏参数
adb shell dumpsys window displays
输出示例:
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。

9.6 查看设备 android_id
adb shell settings get secure android_id
输出示例:
51b6be48bac8c569

9.7 查看设备IMEI
在 Android 4.4 及以下版本可通过如下命令获取 IMEI:
adb shell dumpsys iphonesubinfo
输出示例:
Phone Subscriber Info:
  Phone Type = GSM
  Device ID = 860955027785041
其中的 Device ID 就是 IMEI。
而在 Android 5.0 及以上版本里这个命令输出为空,得通过其它方式获取了(需要 root 权限):
adb shell
su
service call iphonesubinfo 1
把里面的有效内容提取出来就是 IMEI 了,比如这里的是 860955027785041。
参考:adb shell dumpsys iphonesubinfo not working since Android 5.0 Lollipop

9.8 查看设备 Android 系统版本
adb shell getprop ro.build.version.release
输出示例:
5.0.2

9.9 查看设备 IP 地址
adb shell ifconfig | grep Mask
在有的设备上这个命令没有输出,如果设备连着 WiFi,可以使用如下命令来查看局域网 IP:
adb shell ifconfig wlan0
如果以上命令仍然不能得到期望的信息,那可以试试以下命令(部分系统版本里可用):
adb shell netcfg

9.10 查看设备 Mac 地址
adb shell cat /sys/class/net/wlan0/address
输出示例:
f8:a9:d0:17:42:4d
这查看的是局域网 Mac 地址,移动网络或其它连接的信息可以通过前面的小节「IP 地址」里提到的 adb shell netcfg 命令来查看。

9.11 查看设备 CPU 信息
adb shell cat /proc/cpuinfo

9.12 查看设备内存信息
adb shell cat /proc/meminfo

9.13 查看设备更多硬件与系统属性
设备的更多硬件与系统属性可以通过如下命令查看:
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 属性名查找不到,可以这样试试:
adb shell cat /system/build.prop | grep ro.product.cpu.abi
示例输出:

ro.product.cpu.abi=armeabi-v7a
ro.product.cpu.abi2=armeabi

10.修改设置

注: 修改设置之后,运行恢复命令有可能显示仍然不太正常,可以运行 adb reboot 重启设备,或手动重启。
修改设置的原理主要是通过 settings 命令修改 /data/data/com.android.providers.settings/databases/settings.db 里存放的设置值。

10.1 修改分辨率
adb shell wm size 480x1024
表示将分辨率修改为 480px * 1024px。
恢复原分辨率命令:
adb shell wm size reset

10.2 修改屏幕密度
adb shell wm density 160
表示将屏幕密度修改为 160dpi。
恢复原屏幕密度命令:
adb shell wm density reset

10.3 修改显示区域
adb shell wm overscan 0,0,0,200
四个数字分别表示距离左、上、右、下边缘的留白像素,以上命令表示将屏幕底部 200px 留白。
恢复原显示区域命令:
adb shell wm overscan reset

10.4 修改关闭 USB 调试模式
adb shell settings put global adb_enabled 0
用命令恢复不了了,毕竟关闭了 USB 调试 adb 就连接不上 Android 设备了。
去设备上手动恢复吧:「设置」-「开发者选项」-「Android 调试」。

10.5 修改允许/禁止访问非 SDK API
允许访问非 SDK API:
adb shell settings put global hidden_api_policy_pre_p_apps 1
adb shell settings put global hidden_api_policy_p_apps 1
禁止访问非 SDK API:
adb shell settings delete global hidden_api_policy_pre_p_apps
adb shell settings delete global hidden_api_policy_p_apps
不需要设备获得 Root 权限。
命令最后的数字的含义:

0:禁止检测非 SDK 接口的调用。该情况下,日志记录功能被禁用,并且令 strict mode API,即 detectNonSdkApiUsage() 无效。不推荐。
1:仅警告——允许访问所有非 SDK 接口,但保留日志中的警告信息,可继续使用 strick mode API。
2:禁止调用深灰名单和黑名单中的接口。
3:禁止调用黑名单中的接口,但允许调用深灰名单中的接口。


10.6 修改状态栏和导航栏的显示隐藏
adb shell settings put global policy_control <key-values>
<key-values> 可由如下几种键及其对应的值组成,格式为 <key1>=<value1>:<key2>=<value2>。

immersive.full:同时隐藏
immersive.status:隐藏状态栏
immersive.navigation:隐藏导航栏
immersive.preconfirms:?

这些键对应的值可则如下值用逗号组合:

apps:所有应用
*:所有界面
package-name:指定应用
-package-name:排除指定应用

例如:
adb shell settings put global policy_control immersive.full=*
表示设置在所有界面下都同时隐藏状态栏和导航栏。
adb shell settings put global policy_control immersive.status=com.package1,com.package2:immersive.navigation=apps,-com.package3
表示设置在包名为 com.package1 和 com.package2 的应用里隐藏状态栏,在除了包名为 com.package3 的所有应用里隐藏导航栏。

11.实用功能

11.1 屏幕截图
截图保存到电脑:
adb exec-out screencap -p > sc.png
如果 adb 版本较老,无法使用 exec-out 命令,这时候建议更新 adb 版本。无法更新的话可以使用以下麻烦点的办法:
先截图保存到设备里:
adb shell screencap -p /sdcard/sc.png
然后将 png 文件导出到电脑:
adb pull /sdcard/sc.png
可以使用 adb shell screencap -h 查看 screencap 命令的帮助信息,下面是两个有意义的参数及含义:

-p:指定保存文件为 png 格式
-d display-id:指定截图的显示屏编号(有多显示屏的情况下)

实测如果指定文件名以 .png 结尾时可以省略 -p 参数;否则需要使用 -p 参数。如果不指定文件名,截图文件的内容将直接输出到 stdout。
另外一种一行命令截图并保存到电脑的方法:
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

11.2 录制屏幕
录制屏幕以 mp4 格式保存到 /sdcard:
adb shell screenrecord /sdcard/filename.mp4
需要停止时按 Ctrl-C,默认录制时间和最长录制时间都是 180 秒。
如果需要导出到电脑:
adb pull /sdcard/filename.mp4
可以使用 adb shell screenrecord --help 查看 screenrecord 命令的帮助信息,下面是常见参数及含义:

--size WIDTHxHEIGHT:视频的尺寸,比如 1280x720,默认是屏幕分辨率。
--bit-rate RATE:视频的比特率,默认是 4Mbps。
--time-limit TIME:录制时长,单位秒。
--verbose:输出更多信息。

11.3 查看连接过的 WiFi 密码,注:需要 root 权限。
    adb shell
    su
    cat /data/misc/wifi/*.conf

11.4 设置系统日期和时间
注:需要 root 权限。
adb shell
su
date -s 20160823.131500
表示将系统日期和时间更改为 2016 年 08 月 23 日 13 点 15 分 00 秒。

11.5 重启手机
adb reboot

11.6 检测设备是否已 root
adb shell
su
此时命令行提示符是 $ 则表示没有 root 权限,是 # 则表示已 root。

11.7 使用 Monkey 进行压力测试
Monkey 可以生成伪随机用户事件来模拟单击、触摸、手势等操作,可以对正在开发中的程序进行随机压力测试。
简单用法:
adb shell monkey -p <packagename> -v 500
表示向 <packagename> 指定的应用程序发送 500 个伪随机事件。
Monkey 的详细用法参考 官方文档。

11.8 开启/关闭 WiFi,注:需要 root 权限。

开启 WiFi:
adb root
adb shell svc wifi enable

关闭 WiFi:
adb root
adb shell svc wifi disable
若执行成功,输出为空;若未取得 root 权限执行此命令,将执行失败,输出 Killed。

12.刷机相关命令

12.1 重启到 Recovery 模式
adb reboot recovery

12.2 从 Recovery 重启到 Android
adb reboot

12.3 重启到 Fastboot 模式
adb reboot bootloader

通过 sideload 更新系统
如果我们下载了 Android 设备对应的系统更新包到电脑上,那么也可以通过 adb 来完成更新。
以 Recovery 模式下更新为例:

  1. 重启到 Recovery 模式:adb reboot recovery
  2. 在设备的 Recovery 界面上操作进入 Apply update-Apply from ADB。注:不同的 Recovery 菜单可能与此有差异,有的是一级菜单就有 Apply update from ADB。
  3. 通过 adb 上传和更新系统:adb sideload <path-to-update.zip>

13.安全相关命令

13.1 启用/禁用 SELinux

启用 SELinux
adb root
adb shell setenforce 1
禁用 SELinux
adb root
adb shell setenforce 0

13.2 启用/禁用 dm_verity

启用 dm_verity
adb root
adb enable-verity
禁用 dm_verity
adb root
adb disable-verity

14.更多 adb shell 命令

Android 系统是基于 Linux 内核的,所以 Linux 里的很多命令在 Android 里也有相同或类似的实现,在 adb shell 里可以调用。本文档前面的部分内容已经用到了 adb shell 命令。

14.1 查看进程状态
adb shell ps
输出信息各列含义:

USER:所属用户
PID:进程 ID
PPID:父进程 ID
NAME:进程名

14.2 查看处理器实时状态
adb shell top [-m max_procs] [-n iterations] [-d delay] [-s sort_column] [-t] [-h]
adb shell top 后面可以跟一些可选参数进行过滤查看不同的列表,可用参数及含义如下:

-m:最多显示多少个进程
-n:刷新多少次后退出
-d:刷新时间间隔(单位秒,默认值5)
-s:按某列排序(可用col值:cpu, vss, rss, thr)
-t:显示线程信息
-h:显示帮助文档

输出信息各列含义:

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:进程名

14.3 查看进程 UID
有两种方案:
(1) adb shell dumpsys package <packagename> | grep userId=
如:adb shell dumpsys package org.mazhuang.guanggoo | grep userId=10394

(2) 通过 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:/ $