版权声明:本文为博主原创文章,未经博主同意不得转载。

https://blog.csdn.net/hunterno4/article/details/35569665

        robotium框架支持WebView,在robotium中有getWebElements()、getWebElements(By by)等方法来获取android中的WebView的元素。并提供了 clickOnWebElement方法来完毕点击事件.android中的原生控件是比較好攻取的,那么对于WebView这个框架是怎么获取的呢。

第一步:利用JS获取页面中的全部元素 
         在PC上,获取网页的元素能够通过注入javascript元素来完毕,以Chrome浏览器为例,打开工具——JavaScript控制台(快捷方式:Ctrl+Shift+J)。输入 javascript:prompt(document.URL)即会弹出含当前页面的URL的提示框,因此通过编写适当的JS脚本是能够在这个弹出框中显示全部页面元素的。

RobotiumWeb.js就是此功能实现用的JS脚本。以solo中getWebElements()为例,

	public ArrayList<WebElement> getWebElements(boolean onlySufficientlyVisible){
boolean javaScriptWasExecuted = executeJavaScriptFunction("allWebElements();"); return getWebElements(javaScriptWasExecuted, onlySufficientlyVisible);
}
	private boolean executeJavaScriptFunction(final String function){
final WebView webView = viewFetcher.getFreshestView(viewFetcher.getCurrentViews(WebView.class, true)); if(webView == null){
return false;
}
//做一些JS注入运行前的准备工作。比如将WebView设为可同意运行JS等,并将RobotiumWeb.js中的脚本以String形式返回
final String javaScript = prepareForStartOfJavascriptExecution(); activityUtils.getCurrentActivity(false).runOnUiThread(new Runnable() {
public void run() {
if(webView != null){
webView.loadUrl("javascript:" + javaScript + function);
}
}
});
return true;
}
        能够看出这种方法运行的是allWebElements();函数,即相似运行RobotiumWeb.js文件里例如以下JS代码片段:
能够把例如以下片段放到JavaScript控制台中看效果
javascript:
function allWebElements() {
for (var key in document.all){
try{
promptElement(document.all[key]); //调用promptElement(element)函数
}catch(ignored){}
}
finished(); //运行完后,调用finished()函数
} function promptElement(element) {
var id = element.id;
var text = element.innerText;
if(text.trim().length == 0){
text = element.value;
}
var name = element.getAttribute('name');
var className = element.className;
var tagName = element.tagName;
var attributes = "";
var htmlAttributes = element.attributes;
for (var i = 0, htmlAttribute; htmlAttribute = htmlAttributes[i]; i++){
attributes += htmlAttribute.name + "::" + htmlAttribute.value;
if (i + 1 < htmlAttributes.length) {
attributes += "#$";
}
} var rect = element.getBoundingClientRect();
if(rect.width > 0 && rect.height > 0 && rect.left >= 0 && rect.top >= 0){
prompt(id + ';,' + text + ';,' + name + ";," + className + ";," + tagName + ";," + rect.left + ';,' + rect.top + ';,' + rect.width + ';,' + rect.height + ';,' + attributes); //弹出包括id、text、name等字段的提示框
}
}
function finished(){
prompt('robotium-finished'); //弹出包括robotium-finished字符串的提示框,用于标识脚本注入运行结束
}

        从脚本中能够看出JS获得页面元素后还进行了一定的格式化处理,在每一个元素之间加了;,符号,这也是为了在后面代码中更加方便地解析。脚本的最后调用了finished()函数,即弹出包括robotium-finished的提示框。这一步完毕了页面元素的获取,那么提示框中包括的内容在Android中怎么获取呢?
第二步:在Android中获取WebView中prompt提示框中的信息
        在Android的Webkit包中有个WebChromeClient类,这个类中的onJsPrompt方法就是用于处理WebView中的提示框的,当WebView中有JS提示框时,会回调该方法。String message參数将包括提示框中的信息,因此robotium写了个继承自WebChromeClient类的RobotiumWebClient类。覆写了onJsPrompt
onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result)
	@Override
