- adb的功能还是很多的,本文中只列出了部分常用的,还是推荐大家直接看官方文档
- adb命令入口:system/core/adb/commandline.cpp
全局选项和变量
- 选项:
-a 监听所有网络接口,而非仅本地
-d 使用USB连接的设备 (若有多个则会报错)
-e 使用TCP/IP设备 (若有读个则会报错)
-s SERIAL 使用指定序列号的设备 (覆盖$ANDROID_SERIAL)
-t ID 使用指定transport id的设备
-H 指定adb server的host [默认localhost]
-P 指定adb server的端口 [默认5037]
-L SOCKET 指定adb server的监听socket[默认tcp:localhost:5037]
- 变量
$ADB_TRACE comma-separated list of debug info to log: all,adb,sockets,packets,rwx,usb,sync,sysdeps,transport,jdwp
$ADB_VENDOR_KEYS colon-separated list of keys (files or directories)
$ANDROID_SERIAL serial number to connect to (see -s)
$ANDROID_LOG_TAGS tags to be used by logcat (see logcat --help)
设备与网络
服务管理
start-server 确保至少有一个server在运行
kill-server 关闭运行中的server
reconnect kick connection from host side to force reconnect
reconnect device kick connection from device side to force reconnect
reconnect offline reset offline/unauthorized devices to force reconnect
设备管理
devices devices [-l] 列出已连接的设备 (-l 输出详细信息)
无线调试
安卓11及以后
手机连接同一个WiFi,数据线连接电脑->开发者选项->无线调试开启->点击使用配对码配对设备->查看弹窗中的IP、port和配对码->运行下面adb命令进行配对:
adb pair ip:port
>Enter pairing code: 输入配对码
>Successfully paired to 192.168.1.130:37099 [guid=adb-235XY]
配对完成后运行下面命令进行连接:
adb connect ip:port
安卓10及之前
手机连接同一个WiFi,数据线连接电脑 -> 开发者选项 -> USB调试开启 -> 输入下面命令设置目标设备以监听端口 5555 上的TCP/IP连接:
adb connect device_ip
然后通过下面的命令查看已无线连接的设备:
adb devices
> device_ip_address:5555 device
注意:
- 手机和电脑需要连接同一个无线;
- 如果遇到adb端口冲突,可以通过下面的方式来找到对应端口的进程并杀掉:
对windows:for /f "tokens=5" %a in ('netstat -ano^|find "5555"') do (taskkill /f /pid %a&adb devices&set /p=&exit)
网络连接
connect HOST[:PORT] 通过TCP/IP协议连接指定设备 [默认端口5555]
disconnect [HOST[:PORT]] 断开指定TCP/IP的设备或所有设备 [默认端口5555],
forward --list 列出设备所有正向套接字连接
forward [--no-rebind] LOCAL REMOTE
通过下述几种方式发起正向连接:
tcp:<port> (<local> may be "tcp:0" to pick any open port)
localabstract:<unix domain socket name>
localreserved:<unix domain socket name>
localfilesystem:<unix domain socket name>
dev:<character device name>
jdwp:<process pid> (remote only)
forward --remove LOCAL 移除指定正向套接字连接
forward --remove-all 移除所有正向套接字连接
ppp TTY [PARAMETER...] 通过USB运行PPP命令
reverse --list 列出设备所有逆向套接字连接
reverse [--no-rebind] REMOTE LOCAL
通过下述几种方式发起逆向连接:
tcp:<port> (<remote> may be "tcp:0" to pick any open port)
localabstract:<unix domain socket name>
localreserved:<unix domain socket name>
localfilesystem:<unix domain socket name>
reverse --remove REMOTE 移除指定逆向套接字连接
reverse --remove-all 移除所有逆向套接字连接
其他
wait-for[-TRANSPORT]-STATE
wait for device to be in the given state
State: device, recovery, sideload, or bootloader
Transport: usb, local, or any [default=any]
get-state 打印设备[ offline | bootloader | device]信息
get-serialno 打印设备<serial-number>
get-devpath print <device-path>
remount 重新装载 /system, /vendor, and /oem partitions read-write
reboot [bootloader|recovery|sideload|sideload-auto-reboot] 重启设备;默认启动系统镜像,但也支持bootloader和recovery. sideload reboots
into recovery and automatically starts sideload mode,
sideload-auto-reboot is the same but reboots after sideloading.
sideload OTAPACKAGE sideload the given full OTA package
root restart adbd with root permissions
unroot restart adbd without root permissions
usb restart adb server listening on USB
tcpip PORT restart adb server listening on TCP on PORT
文件传输
push [--sync] LOCAL... REMOTE 从本机推送文件/目录到设备指定目录
--sync: 仅推送比设备更新的文件(同名时)
pull [-a] REMOTE... LOCAL 从设备拉取文件/目录到本机指定目录
-a: 保留原文件日期和读写模式
sync [system|vendor|oem|data|all] 将本地构建产物从$ANDROID_PRODUCT_OUT同步到设备中 (默认全部文件)
-l: 仅列出不拷贝
根据资料
ANDROID_PRODUCT_OUT
和ANDROID_PRODUCT_OUT_BIN
是rom相关的变量,做framework相关可能用到
安全相关
disable-verity disable dm-verity checking on userdebug builds
enable-verity re-enable dm-verity checking on userdebug builds
keygen FILE
generate adb public/private key; private key stored in FILE,
public key stored in FILE.pub (existing files overwritten)
应用管理
安装和卸载
install [-lrtsdg] PACKAGE
install-multiple [-lrtsdpg] PACKAGE... 推送安装包到设备并安装
-l: forward lock application
-r: 替换已安装的应用,即先卸载已有的再安装
-t: allow test packages
-s: 指定安装位置为SD卡
-d: 允许版本号降级 (仅支持debug包)
-p: 部分安装 (仅批量安装)
-g: 授予所有运行时权限
uninstall [-k] PACKAGE 卸载指定APP
'-k': 保留data和cache文件目录
注意:命令中出现package指的是包名,但这里是指apk文件路径
数据备份及恢复
backup 数据备份
restore 数据恢复
扩展:Android属性allowBackup安全风险:此配置设置为true将允许攻击者获取应用数据,如联系人、密码等隐私数据,对用户数据安全造成隐患。-来源
应用调试
bugreport [PATH] 指定bugreport路径或具体文件 [默认bugreport.zip],设备如果不支持zip格式的bugreport则会直接把报告输出到stdout.
jdwp list pids of processes hosting a JDWP transport
logcat show device log (logcat --help for more)
Logcat
logcat日志文件位于:data/misc/logd
浏览日志文件:adb shell ls -al data/misc/logd
控制台打印
指定pid:
logcat --pid <pid>
# 可以通过下面的方法获取指定包名的pid:
if [$verionInt -ge 8]; then
# android8.0及以上系统获取正在运行的进程pid需要加上-A
pid="$(adb shell ps -A | grep $packageName | awk '{print $2}')"
else
pid="$(adb shell ps | grep $packageName | awk '{print $2}')"
fi
指定输出格式:
-v
设置日志输入格式,默认的是brief 格式- brief — Display priority/tag and PID of originating process (the default format).显示prority/tag,产生日志的进程的id,和日志消息本身。它是日志默认的输出格式。
- process — Display PID only.显示priority,产生日志的进程的id,和日志消息本身
- tag — Display the priority/tag only.显示prority/tag,和消息本身
- thread — Display process:thread and priority/tag only.显示priority,线程和日志消息本身
- raw — Display the raw log message, with no other metadata fields.只显示消息本身
- time — Display the date, invocation time, priority/tag, and PID of the originating process.显示产生日志的时间,prority/tag,产生日志的进程Id,和日志消息本身。
- long — Display all metadata fields and separate messages with a blank lines.显示产生日志的时间,prority/tag,产生日志的进程Id,和日志消息本身。但是日志消息本身另其一行进行显示。每个日志之间空一行。
# 输出带颜色的logcat日志
adb logcat *:D -v color brief
# 输出带时间戳的logcat日志
adb logcat -v time
过滤输出内容:
-c
清空指定的日志缓冲区。应该就是清除其对应的日志文件-b
: 指定要查看的日志缓冲区,可以是 system , events , radio,main,all . 默认值是 system和main。-g
输出指定的日志缓冲区,输出后退出.-s
设置默认的过滤级别为silent.- V — Verbose (lowest priority) 对应于Log.i()系列函数
- D — Debug 对应于Log.d()系列函数
- I — Info 对应于Log.i()系列函数
- W — Warning 对应于Log.w()系列函数
- E — Error 对应于Log.e()系列函数
- F — Fatal 对应于Log.wtf()系列函数
- S — Silent (highest priority, on which nothing s ever printed)
# 查看指定tag
adb logcat ActivityManager:I *:s
# 仅输出tag为robin,level为info的日志,其他日志不输出,等同于adb logcat robin:i *:S
adb logcat -s robin:i
# 指定输出多个缓冲区的日志
adb logcat -b system -b main -b events -b radio -s robin:i
指定输出到文件:
-d
输出日志到屏幕上.-f
指定输出日志到 ,注意这是Android设备上的文件,默认是stdout .-n
设置日志的最大数目 .,默认值是4,需要和 -r 选项一起使用。-r
每 时输出日志,默认值为16,需要和-f 选项一起使用.
# PC端输出logcat日志并保存到指定文件
adb logcat *:D > logcat.txt
# 手机端输出logcat日志并保存到指定文件
adb logcat *:D -f logdirlogcat.txt
多个设备时,可以使用
-s serial_number
来指定设备
Log.isLoggable(TAG, Log.VERBOSE)
- 第一步,打开拨号设置,拨号*##2846579##*,进入后台设置–LOG设置–勾选AP日志,使得所有日志可以输出
- 第二步,使用setprop修改isLoggable的级别:
setprop log.tag.<YOUR_LOG_TAG> <LEVEL>
// 比如我们的场景则是:
setprop log.tag.MainActivity VERBOSE
终端命令
可以通过adb shell
直接进入终端,执行相关命令,然后exit
退出终端。也可以直接adb shell command
在外部执行终端命令。
shell [-e ESCAPE] [-n] [-Tt] [-x] [COMMAND...] 执行远程shell命令 (没有cmd则会进入shell模式,exit退出)
-e: 选择转义字符(escape character)或 "none",默认 '~'
-n: don't read from stdin
-T: disable PTY allocation
-t: force PTY allocation
-x: disable remote exit codes and stdout/stderr separation
emu COMMAND 执行模拟器控制台命令
注意:终端命令中有关文件路径是指设备的文件路径,这一点需要铭记。
dumpsys
查看当前页面类名
在IDE中可以通过layout inspector来查看当前的activity的具体类名,除此之外还可以使用adb命令:
# Windows环境
adb shell dumpsys activity | findstr mResumedActivity
# 类Linux环境
adb shell dumpsys activity | grep mResumedActivity
查看当前打开的APP包名
# 获取当前打开的APP包名(前面的为包名,斜杠后面的是当前启动的acivity)
adb shell dumpsys window | findstr mCurrentFocus
am
am
命令不仅管理activity,还可以管理应用进程、service、广播等。
Process相关操作
# 强行停止与 package(应用的软件包名称)关联的所有进程
adb shell am force-stop com.example.app
# 终止与 package(应用的软件包名称)关联的所有进程。此命令仅终止可安全终止且不会影响用户体验的进程。
adb shell am kill com.example.app
# 终止所有后台进程
adb shell am kill-all
Activity相关操作
# 启动activity
adb shell am start -n com.example.app/.ExampleActivity
# 在指定屏幕上启动activity
# - 屏幕displayid:多屏安卓设备的屏幕编号,从0开始
am start -n com.example.app/.ExampleActivity --display <屏幕displayid>
Service相关操作
adb shell am startservice -n com.example.app/.ExampleService
Broadcast相关操作
# 发出指定action的广播
adb shell am broadcast -a com.example.app.MY_CUSTOM_ACTION
# 发出指定action且带extra参数的广播,其中-e可以指定多个
adb shell am broadcast -a com.example.app.MY_CUSTOM_ACTION -e "extraKey1" "extraValue1"
屏幕相关操作
# 关闭应用的屏幕兼容性
adb shell am screen-compat off com.example.app
# 替换设备显示密度。此命令支持使用低密度屏幕在高密度屏幕环境上进行测试(反之亦然),对于在不同密度的屏幕上测试应用非常有用。
adb shell am display-density 480
# 替换设备显示尺寸。此命令支持使用大屏设备模仿小屏幕分辨率(反之亦然),对于在不同尺寸的屏幕上测试应用非常有用。
adb shell am display-size 1280x800
# 恢复设备显示尺寸
adb shell am display-size reset
性能分析相关操作
# 启动process的性能剖析器,将结果写入file
adb shell am profile start process ./profile.log
# 停止 process 的性能剖析器
adb shell am profile stop process
# 转储 process 的堆,写入 file
adb shell am dumpheap -n process ./heap.txt
pm
主要包括包查询、安装、卸载,以及包相关的权限(查询、授予、禁用)、应用缓存、等。
查找手机上的安装包包名
# 查看手机上所有的安装包
adb shell pm list package
# 查看第三方安装包
adb shell pm list package -3
# 查看系统的包
adb shell pm list packages -s
# 关键词搜索包名
adb shell pm list packages -e “要搜索的内容”
安装和卸载
# 安装apk
adb shell pm install -d ./test.apk
# 卸载应用
adb shell pm uninstall com.example.app
清除应用缓存
adb shell pm clear com.example.app
查看apk路径
adb shell pm path com.example.app
monkey
参数说明
adb shell monkey -p 包名 --throttle 100 --ignore-crashes --ignore-timeouts --ignore-security-exceptions --ignore-native-crashes --monitor-native-crashes -v -v -v –s 1540475754297 100
-
-p
:指定包名,若不指定则在整个系统中执行,可以指定多个-p
指定多个包名,包名不需要引号; -
-v
:指定日志级别,默认-v
。
--v
仅提供启动、测试完成和最终结果等少量信息
--v -v
提供较为详细的日志,包括每个发送到Activity的事件信息
--v -v -v
提供最详细的日志,包括了测试中选中/未选中的Activity信息 -
-s
:指定伪随机数生成器的seed值,若seed值相同则两次Monkey测试所产生的事件序列也相同,如上面seed指定为1540475754297,可以在执行monkey指定seed复现问题 -
--throttle
:指定用户事件的操作间隔时延,单位是毫秒。如果不指定这个参数,monkey会尽可能快的生成和发送消息。 -
--ignore-timeouts
:忽略超时错误 -
--ignore-crashes
:忽略crash -
--ignore-security-exceptions
:忽略许可错误 -
--monitor-native-crashes
:用于指定是否监视并报告应用程序发生崩溃的本地代码 -
--pct-touch
:触摸事件百分比,[0,100]内的整数
事件 | 说明 |
---|---|
pct-touch | 触摸事件,是一个down-up事件,它发生在屏幕上的某单一位置 |
pct-motion | 动作事件,由屏幕上某处的一个down事件、一系列的伪随机事件和一个up事件组成 |
pct-trackball | 轨迹事件,由一个或几个随机的移动组成,有时还伴随有点击 |
pct-nav | 导航事件,由来自方向输入设备的up/down/left/right组成 |
pct-majornav | 主要导航事件,通常引发图形界面中的动作,如:5-way键盘的中间按键、回退按键、菜单按键 |
pct-syskeys | 按键事件,通常被保留由系统使用,如Home、Back、Start Call、End Call及音量控制键 |
pct-appswitch | 页面切换,在随机间隔里Monkey将执行一个startActivity()调用,作为最大程度覆盖包中全部Activity的一种方法 |
pct-anyevent | 所有其它类型的事件,如:按键、其它不常用的设备按钮等等 |
日志分析
保存monkey日志:
adb shell monkey -p 包名 100 > adb-monkey.log
日志主要包含以下内容:
bash arg: -p # 打印monkey命令执行参数
bash arg: me.hao.monkeytest
bash arg: -v
bash arg: -v
bash arg: -v
bash arg: 100
:Monkey: seed=1639644250125 count=100
:AllowPackage: me.hao.monkeytest # 通过-p指定的包名
:IncludeCategory: android.intent.category.LAUNCHER
:IncludeCategory: android.intent.category.MONKEY
// Selecting main activities from category android.intent.category.LAUNCHER
// - NOT USING main activity com.android.browser.launch.SplashActivity (from package com.android.browser)
...
// Seeded: 1639644250125 # 没有设置seed,monkey默认生成了一个
// Event percentages: # monkey事件分布百分比
// 0: 15.0%
// 1: 10.0%
// 2: 2.0%
// 3: 15.0%
// 4: -0.0%
// 5: -0.0%
// 6: 25.0%
// 7: 15.0%
// 8: 2.0%
// 9: 2.0%
// 10: 1.0%
// 11: 13.0%
# 这里是执行monkey的页面
:Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=me.hao.monkeytest/me.hao.monkeytest.MainActivity;end
// Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=me.hao.monkeytest/me.hao.monkeytest.MainActivity } in package me.hao.monkeytest
// Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=me.hao.monkeytest/me.hao.monkeytest.MainActivity } in package me.hao.monkeytest
Sleeping for 0 milliseconds # 事件执行时间间隔,通过--throttle制定,默认为0
:Sending Key (ACTION_DOWN): 21 // KEYCODE_DPAD_LEFT #具体的事件
...
Events injected: 100 # 事件执行次数
:Sending rotation degree=0, persist=false
:Dropped: keys=0 pointers=20 trackballs=0 flips=0 rotations=0
## Network stats: elapsed time=557ms (0ms mobile, 0ms wifi, 557ms not connected)
// Monkey finished
日志关键词:
- 程序无响应,ANR问题:在日志中搜索“ANR”
- 崩溃问题:在日志中搜索“CRASH”
- 内存泄漏等问题:在日志中搜索“GC”
- 其他问题:在日志中搜索”Exception”
screencap
# 屏幕截图,注意保存路径是指设备上的路径
adb shell screencap /sdcard/screen.png
# 复制图片到命令行当前路径
adb pull /sdcard/screen.png
screenrecord
# 屏幕录制,注意保存路径是指设备上的路径
adb shell screenrecord /sdcard/demo.mp4
# 复制视频到命令行当前路径
adb pull /sdcard/demo.png
settings
#disable auto-rotate
# 0-关闭自动旋转
# 1-打开自动旋转
adb shell settings put system accelerometer_rotation 0
#3:270° clockwise,0,1,2
# 1-旋转到90
# 2-旋转到180
# 3-旋转到270
adb shell settings put system user_rotation 3
getprop/setprop/watchprops
所有这些属性都保存文件中:
/system/build.prop
init.rc
default.prop
这些配置中以ro开头的是只读属性。需要root权限才能cat此文件。
读取配置:
getprop ro.build.model
很多时候我们希望在Java代码中读取一些系统配置或自定义配置来执行相应的逻辑,使用Java读取配置的方法为:
private String getXXXYYY() {
String type = null;
try {
Process process = Runtime.getRuntime().exec("getprop ro.xxx.yyy");
if (process != null) {
InputStreamReader ir = new InputStreamReader(process.getInputStream());
if (ir != null) {
BufferedReader input = new BufferedReader(ir);
if (input != null) {
type = input.readLine();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
Slog.d(TAG, "getXXXYYY" + type);
return input.readLine();
}
写配置:setprop
# 设备改机
setprop ro.build.model XM
# 自定义配置,自定义配置非debug前缀会报错
setprop debug.xxx abc
监听配置:
watchprops命令用来监听系统属性的变化,如果期间系统的属性发生变化则把变化的值显示出来。
$ adb shell watchprops
1491476973 dalvik.vm.heapgrowthlimit = '512m'
1491476323 init.svc.debuggerd = 'running'
...
appops
# 允许指定APP使用VPN功能
appops set <package_name> ACTIVATE_VPN allow
读取应用的 ART 配置文件
从 Android 7.0(API 级别 24)开始,Android Runtime (ART) 会收集已安装应用的执行配置文件,这些配置文件用于优化应用性能。您可能需要检查收集的配置文件,以了解在应用启动期间,系统频繁执行了哪些方法和使用了哪些类。
要生成文本格式的配置文件信息,请使用以下命令:
adb shell cmd package dump-profiles com.example.app
要检索生成的文件,请使用:
adb pull /data/misc/profman/com.example.app.txt
实际我在使用过程中,在执行adb pull时,出现如下错误:
adb: error: failed to stat remote object ‘/data/misc/profman/com.example.app.txt’: No such file or directory
更多硬件与系统属性
设备的更多硬件与系统属性可以通过如下命令查看:
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 | 屏幕密度 |