【Android端 adb相关】adb相关总结
一、什么是adb?
adb的全称是:Android Debug Bridge,adb命令的构成是三部分,分别是:服务器、客户端、后台程序:
(1)客户端:一个在PC上运行的客户端。可以通过shell端使用adb命令启动客户端。 其他Android工具比如说ADT插件和DDMS同样可以产生adb客户端.
(2)服务器:一个在PC上作为后台进程运行的服务器。该服务器负责管理客户端与运行于模拟器或设备上的adb守护程序(daemon)之间的通信。.
(3)后台程序(daemon):一个以后台进程的形式运行于模拟器或设备上的守护程序(daemon)。.
具体的工作流程是:
(1)通过cmd脚本运行adb命令的时候,首先会检查是否有adb服务器,服务器会绑定一个TCP端口 5037
(2)服务器端会监听客户端发送的命令,所有客户端均使用5037端口与服务器进行通信
(3)服务器设置与所有运行的模拟器/设备实例的连接。它通过扫描 5555 到 5585 之间(模拟器/设备使用的范围)的奇数号端口查找模拟器/设备实例。
(4)服务器一旦发现 adb 后台程序,它将设置与该端口的连接
(5)每个模拟器/设备实例将获取一对按顺序排列的端口 — 用于控制台连接的偶数号端口和用于 adb 连接的奇数号端口。例如:
模拟器 1,控制台:5554
模拟器 1,adb:5555
模拟器 2,控制台:5556
模拟器 2,adb:5557
以此类推...
如上所示,在端口 5555 与 adb 连接的模拟器实例与侦听端口 5554 的控制台的实例相同。
(6)所以一台PC上如果启动了一个adb服务器,能够连接的移动端设备数是16个
adb的程序位置在:sdk/platform-tools/目录下
二、adb命令的具体的应用
可以分为多个方面:
(一)与设备相关/adb服务相关
1、adb devices,列出所有设备数,例如:
58b6aa5f代表的是设备id,即device_id,如果同时存在设备和模拟器的话,会看到如下图所示内容:
如果设备能够连接成功,右侧状态显示为device,如果没有连接成功,则显示offline,如果始终没有出现设备,则可能需要尝试关闭并重新打开usb调试或者重新进行usb连接线与设备和PC端的连接,再尝试执行命令。
连接多台设备的时候,可以通过增加-s deviceid参数来达到向某条设备发送命令的目的,
例如:adb -s 58b6aa5f install apk包在PC端的路径
2、adb start-server
一般会把这个命令和kill-server一起用,即kill-server之后,重新start-server,这里启动的是:adb的服务器端。
如果想要start-server,只要执行任何一条非kill-server的adb命令就可以,比如:adb devices就可以。
执行adb命令的时候,会首先判断服务器是否已经启动,如果没有启动,则会启动adb服务器。
服务器端的端口可能有时会出现被占用的情况,比如360手机助手、91助手等,一连接手机之后,就把5037的端口号占用了,这种情况下要如何处理?
此种情况下需要通过判断当前有哪些进程占用了5037的端口,然后把这些进程杀死,之后再start-server,之后执行adb devices查看设备是否能够正常展示出来
3、adb kill-server
有时连接设备很久执行adb devices也不出现设备列表,此时可能会通过插拔设备,也可以通过kill-server之后重启服务来尝试。
(二)与文件操作/APK包相关
1、将文件从电脑端推到手机端(用local代表PC端,remote代表设备端)
具体命令是:adb push local remote
例如将一个APK包从PC端的某个位置push到手机端的sdcard下:
之后可以直接通过adb shell查看/sdcard目录下的文件,看到确实存在上面push进去的文件:
2、将文件从手机端拖到电脑端
具体命令是:adb pull remote local
例如将生成的日志文件从手机端拖到电脑端的E盘目录下:
上面一条命令是直接将sdcard/xxx.apk文件直接pull到E盘下面,这里的2017-0111被认为是文件,并且没有后缀名
下面一条命令是:直接将sdcard/xxx.apk文件直接pull到E盘的2017-0111这个目录下,但是因为E盘下没有2017-0111这个文件夹,所以提示错误,如果存在这个文件夹的话,则执行结果如下:
可以看到,确实将apk文件全部pull到E盘的123目录下:
3、安装包(包括pm相关的操作)
不通过shell pm调用的,直接通过install来调用的命令:adb install 安装包在PC端的具体位置,例如:
执行install会首先将APK包拷贝到某个位置,这里就是/data/local/tmp的目录下,之后之后进行安装,手机rom不同,安装到手机之后,部分机型可以直接安装,部分机型会提示用户安装(需要手动点击安装才可安装成功)
安装的结果包括如下几种:
Success
Failure,其中原因包含:(1)INSTALL_CANCELED_BY_USER(2)Failure [INSTALL_FAILED_ALREADY_EXISTS] (3)Failure [INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES]
pm,其实就是package manager的缩写,所以pm相关的不仅可以安装包,还可以获取很多跟安装包相关的内容。
可以通过pm进行安装包相关的获取,例如:
(1)获取手机内的所有安装包:adb shell pm list packages
(2)获取安装包当前在移动设备内的路径:adb shell pm path 包名,例如:
可以将待安装的安装包通过adb push到某个目录下,然后将这个目录+apk包名 记录下来,之后使用这个路径作为pm的APK的path:adb shell pm install apk_path
例如在1中将一个APK文件push到了sdcard目录下,然后再通过shell pm进行安装:
4、卸载包
具体命令是:adb uninstall package-name
例如:adb uninstall com.ganji.android
其中,com.ganji.android是赶集网APP的包名,这个包名的获取可以通过aapt 命令获取,在(六)中会进行介绍
也可以通过adb shell pm uninstall 包名来卸载:
(三)与Activity、Service、广播等相关:
1、获取当前Activity的栈信息(获取最顶端的Activity)
具体命令是:adb shell dumpsys activity top | findstr ACTIVITY
获取当前界面的UI信息:adb shell dumpsys activity top
可以通过adb shell dumpsys activity -h 获取帮助
2、打开某个Activity、Service、广播
具体命令是:adb shell am start xxx
其中am其实就是ActivtiyManager的缩写,关于ActivityManager相关的内容会在之后进行详细总结。
命令是:adb shell am start ACTIVITY的路径,这个可以通过adb shell dumpsys activity top | findstr ACTIVITY来获取
直接结束与包名相关的所有进程:adb shell am forcr-stop 包名
针对shell am的命令的使用可以通过-h获取帮助信息:
(四)与进程相关
1、获取当前进程:adb shell ps | findstr 包名
以上具体各列的含义:
分别是:
USER——uid,比如com.ganji.android的uid是u0_a164
PID——进程id
PPID——父进程id
VSIZE——进程虚拟地址空间大小
RSS——进程正在使用的物理内存大小
WCHAR——内核地址
PC——当前程序指针
NAME——进程名
2、杀死当前进程(可以通过apk包名杀死进程)
通过adb shell am force-stop 包名,可以直接强制杀死整个应用的所有进程
通过pid杀死某个进程:adb shell kill -9 pid
会得到下面的这个错误:
然而可能因为root权限的问题,导致提示不允许,所以一般情况下强杀进程都直接用am force-stop来操作。
通过adb shell kill -l可以列出-s的参数列表:
(五)与性能相关内容
1、获取内存信息
命令为:adb shell dumpsys meminfo <包名|pid> [-d]
其中[-d]代表可选参数,代表Dalvik and ART memory 使用的更多info
具体的使用如下:
这条命令运行之后,列出的就是在运行命令当时的APP的内存分配情况,单位是:KB
其中我们需要关注的内容是:
Private Clean 和 Private Dirty:代表的是当前APP的该进程自己独占的内存,如果当前进程结束,则这个内存大部分是能够被释放的。
Pss:这个就是这个APP当前进程各个部分的真实内存,包含进程内独享的内存+与其他进程按比例包含的共享库的内存。
一般情况下,关注的数据是:Pss Total和Private Dirty这两列,可能也需要关注Private Clean和Heap Alloc这两列。
备注:其中内存类型: 干净内存和脏内存
干净内存: 从磁盘上拷贝到内存中的空间, 比如, 代码, framework,内存映射文件.
脏内存: 其他的内存空间. 比如 在堆上的初始化数据, 数据库缓存,解压的图片数据等.
大部分应用初始化的数据都是脏内存
也就是说:干净内存被清理之后,可以直接从磁盘上读取就可以得到;脏内存被清理之后需要重新跑app才能够得到
后面会专门就内存这块的做更详细的分析。
Zygote:
在Android里,Zygote是个进程,该进程中包含了所有的框架类,共用的资源,以及预加载的本地库
可以通过adb shell getprop | findstr heapgrowthlimit来获取单个程序限制的最大内存
2、获取cpu信息
user和kernel模式的cpu分别对应的是什么?Android developer给出的内容见下:
In user mode, the code must use system APIs to access hardware or memory, has access to virtual memory addresses only, and crashes are usually recoverable. In kernel mode, the code can directly access hardware, including physical memory addresses; crashes halt the device
命令是:adb shell dumpsys cpuinfo ,具体运行及结果见下图:
以上命令会列出所有进程的cpuinfo
命令执行结果的最底端会给出总值Total:
针对单项的内容,如:
这个数据代表:
CPU占用率为0.7%,在user模式和kernel模式下分别是0.3%
如果想要筛选出某个APK包的cpuinfo,在windows下需要如此执行:
也可以通过:adb shell top -n 1 | findstr 包名
dumpsys cpuinfo 里面是描述Cpu的使用详情 且里面的cpu占比是指Cpu所花的时间比比如用户活动消耗时间占比和内耗消耗时间占比,top是实际单进程的Cpu占用。
需要特别关注的是:dumpsys cpuinfo得到的值可能大于100%,如果是多核的情况下。
3、获取流畅度相关
可以通过adb shell dumpsys gfxinfo 包名来获取渲染最近128帧的耗时:
需要在开发者选项中勾选——GPU呈现模式分析——在adb shell dumpsys gfxinfo中
运行之后,在profile中可以看到:
将Draw+Prepare+Process+Execute的总时长加起来,是渲染一帧的总时长:保证这个总时长是小于16ms的,就可以保证流畅度过关。
4、获取电量相关(最好是在5.0及以上的安卓机器上执行,高版本的提供的信息更全一些)
具体命令是:adb shell dumpsys batterystats > PC端某个具体位置(具体到文件)
然后打开文件之后,能够看到:
从最顶端的这个文件搜索你想要找的app的包名,比如:com.ganji.android,然后可以看到该APP对应的uid为:
然后可以继续往下搜索这个uid,下面所有的信息统计都是按照uid来的:
例如estimated power use (mAh):
继续搜索就可以看到更详细的一些内容,包含所有可能耗电的部件的详情信息:
或者也可以通过:adb shell dumpsys bugreport ,这个在后面专门做电量分析的时候会专门做相关介绍。
5、获取流量相关:
如果不root的话,就需要通过进程获取,那么首先需要启动程序,然后才能通过ps获取到pid,取最前面的一列就是uid:
例如以上命令,启动程序之后,自然就能够获取到程序,然后通过adb shell ps | findstr com.ganji.android就能获取到最前面的值为uid;
需要获取流量的话:
可以通过上面的方式获得:
adb shell cat /proc/net/xt_qtaguid/stats | findstr uid
一般来说:第6列和第8列代表接收数据和传输数据,如果有多行的,需要进行加和操作。——(这里的说第6列其实是从1开始算的)
从代码角度来考虑的话,index从0开始,其实就是5和7列,分别代表的是接收数据 和 传输数据。
其中,可以通过下方的命令,拿到所有uid的网络信息:
adb shell cat proc/net/xt_qtaguid/stats > netstats.txt
来自 <http://stackoverflow.com/questions/15163549/interpreting-android-xt-qtaguid-stats>
然后看到txt文件中的内容如下:
可以看到第4列是uid的显示,比如说上面直接findstr拿到的值中,第4行的值就是10251,表示的是apk的uid值;
其中cnt_set=0时表示:cnt_set=1时表示内容如下:
acct_tag_hex is a socket tag
Lines with cnt_set==0 are for background data
Lines with cnt_set==1 are for foreground data
Total traffic is a sum of both
来自 <http://stackoverflow.com/questions/15163549/interpreting-android-xt-qtaguid-stats>
其中第5列rx_bytes就是接收的数据,第7列tx_bytes就是传输的数据。
根据生成的netstats.txt的文档,看到的title内容如下:
idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
可以看到赶集网的APP在整个过程中是没有请求udp数据的,都是走的tcp的,但如果有采用非tcp的请求的话,最好还是按照这种方式计算值。
可以通过以下方式获取到app的uid:
然后打开txt文件,搜索:userid=
截图如下:
就能得到userId=10251的内容,这个值就是本次安装包的userid。
或者直接通过下面一行语句就能拿到userid:
(六)不是adb命令,但是是调用sdk相关的工具:
1、对package进行具体信息获取(包括包名、icon、min-sdk、权限、LaunchActivity等)
aapt dump badging 安装包在PC端的具体位置
具体运行如下:
当然也可以将内容重定向输出到文件中,例如:
得到的内容与在控制台输出的内容一致。
可以通过脚本对输出结果进行处理,可以对内容进行逐行读取,根据key值获取到value值,进而将需要的内容以key-value的形式存储成dict,之后对该数据结构按照自己所想进行所用即可。
2、安装包的解压缩:unzip
unzip.exe可以通过官网直接下载,地址:http://stahlworks.com/dev/index.php?tool=zipunzip
其中在windows下unzip.exe可以直接对Android的APK包进行解压,并且对中英文的支持及不同路径的处理都无问题(之前因为对APK通过python进行解压,中文的文件名显示会出现问题)
具体的用法及参数含义:
例如,需要将一个APK包直接进行解压,可以通过下面命令行:unzip APK包路径 -d DestDir
例如,需要从一个APK包中提取某些文件出来,可以通过下面命令行:unzip -j APK包路径 File路径 -d DestDir
具体运行时,例如想要把证书文件.RSA解压到E盘目录下:
可以看见,如果不增加参数-j,就会默认将文件META-INF文件夹整体拷贝过去,得到的目录是:e:/123/META=INF/GANJI.RSA
如果增加参数-j,就会不创建目录,即只会将GANJI.RSA文件解压出来,得到的目录是:e:/123/GANJI.RSA
3、获取安装包的证书相关
在Android-developer中介绍了apksigner,但是这个需要在Android的24.0.3之后才有,具体目录是:sdk/build-tools/24.0.3,这个目录下面才会有。
也可以通过:
(1)unzip.exe -j apk /META-INF/*.RSA -d 自定义的文件夹,就能得到证书
(2)得到证书文件之后,通过keytool -printcert -file .RSA文件的路径(其中keytool只要配置了java的环境变量就可以使用,参考资料可见:http://www.micmiu.com/lang/java/keytool-start-guide/)
需要跟APP正确的md5值进行比较,sha1也可以输出,比较之后,如果一致,认为OK
参考资料:
1、带你了解 Android Debug Bridge (adb)
http://www.jianshu.com/p/ab8a026a5355
2、How to get zip and unzip on the windows command line
http://stahlworks.com/dev/index.php?tool=zipunzip
3、
常见Android安装启动失败问题,android安装失败
来自 <http://www.android100.org/html/201508/30/177571.html>
http://www.android100.org/html/201508/30/177571.html
4、Investigate your RAM Usage
https://developer.android.com/studio/profile/investigate-ram.html#ViewingAllocations
5、Android内存分析工具:adb命令
http://blog.csdn.net/berber78/article/details/47819139
6、Android 性能测试实践(三)Cpu
https://testerhome.com/topics/2583
7、[Android] adb shell dumpsys的使用
http://www.lai18.com/content/3777101.html
这个里面有一段话:
查询到运行的system service后,就可以在dumpsys后面加上service的名字,查看指定的service信息。
adb shell dumpsys activity
来自 <http://www.lai18.com/content/3777101.html>
也就是说:其实可以通过dumpsys 后面加service的名字,拿到所有需要的内容
8、adbshell:
http://adbshell.com/commands/adb-uninstall
9、android 中 dumpsys 命令使用
https://testerhome.com/topics/1462