public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult r) { if(message != null && (message.contains(";,") || message.contains("robotium-finished"))){
//假设提示框中包括robotium-finished字符串,即表示那段JS注入脚本运行完毕了
if(message.equals("robotium-finished")){
webElementCreator.setFinished(true);
}
else{
webElementCreator.createWebElementAndAddInList(message, view);//有人提示框中的内容。那么就能够对提示框中的内容进行处理了
}
r.confirm();
return true;
}
else {
if(originalWebChromeClient != null) {
return originalWebChromeClient.onJsPrompt(view, url, message, defaultValue, r);
}
return true;
} }

      

     另外。原本的WebView默认是不同意运行JS的。因此须要先运行enableJavascriptAndSetRobotiumWebClient方法。

将JavaScriptEnabled设置为true。将将WebChromeClient设置为robotiumWebClient

	public void enableJavascriptAndSetRobotiumWebClient(List<WebView> webViews, WebChromeClient originalWebChromeClient){
this.originalWebChromeClient = originalWebChromeClient; for(final WebView webView : webViews){ if(webView != null){
inst.runOnMainSync(new Runnable() {
public void run() {
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebChromeClient(robotiumWebClient); }
});
}
}
}
第三步:将提示框中的消息存入WebElement Java bean中
        获取到了prompt提示框中的消息后。接下来就是对这些已经过处理含特殊格式的消息进行解析处理了。依次得到WebElement的id、text、name等字段。

	private WebElement createWebElementAndSetLocation(String information, WebView webView){
String[] data = information.split(";,"); //将消息按;,符号切割,当中;,符号是在前面运行JS时增加的
String[] elements = null;
int x = 0;
int y = 0;
int width = 0;
int height = 0;
Hashtable<String, String> attributes = new Hashtable<String, String>();
try{
x = Math.round(Float.valueOf(data[5]));
y = Math.round(Float.valueOf(data[6]));
width = Math.round(Float.valueOf(data[7]));
height = Math.round(Float.valueOf(data[8]));
elements = data[9].split("\\#\\$");
}catch(Exception ignored){} if(elements != null) {
for (int index = 0; index < elements.length; index++){
String[] element = elements[index].split("::");
if (element.length > 1) {
attributes.put(element[0], element[1]);
} else {
attributes.put(element[0], element[0]);
}
}
} WebElement webElement = null; try{
webElement = new WebElement(data[0], data[1], data[2], data[3], data[4], attributes);//将id、text、name等字段存入
setLocation(webElement, webView, x, y, width, height);
}catch(Exception ignored) {} return webElement;
}
	/**
* Sets the location of a {@code WebElement}
*
* @param webElement the {@code TextView} object to set location
* @param webView the {@code WebView} the text is shown in
* @param x the x location to set
* @param y the y location to set
* @param width the width to set
* @param height the height to set
*/ private void setLocation(WebElement webElement, WebView webView, int x, int y, int width, int height ){
float scale = webView.getScale();
int[] locationOfWebViewXY = new int[2];
webView.getLocationOnScreen(locationOfWebViewXY); int locationX = (int) (locationOfWebViewXY[0] + (x + (Math.floor(width / 2))) * scale);
int locationY = (int) (locationOfWebViewXY[1] + (y + (Math.floor(height / 2))) * scale); webElement.setLocationX(locationX);
webElement.setLocationY(locationY);
}

至此。WebElement对象中包括了id、text、name等字段。还包括了x、y坐标,知道了坐标后就能够像其他Android中的原生View一样依据坐标发送点击事件。

