在混合开发的App中,经常会有内嵌的H5页面。那么这些H5页面元素该如何进行定位操作呢?
针对这种场景直接使用前面所讲的方法来进行定位是行不通的,因为前面的都是基于Andriod原生控件进行元素定位,而Web网页是单独的B/S架构,两者的运行环境不同因此需要进行上下文(context)切换,然后对H5页面元素进行定位操作。
Context的中文翻译为:语境; 上下文; 背景; 环境,在开发中我们经常说“上下文”,那么这个“上下文”到底是指什么意思呢?
Android源码中的注释是这么来解释Context的:
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
翻译如下:
关于应用程序环境的全局信息的接口。这是一个抽象类,其实现由Android系统提供。它允许访问特定于应用程序的资源和类,以及对应用程序级操作的调用,如启动活动、广播和接收意图等。
在程序中context我们可以理解为当前对象在程序中所处的一个环境。比如前面提到的App一个界面是属于Activity类型,也就是Android界面环境,但是当访问内嵌的网页是属于另外一个环境(网页环境),两者处于不同的一个环境。
dr.fone app 内嵌网页地址:https://drfone.wondershare.com/backup.html
WebView
是Android
系统提供能显示网页的系统控件,它是一个特殊的View
,同时它也是一个ViewGroup
,可以有很多其他子View。
在Android 4.4
以下(不包含4.4)系统WebView底层实现是采用WebKit
(http://www.webkit.org/)内核,
而在Android 4.4
及其以上Google 采用了chromium
(http://www.chromium.org/)作为系统WebView的底层内核支持。
这里简单介绍下基于Chromium
的Webview
和基于Webkit webview
的差异,基于Chromium Webview
提供更广的HTML5,CSS3,Javascript支持,在目前最新Android
系统版本5.0上基于chromium 37
,Webview
提供绝大多数的HTML5
特性支持。Webkit JavaScript
起采用WebCore Javascript
在Android 4.4
上换成了V8
能直接提升JavaScript
性能。另外Chromium
支持远程调试(Chrome DevTools)。
手机上安装Chrome必须Google play去安装,手机上没有Google play可以先安装一个“GO谷歌安装器” 安装后注册Google play账号(由于众所周知的网络原因,Googleplay大陆地区无法使用)
Android System WebView
版本对应,否则不支持。Appium Chromedriver 官方说明文档 chromediver路径 一般位于appium路径中的...\node_modules\appium-chromedriver\chromedriver\win里面,如下所示:运行chromedriver.exe可以查看到当前的版本信息。
C:\Users\Shuqing\AppData\Roaming\npm\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win
adb devices
可查看到此设备。(设备系统Android 5.0以上)chrome://inspect/#devices
,进入调试模式,点击 inspect
可以打开H5调试页面。如下图所示在app中配置如下代码(在WebView类中调用静态方法setWebContentsDebuggingEnabled):
if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.KITKAT) {
WebView.setWebContentsDebuggingEnabled(true);
注:此步骤,一般需要App开发人员开启。
启动dr.fone app 进入backup H5页面中的输入邮箱并点击提交,然后返回
获取方法实践
contexts=driver.contexts
print(contexts)
#打印结果
['NATIVE_APP', 'WEBVIEW_com.android.launcher', 'WEBVIEW_com.wondershare.drfone', 'WEBVIEW_com.psiphon3']
by_h5.py
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
desired_caps={}
desired_caps['platformName']='Android'
desired_caps['platformVersion']='5.1.1'
desired_caps['deviceName']='127.0.0.1:21503'
desired_caps['app']=r'C:\Users\Shuqing\Desktop\dr.fone3.2.0.apk'
desired_caps['appPackage']='com.wondershare.drfone'
desired_caps['appActivity']='com.wondershare.drfone.ui.activity.WelcomeActivity'
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
driver.implicitly_wait(5)
#点击Backup菜单
print('click BackupBtn')
driver.find_element_by_id('com.wondershare.drfone:id/btnBackup').click()
#等待next菜单,然后点击
WebDriverWait(driver,8).until(lambda x:x.find_element_by_id('com.wondershare.drfone:id/btnRecoverData'))
print('click NextBtn')
driver.find_element_by_id('com.wondershare.drfone:id/btnRecoverData').click()
#等待webview页面加载
WebDriverWait(driver,8).until(lambda x:x.find_element_by_class_name('android.webkit.WebView'))
contexts=driver.contexts
print(contexts)
#需android4.4及以上版本的系统中才会输出更多的webview
print('switch conetext')
driver.switch_to.context('WEBVIEW_com.wondershare.drfone')
print('edit email')
driver.find_element_by_id('email').send_keys('shuqing@wondershare.cn')
print('click sendBtn')
driver.find_element_by_class_name('btn_send').click()
#切换context 点击返回
driver.switch_to.context('NATIVE_APP')
driver.find_element_by_class_name('android.widget.ImageButton').click()
报错1
raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.WebDriverException:Message: An unknown server-side error occurred while processing the command.
Original error: Failed to start Chromedriver session: A new session could not be created.
(Original error: session not created exception: Chrome version must be >= 60.0.3112.0
报错2
error: Chromedriver: Chromedriver exited unexpectedly with code null, signal SIGTERM
【解决方案】
{Appium path}\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win
Mac路径
/Applications/Appium.app/Contents/Resources/app/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac