ATX ATX-uiautomator2 app 原生 + webview 的实际操作记录 (安卓)

郝斯文 · 2018年09月04日 · 最后由 bluepang2016 回复于 2021年05月18日 · 8790 次阅读

只是为了记录自己实践的过程以及遇到的问题,也会直接引用各位大佬的

由于之前一直都是在用 appium,但是 appium 太不稳定,依懒性太强,后来发现了新大陆 ATX,真是惊喜!而且大佬@codeskyblue 在 atx 项目中已经实现了对 Android Webview 的支持
(目前只支持安卓的)

大佬@codeskyblue的 uiautomator2 Webview 的简单说明地址: https://testerhome.com/topics/7232
主要大部分都是跟着大佬@cynicATX-uiautomator2 实现 webview 的操作说明一步一步进行的
这里不多说其他 uiautomator2 的安装跟环境配置问题,具体说明如下链接内都有详细说明,
https://testerhome.com/topics/12521
https://testerhome.com/topics/11357

一、chromedriver 配置(必备)

1、通过访问 chrome://inspect可以查到当前 App 使用的 WebView 版本(切记手机要链接上电脑-wifi 跟 usb 链接都可以)

2、如果 chromedriver 都不知道的请自行去了解,相信用过 appium 的人都知道。当然 chromedriver 版本的选择也很讲究,必须跟你手机应用使用的 WebView 版本相对应,过高过低都不行,具体的版本对应关系可以查看https://npm.taobao.org/mirrors/chromedriver/2.28/notes.txt
3、那看上图 WebView 版本的版本是 55,那么对应的 chromedriver 版本应该是 2.28

4、找到对应的 chromedriver 版本后自行下载到本地,并添加到 PATH 中。(启动不启动都可以)
5、selenium 安装:pip install selenium

切记:Chrome 开 inspect 的时候不能和 python 代码同时运行。

二、修改 chromedriver.py 相关代码

直接修改 atx 的 chromedriver.py 代码
(这里说的 chromedriver.py 是 atx 模块下的,需要安装 atx,如果不想安装 atx 就从https://github.com/NetEaseGame/ATX/blob/master/atx/ext/chromedriver.py 下载到本地放到代码目录下,下面导入 from atx.ext.chromedriver import ChromeDriver 根据存放的目录自行修改),

  • d.current_app() 这里有个问题(只是我遇到了,不知道你们是否会这样,如果没问题就不用改)说明下,d.current_app() 的 package 是等于 ‘d0 com.github.android_app_bootstrap’ 比 PackageName 多一个 ‘d0’,所以可能会导致报错 app 没有安装的提示,如下所示:

    selenium.common.exceptions.WebDriverException: Message: unknown error: d0 com.github.android_app_bootstrap is not installed on device 2240e086
    (Driver info: chromedriver=2.28.455520 (cc17746adff54984afff480136733114c6b3704b),platform=Windows NT 6.1.7601 SP1 x86_64)
    
    • 所以我改用 d.info 的 currentPackageName
    • 也可以自己处理下 d.current_app() 的 package: PackageName=app['package'].split(' ')[1]
  • device_ip 是为了方便 wifi 连接使用(切记要先拿手机 adb tcpip 实现 adb 无线连接,具体操作如下)

    • 将 Android 设备与要运行 adb 的电脑连接到同一个局域网,比如连到同一个 WiFi。
    • 将设备与电脑通过 USB 线连接。 应确保连接成功(可运行 adb devices 看是否能列出该设备)。
    • 让设备在 5555 端口监听 TCP/IP 连接: adb tcpip 5555
  • 由于我是 Windows 开始一直报 MaxRetryError,不知道怎么回事,后来仔细去看了 chromedriver.py 的代码逻辑,实际上它的原理很简单,
    它需要 start chromedriver instance(但并不是每次都要启动,只需要正常启动一次即可),于是我手动启动后再执行代码成功了,所以我增加了 MaxRetryError 的报错捕捉,捕捉到就先启动 chromedriver,再通过 webdriver 驱动应用操作。

(有些电脑环境不是报 MaxRetryError,自己看情况,也可以直接把 try except 去掉)

三、代码实践

一样也是拿 macac 的 demo 演示的 apk 来测试一下看看,apk 下载地址:https://npmcdn.com/android-app-bootstrap@latest/android_app_bootstrap/build/outputs/apk/android_app_bootstrap-debug.apk

  • testwebview.py 代码如下:
import time
import uiautomator2 as u2
from atx.ext.chromedriver import ChromeDriver

d = u2.connect('10.10.23.15')  #手机的ip 为10.10.23.15
d.app_start('com.github.android_app_bootstrap',stop='True')
d(text='Login').click()
d(text='Baidu').click()
driver = ChromeDriver(d).driver('10.10.23.15:5555')  #这里也一样填手机的ip,端口5555即可
driver.find_element_by_id('index-kw').click()
driver.find_element_by_id('index-kw').send_keys('Python')
driver.find_element_by_id('index-bn').click()
print(driver.title)
driver.quit()
  • 代码是通过 ip 连接的(断开数据线的情况)

    • 通过python -m uiautomator2 init(init 的时候必须数据线连接电脑才可以哦,当然如果 wifi 连接上了的也可以不用数据线)初始化后的 uiautomator 就可以看到 ip,这里有个问题就是锁屏或者关机重启后可能都需要重新python -m uiautomator2 init才能确保设备连接电脑,如果你不想每次都 init,可以用 u2init 解决你的烦恼,具体操作说明请跳转->atx-server u2init 实现设备自动接入 server,即插即连
  • 手机有线连接电脑的情况下 ip 不需要填,为空即可

四、webview 的 setWebContentsDebuggingEnabled->使用 VXP 强制开始 WebView

webview 可以切换过去了,但是还有一个问题,就是需要把被测 APP 的 webview 的 setWebContentsDebuggingEnabled 打开,需要开发人员修改代码开启支持,或者跑在模拟器上
一开始,是很苦恼的事情,后来发现大佬的笔记。

关于那个插件的原理可以在这里看到 https://www.jianshu.com/p/d6699cd4505e

安装好之后,先打开

进入到模块中,勾选 WebViewDebugHook

返回,然后向下滑动,进入界面,点击箭头位置

最后进入到一个设置页面,拖到最下面点击 重启 让插件更改生效

PS: 使用 VXP 安装的应用 pm list packages 是看不到的,只有在运行的时候用 ps 才可以查看到

共收到 3 条回复 时间 点赞

赞,实践精神

郝斯文 [该话题已被删除] 中提及了此贴 09月14日 11:18

请教下 我运行例子里面的代码,启动的怎么是 PC 端的 chrome 呢?

if name == 'main':
import uiautomator2 as u2
import time

d = u2.connect()
d.app_stop('com.github.android_app_bootstrap')
d.app_start('com.github.android_app_bootstrap')
d(text='Login').click()
d(text='Baidu').click()
time.sleep(3)
driver = ChromeDriver(d).driver()
driver.find_element_by_id('index-kw').click()
driver.find_element_by_id('index-kw').send_keys('Python')
driver.find_element_by_id('index-bn').click()
driver.quit()

qugo9955 回复

亲测这种调用 webdriver 的方式有问题,换下面这种方式就可以了:
d = u2.connect()
app = d.app_current()
print(app)

options = webdriver.ChromeOptions()
options.add_experimental_option('androidDeviceSerial', d.serial)
options.add_experimental_option('androidPackage', app.get('package'))
options.add_experimental_option('androidUseRunningApp', True)

driver = webdriver.Chrome('chromedriver', options=options)
print(driver.current_url)

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册