robotium原理之获取WebElement元素的更多相关文章

  1. Selenium 获取隐藏元素的内容

    第一种 先获取元素通过 属性获取 WebElement webElemt= webElement.findElement(By.xpath("//*[@class='xxxxxx]/a&qu ...

  2. selenium定位方式-获取标签元素:find_element_by_xxx

    定位方式取舍# 唯一定位方式.多属性定位.层级+角标定位(离目标元素越近,相对定位越好) # 推荐用css selector(很少用递进层次的定位)# 什么时候用xpath呢? 当你定位元素时,必须要 ...

  3. vue获取dom元素注意问题

    mounted(){ setTimeout(()=>{ this.contentToggle(); },1000) }, methods:{ contentToggle(){ console.l ...

  4. Robotium原理初步--Android自动化测试学习历程

    章节:自动化基础篇——Robotium原理初步(第四讲) 主要讲解内容与笔记: 一.基于控件 1.spinner——下拉菜单 2.TabHost——左右滑动选择菜单,类似电话本 3.Gallery—— ...

  5. selenium 获取某元素的 某属性 的值

    selenium  获取某元素的 某属性的值 1 先通过元素定位,获得此元素的 WebElement; WebElement   yuansu = driver.findElement(By.clas ...

  6. javascript实现浏览器管理员工具鼠标获取Html元素 并生成 xpath

    javascript实现浏览器管理员工具鼠标获取Html元素 并生成 xpath 看看标题就被吓尿了,够长吧.让我们看看到底是个什么玩意.. 直接上图: 就是这个东东了,做为一个写爬虫的,有必要了解下 ...

  7. selenium+python自动化104-如何获取隐藏元素text文本

    前言 首先 selenium 是可以定位到隐藏元素的,但是 selenium 不能跟隐藏元素交互,也就是隐藏元素element不能使用element.click()方法. 隐藏元素element.te ...

  8. 如何通过源生js获取一个元素的具体样式值 /* getCss:获取指定元素的具体样式的属性值 curElement:[dom对象] attr:[string] */

    昨天的博客些的真的是惨不忍睹啊!!!但是我的人生宗旨就是将不要脸的精神进行到底,所以,今天我又来了.哈哈哈哈哈! 方法一:元素.style.属性名:(这个有局限性--只能获取行内样式的值,对于样式表或 ...

  9. v-for遍历出的元素上添加click事件,获取对应元素上的属性id值

    <span v-for="(n,nav) in floorList" data-id="{{nav.itemId}}" v-on:click=" ...

随机推荐

  1. C++ operator关键字

    operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名. 这是C++扩展运算符功能的方法,虽然样子古怪,但也可以理解:一方面要使运算 ...

  2. javascript父、子页面交互小结

    帧用来存放子页面,既可以是iframe,又可以是frameset.window对象是全局对象,页面上的一切函数和对象都在它的作用域里.     1.parent代表父窗口.如果父窗口又存在若干层嵌套, ...

  3. 【BZOJ】1648: [Usaco2006 Dec]Cow Picnic 奶牛野餐(dfs)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1648 水题.. dfs记录能到达的就行了.. #include <cstdio> #in ...

  4. 【DeepLearning】一些资料

    记录下,有空研究. http://nlp.stanford.edu/projects/DeepLearningInNaturalLanguageProcessing.shtml http://nlp. ...

  5. Hibernate 自动生成数据库表

    http://blog.csdn.net/u010096526/article/details/50533428

  6. Struts2_day03--OGNL的#、%使用

    OGNL的#.%使用 #使用 1 使用#获取context里面数据 2 演示# 操作 (1)向request域放值 (2)在页面中使用ognl获取 %使用 1 在struts2标签中表单标签 (1)在 ...

  7. Jquery-easyUi------(布局)

    <%@ Master Language="C#" Inherits="System.Web.Mvc.ViewMasterPage" %> <! ...

  8. C++中的自动存储、静态存储和动态存储

    根据用于分配内存的方法,C++中有3中管理数据内存的方式:自动存储.静态存储和动态存储(有时也叫做自由存储空间或堆).在存在是间的长短方面,以这三种方式分配的数据对象各不相同.下面简要介绍这三种类型( ...

  9. 扩展jquery scroll事件,支持 scroll start 和 scroll stop

    效果预览: github: https://besswang.github.io/webapp-scroll/ 参考地址: http://www.ghugo.com/special-scroll-ev ...

  10. MYSQL常用命令(转载)

    1.导出整个数据库 mysqldump -u 用户名 -p --default-character-set=latin1 数据库名 > 导出的文件名(数据库默认编码是latin1)mysqldu ...