换种方式玩手机

设备管理

连接设备

adb connect/disconnect

Android日志

Android 系统的日志分为两部分,底层的 Linux 内核日志输出到 /proc/kmsg,Android 的日志输出到 /dev/log。使用adb logcat,可以将logcat日志信息输出到屏幕

手机teriminal

adb shell

查询已连接设备/模拟器

$ adb devices

List of devices attached
cf264b8f	device
emulator-5554	device
10.129.164.6:5555	device

端口转发

adb forword,可以设置将对特定主机端口的请求转发到模拟器/设备实例上的其他端口

查看设备信息

d.info

{'currentPackageName': 'com.ss.android.ugc.aweme', 'displayHeight': 1280, 'displayRotation': 0, 'displaySizeDpX': 411, 'displaySizeDpY': 731, 'displayWidth': 720, 'productName': 'cancro', 'screenOn': True, 'sdkInt': 23, 'naturalOrientation': True}

查看WLAN ip

d.wlan_ip 

查看设备详细信息

d.device_info 

{'udid': 'ZX1G42CPJD-08:00:27:81:24:f1-MIX_2', 'version': '6.0.1', 'serial': 'ZX1G42CPJD', 'brand': 'Xiaomi', 'model': 'MIX 2', 'hwaddr': '08:00:27:81:24:f1', 'port': 7912, 'sdk': 23, 'agentVersion': '0.9.5', 'display': {'width': 720, 'height': 1280}, 'battery': {'acPowered': True, 'usbPowered': False, 'wirelessPowered': False, 'status': 2, 'health': 2, 'present': True, 'level': 47, 'scale': 100, 'voltage': 3836, 'temperature': 251, 'technology': 'Li-poly'}, 'memory': {'total': 3628052, 'around': '3 GB'}, 'arch': '', 'owner': None, 'presenceChangedAt': '0001-01-01T00:00:00Z', 'usingBeganAt': '0001-01-01T00:00:00Z', 'product': None, 'provider': None}

将文件推送到设备

d.push("foo.txt", "/sdcard/") 

从设备中拉出文件

d.pull("/sdcard/tmp.txt", "tmp.txt") 

在设备中执行命令

output, exit_code = d.shell("pm list packages", timeout=60) # timeout 60s (Default)

{"error":null,"exitCode":0,"output":"package:com.github.uiautomator\npackage:com.hpbr.bosszhipin\npackage:com.android.providers.telephony\npackage:io.appium.settings\npackage:com.android.providers.calendar\npackage:com.android.providers.media\npackage:com.sohu.inputmethod.sogou\npackage:com.android.wallpapercropper\npackage:com.minhui.networkcapture\npackage:com.android.documentsui\npackage:com.android.galaxy4\npackage:com.android.externalstorage\npackage:com.android.htmlviewer\npackage:cn.com.open.mooc\npackage:com.android.quicksearchbox\npackage:com.android.mms.service\npackage:com.android.providers.downloads\npackage:com.github.uiautomator.test\npackage:com.android.browser\npackage:com.tal.kaoyan\npackage:io.appium.uiautomator2.server\npackage:com.android.defcontainer\npackage:de.robv.android.xposed.installer\npackage:com.droider.crackme0201\npackage:com.android.providers.downloads.ui\npackage:com.android.pacprocessor\npackage:com.xingin.xhs\npackage:com.tencent.mm\npackage:com.android.certinstaller\npackage:com.cxdosx.gowifisetting\npackage:com.cubic.choosecar\npackage:android\npackage:com.tencent.android.qqdownloader\npackage:com.android.camera2\npackage:com.baidu.searchbox\npackage:com.android.backupconfirm\npackage:com.yoho\npackage:com.android.provision\npackage:com.android.statementservice\npackage:bin.mt.plus\npackage:com.android.wallpaper.holospiral\npackage:com.android.phasebeam\npackage:com.android.providers.settings\npackage:just.trust.me\npackage:com.android.sharedstoragebackup\npackage:com.android.printspooler\npackage:com.tencent.qqlite\npackage:com.android.webview\npackage:com.android.inputdevices\npackage:com.xunmeng.pinduoduo\npackage:com.google.android.apps.maps\npackage:com.android.server.telecom\npackage:com.android.keychain\npackage:com.android.chrome\npackage:com.buscode.whatsinput\npackage:com.android.gallery3d\npackage:com.ss.android.ugc.aweme\npackage:com.android.calllogbackup\npackage:com.tencent.mobileqq\npackage:com.android.packageinstaller\npackage:com.android.proxyhandler\npackage:com.cyanogenmod.filemanager\npackage:io.dcloud.H5EA954BB\npackage:app.greyshirts.sslcapture\npackage:io.appium.uiautomator2.server.test\npackage:com.android.wallpaper.livepicker\npackage:com.zhuanzhuan.check\npackage:jackpal.androidterm\npackage:com.android.settings\npackage:com.nice.main\npackage:com.android.wallpaper\npackage:com.android.vpndialogs\npackage:com.sina.weibo\npackage:com.android.phone\npackage:com.android.shell\npackage:com.android.providers.userdictionary\npackage:com.hupan.app\npackage:com.android.location.fused\npackage:com.android.systemui\npackage:com.android.bluetoothmidiservice\npackage:io.kkzs\npackage:tv.danmaku.bili\npackage:com.android.captiveportallogin\npackage:org.geekbang.geekTime\n"}

