一,背景
web页面会在微信中运行。由于UI自动化的需要,需连接微信下的webView页面
二,过程
通过appium连接,可通过inspector与android的native交互,但微信访问web页面后,再用inspector获取页面,inspect可以检测到页面的context了,可一切换就报错,提示chromedriver版本不匹配。
appium 中的chromedriver版本 与 微信内嵌的chrome版本不对应 ?
查看appium的详细日志可知:
目标chrome版本是v86.0.4240,且appium已下载了v86.0.4240 版本的chromdriver,还是报错?继续查看日志
还是报错,查看chromedriver服务的详细过程,可知中间疯狂请求了/json/list,但结果都为空。
继续分析,发现,实际上chromedriver发现了chorme,但不是86版本的chrome,为什么?因为 adb forward 关联的sockect Namespace 是 webview_devtools_remote_16203,其确实没有pages。
那么到底是哪个有page?
查看了相关的命名空间,并逐个forward后,发现 xweb_devtools_remote_16203 才是目标page的所在。
GET http://127.0.0.1:9444/json/version
GET http://127.0.0.1:9444/json
此时才出现预期的webview页面。
xweb是什么东东?xweb是微信新版的内核。旧版的内核是X5。在X5时,socketNamespace 都是 webview_devtools_remote_pid 格式的;但是在xweb内核,就变成 xweb_devtools_remote_pid 格式了。
三,根因
简单对webview建连的原理做下总结。chromedriverService 通过 adb forward 将本地端口 与 android上的chromium的debug端口做映射,所以可达到通过本地端口来与android上的webview通信的效果。
所以问题的原因是什么?是chromedriver的版本的问题吗?实际不是。
根本的原因是, com.tencent.mm:toolsmp 进程下 有 两个 socket Namespace,分别是 webview_devtools_remote_16203 与 xweb_devtools_remote_16203。但 chromedriver 在查时,只会查 webview_devtools_remote_pid 格式的(可能是chromium的规范如此),但微信的xweb内核采用的是 xweb_devtools_remote_pid 格式,所以永远也无法请求到目标page。
四,解决
谁来解决这个问题?
chromedriver官方?其实早在2019年就有前辈给chromedriver官方提了这个问题(其实关于连接微信的webview失败,网上有很多的原因与解决帖,但我认为该前辈讲到的才是根本)
但官方的回复是不解决
appium?从appium的issue上可看到许多wechat上的webview连接失败的问题,实际上appium也无法解决,因为它也是复用了chromedriver的能力。
那咱们撸一个?
实际逻辑也不复杂,adb forward 对应的 socketName 不局限在 webview_remote_devtools,而是遍历下含 remote_devtools 的socketName,找出预期的即可。
为此咱们基于python实现了个小demo,感兴趣的小伙伴可以搞下来耍耍。
https://github.com/HamburgerZ/Py_CDP_Android
当然基于JS通过Pupeeteer工具包也能实现。