Android进阶:实用ADB命令

  • 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

注意:

  1. 手机和电脑需要连接同一个无线;
  2. 如果遇到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_OUTANDROID_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)

来源:huawei上日志输出的问题

  • 第一步,打开拨号设置,拨号*##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

日志关键词:

  1. 程序无响应,ANR问题:在日志中搜索“ANR”
  2. 崩溃问题:在日志中搜索“CRASH”
  3. 内存泄漏等问题:在日志中搜索“GC”
  4. 其他问题:在日志中搜索”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.sdkSDK 版本
ro.build.version.releaseAndroid 系统版本
ro.build.version.security_patchAndroid 安全补丁程序级别
ro.product.model型号
ro.product.brand品牌
ro.product.name设备名
ro.product.board处理器型号
ro.product.cpu.abilistCPU 支持的 abi 列表[节注一]
persist.sys.isUsbOtgEnabled是否支持 OTG
dalvik.vm.heapsize每个应用程序的内存上限
ro.sf.lcd_density屏幕密度

参考资料

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值