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); } }); } } }