应用管理

安装apk

adb install [-lrtsdg] <path_to_apk>

卸载apk

adb uninstall com.ss.android.ugc.aweme

启动app

d.app_start("com.ss.android.ugc.aweme")

停止app

d.app_stop("com.ss.android.ugc.aweme") 

清除app数据

d.app_clear('com.ss.android.ugc.aweme')

获取当前的应用信息

d.app_current()

{'package': 'com.ss.android.ugc.aweme', 'activity': 'com.ss.android.ugc.aweme.splash.SplashActivity'}

停止所有的app

d.app_stop_all()

获得app信息

d.app_info("com.examples.demo")

{"data":{"packageName":"com.ss.android.ugc.aweme","mainActivity":"com.ss.android.ugc.aweme.main.MainActivity","label":"抖音短视频","versionName":"10.6.0","versionCode":100601,"size":82302370},"success":true}

获得所有正在运行的app

d.app_list_running()

['com.android.gallery3d', 'com.android.defcontainer', 'com.android.keychain', 'com.android.statementservice', 'com.android.shell', 'com.android.documentsui', 'com.ss.android.ugc.aweme', 'com.android.externalstorage', 'com.android.phone', 'com.tencent.mm', 'com.android.systemui']

查看应用列表 

d.app_list() 

支持的参数

支持的过滤参数如下:

参数

显示列表

所有应用

-f

显示应用关联的 apk 文件

-d

只显示 disabled 的应用

-e

只显示 enabled 的应用

-s

只显示系统应用

-3

只显示第三方应用

-i

显示应用的 installer

-u

包含已卸载应用

<FILTER>

包名包含 <FILTER> 字符串

与应用的交互

打印UI

xml = d.dump_hierarchy() 

元素定位

resourceId
d(resourceId=)这种方法是最方便的,但是一个APP很多地方都不会有这种特定的标识
className
d(className=)这个方法也很方便,但是弊端也是同个界面多个元素使用同一个className
xpath
d.xpath()在以上方法都不行时就需要xpath定位了,弊端是APP当中的元素id跟classname的影响代码很冗长,同样的如果在APP爬虫中,xpath的优势就变得明显了
text
d(text=)使用文本去确定操作的区域,好处是方便进行定位,在没有文本的就不能进行此项操作,具有局限性
坐标
d.click(坐标)使用cilck方法通过坐标定位需要点击的元素,通过这个方法可以点击的操作都可以进行完成

元素操作

点击系统按键

d.press("back")

滑动

d.swipe(sx, sy, ex, ey)

点击

d.click(x, y)

元素监控

注册监控

d.watcher("ANR").when(xpath="ANR").when("Force Close").click()

开启监控

d.watcher.start(2.0) # 默认监控间隔2.0s

停止监控

d.watcher.stop()

截图

im = d(text="Settings").screenshot()
im.save("settings.jpg")

视频录制

d.screenrecord('output.mp4')

time.sleep(10)
# or do something else

d.screenrecord.stop() # 停止录制后,output.mp4文件才能打开

图像匹配

imdata = "target.png" # 也可以是URL, PIL.Image或OpenCV打开的图像

d.image.match(imdata) 
# 匹配待查找的图片,立刻返回一个结果
# 返回一个dict, eg: {"similarity": 0.9, "point": [200, 300]}

d.image.click(imdata, timeout=20.0)
# 在20s的时间内调用match轮询查找图片,当similarity>0.9时,执行点击操作

多设备管理

atxserver2是一个可以远程控制Android和IOS设备的管理平台,技术栈为:Python3+NodeJS+RethinkDB

包括四部分:
1.RethinkDB : 是一个开源的轻量级的数据库,主要用于存储用于多设备管理的用户、设备数据等
2.atxserver2 :主要负责处理数据,显示与用户的前端交互等等,所以单独运行atxserver2也可以看到效果,当运行起来以候访问: IP:4000 就可以看到效果
3.atxserver2-android-provider: 这一部分是接入Android设备必须启动的项目,主要用于发现Android设备和负责Android设备和平台的交互工作,要想接入Android设备必须启动此项目
4.atxserver2-ios-provider: 这一部分是接入IOS设备必须启动的项目,主要负责IOS设备和平台的交互工作,同样的要想接入IOS设备必须启动此项目(注意需要MAC电脑)

基于 minicap+minitouch+atx-agent实现了Android的远程控制

Minicap提供了一个套接字接口,通过ndk的截屏接口不停的截屏并通过socket接口实时发送,这样客户端便可以得到一序列的图片流,图片流合成后就成为视频

minitouch提供了一个套接字接口,用于在Android设备上触发多点触控事件和手势

除了界面控制外,也提供了API接口控制

adb

Android 调试桥 (adb) 是一种功能多样的命令行工具,可让您与设备进行通信。adb 命令可用于执行各种设备操作(例如安装和调试应用),并提供对 Unix shell(可用来在设备上运行各种命令)的访问权限。它是一种客户端-服务器程序,包括以下三个组件:

  • 客户端:用于发送命令。客户端在开发计算机上运行。您可以通过发出 adb 命令从命令行终端调用客户端

  • 守护程序 (adbd):用于在设备上运行命令。守护程序在每个设备上作为后台进程运行

  • 服务器:用于管理客户端与守护程序之间的通信。服务器在开发机器上作为后台进程运行

adb 的工作原理

当启动某个 adb 客户端时,该客户端会先检查是否有 adb 服务器进程正在运行。如果没有,它会启动服务器进程。服务器在启动后会与本地 TCP 端口 5037 绑定,并监听 adb 客户端发出的命令 - 所有 adb 客户端均通过端口 5037 与 adb 服务器通信

然后,服务器会与所有正在运行的设备建立连接。它通过扫描 5555 到 5585 之间(该范围供前 16 个模拟器使用)的奇数号端口查找模拟器。服务器一旦发现 adb 守护程序 (adbd),便会与相应的端口建立连接。每个模拟器都使用一对按顺序排列的端口 - 用于控制台连接的偶数号端口和用于 adb 连接的奇数号端口。例如:

模拟器 1,控制台:5554
模拟器 1,adb:5555
模拟器 2,控制台:5556
模拟器 2,adb:5557
依此类推

如上所示,在端口 5555 处与 adb 连接的模拟器与控制台监听端口为 5554 的模拟器是同一个

服务器与所有设备均建立连接后,您便可以使用 adb 命令访问这些设备。由于服务器管理与设备的连接,并处理来自多个 adb 客户端的命令,因此您可以从任意客户端(或从某个脚本)控制任意设备

uiautomator2

uiautomator2是基于uiAutomator的,uiAutomator是Google提供的用来做安卓自动化测试的一个Java库,基于Accessibility服务。可以获取屏幕上任意一个APP的任意一个控件属性,并对其进行任意操作。uiautomator2将uiAutomator的功能封装成了http接口的Python库,并在在手机上运行了一个http rpc服务,实现了在电脑上运行的python脚本控制手机的目的

uiautomator2整体

uiautomator2工作流程源码追踪

1.本地

命令>http>_AgentRequestSession>_prepare_atx_agent>_setup_atx_agent>start_atx_agent>_get_atx_agent_url>forward_port

每个uiautomator2命令都会经过http方法也就是_AgentRequestSession,_AgentRequestSession在发送请求前都会先对atx-agent的版本检查一下_prepare_atx_agent,如果版本不符则进行安装操作并启动atx-agent,之后_AgentRequestSession开始获得atx_agent_url,其中host是localhost,端口是从forward_list获得的,如果没有则新forward一个,这样在本地运行的命令请求现在到了本地的forward端口上了,forward是一个socket连接,根据协议其将本地指定端口的数据转发到远端指定端口上,也就是手机设备7912端口,atx-agent服务运行在这个端口上

2.atx-agent

uiautomatorProxy>android-uiautomator-server

atx-agent收到请求后,根据路由如果是"/jsonrpc/0"或"/ping"将交给uiautomatorProxy处理,源码

atx-agent转发处理
atx-agent转发处理

uiautomatorProxy收到调用后,负责将数据携带好后,进而去请求9008端口的服务,起到的是代理的作用,源码

uiautomatorProxy代理

这个占用9008端口的服务也是atx-agent触发的,源码

atx-agent启动uiautomator

3.android-uiautomator-server

AutomatorHttpServer>JsonRpcServer>UiAutomator

这里是真正包裹原生uiautomator的那个服务AutomatorHttpServer,可以看到是在这里启动的9008端口,源码

启动9008服务
启动9008服务

AutomatorHttpServer是基于NanoHTTPD的,NanoHTTPD是一个轻量级的java服务器,源码

基于NanoHTTPD的AutomatorHttpServer

随后,setUp中,又做了一次路由,将jsonrpc/0这种请求丢给了JsonRpcServer处理,进而调用AutomatorService中的方法,源码

AutomatorService

总结

1.基本操作:本次主要对手机先以设备管理、应用管理、与应用的交互、多设备管理的维度,介绍了在不接触的情况下,通过代码的方式来获得手机信息并控制其运行,其实它还能帮我们做更多的事情,只要人可以做的它也可以做,在工作或生活中如果有需要对APP进行有规律的操作,交给它就可以了
2.监控:为了方面随时查看手机的运行状况,增加监控,在远程也可以直观的查看操控手机
3.原理:在最后介绍了一下代码是如何控制手机运行的,了解了它的运行原理后希望能够对大家有些启发,因为我们也可以写一些库发送到手机上作一些工具,比如说做后门,做监控,做很多很多

 

相关资料:

awesome-adb

uiautomator2

atx-agent

android-uiautomator-server

atxserver2

atxserver2-android-provider

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值