您好,登錄后才能下訂單哦!
通過前面的兩篇文章《Appium Android Bootstrap源碼分析之控件AndroidElement》和《Appium Android Bootstrap源碼分析之命令解析執行》我們了解到了Appium從pc端發送過來的命令是如何定位到命令相關的控件以及如何解析執行該命令。那么我們剩下的問題就是bootstrap是怎么啟動運行的,我們會通過本篇文章的分析來闡述這個問題,以及把之前學習的相關的類給串起來看它們是怎么互動的。
public class Bootstrap extends UiAutomatorTestCase { public void testRunServer() { SocketServer server; try { server = new SocketServer(4724); server.listenForever(); } catch (final SocketServerException e) { Logger.error(e.getError()); System.exit(1); } } }從代碼中可以看到,這個類是繼承與UiAutomatorTestCase的,這樣它就能被uiautomator作為測試用例類來執行了。
public SocketServer(final int port) throws SocketServerException { keepListening = true; executor = new AndroidCommandExecutor(); try { server = new ServerSocket(port); Logger.debug("Socket opened on port " + port); } catch (final IOException e) { throw new SocketServerException( "Could not start socket server listening on " + port); } }它做的第一個事情是先去創建一個AndroidCommandExecutor的實例,大家應該還記得上一篇文章說到的這個類里面保存了一個靜態的很重要的action到命令處理類CommandHandler的實例的映射表吧?如果沒有看過的請先去看下。
public void listenForever() throws SocketServerException { Logger.debug("Appium Socket Server Ready"); ... try { client = server.accept(); Logger.debug("Client connected"); in = new BufferedReader(new InputStreamReader(client.getInputStream(), "UTF-8")); out = new BufferedWriter(new OutputStreamWriter(client.getOutputStream(), "UTF-8")); while (keepListening) { handleClientData(); } in.close(); out.close(); client.close(); Logger.debug("Closed client connection"); } catch (final IOException e) { throw new SocketServerException("Error when client was trying to connect"); } ... }首先調用server.accept去接受appium的連接請求,連接上后就去初始化用于讀取socket的BufferedReader和BufferredWriter這兩個類的實例,最后進入到handleClicentData來進行真正的數據讀取和處理
private void handleClientData() throws SocketServerException { try { input.setLength(0); // clear String res; int a; // (char) -1 is not equal to -1. // ready is checked to ensure the read call doesn't block. while ((a = in.read()) != -1 && in.ready()) { input.append((char) a); } String inputString = input.toString(); Logger.debug("Got data from client: " + inputString); try { AndroidCommand cmd = getCommand(inputString); Logger.debug("Got command of type " + cmd.commandType().toString()); res = runCommand(cmd); Logger.debug("Returning result: " + res); } catch (final CommandTypeException e) { res = new AndroidCommandResult(WDStatus.UNKNOWN_ERROR, e.getMessage()) .toString(); } catch (final JSONException e) { res = new AndroidCommandResult(WDStatus.UNKNOWN_ERROR, "Error running and parsing command").toString(); } out.write(res); out.flush(); } catch (final IOException e) { throw new SocketServerException("Error processing data to/from socket (" + e.toString() + ")"); } }
private AndroidCommand getCommand(final String data) throws JSONException, CommandTypeException { return new AndroidCommand(data); }
private String runCommand(final AndroidCommand cmd) { AndroidCommandResult res; if (cmd.commandType() == AndroidCommandType.SHUTDOWN) { keepListening = false; res = new AndroidCommandResult(WDStatus.SUCCESS, "OK, shutting down"); } else if (cmd.commandType() == AndroidCommandType.ACTION) { try { res = executor.execute(cmd); } ... }
WebElement el = driver.findElement(By.name("Add note"));這里的finElement其實就是一個命令,獲取控件并存放到控件哈希表就是由它對應的CommandHandler實現類Find來完成的。
public AndroidCommandResult execute(final AndroidCommand command) throws JSONException { final Hashtable<String, Object> params = command.params(); // only makes sense on a device final Strategy strategy; try { strategy = Strategy.fromString((String) params.get("strategy")); } catch (final InvalidStrategyException e) { return new AndroidCommandResult(WDStatus.UNKNOWN_COMMAND, e.getMessage()); } ... }appium支持的策略有以下幾種,這其實在我們寫腳本中findElement經常會指定:
public enum Strategy { CLASS_NAME("class name"), CSS_SELECTOR("css selector"), ID("id"), NAME("name"), LINK_TEXT("link text"), PARTIAL_LINK_TEXT("partial link text"), XPATH("xpath"), ACCESSIBILITY_ID("accessibility id"), ANDROID_UIAUTOMATOR("-android uiautomator");
public AndroidCommandResult execute(final AndroidCommand command) throws JSONException { final Hashtable<String, Object> params = command.params(); ... final String contextId = (String) params.get("context"); final String text = (String) params.get("selector"); final boolean multiple = (Boolean) params.get("multiple"); ... }
public AndroidCommandResult execute(final AndroidCommand command) throws JSONException { ... try { Object result = null; List<UiSelector> selectors = getSelectors(strategy, text, multiple); ... } ... }
public AndroidCommandResult execute(final AndroidCommand command) throws JSONException { ... try { Object result = null; List<UiSelector> selectors = getSelectors(strategy, text, multiple); if (!multiple) { for (final UiSelector sel : selectors) { try { Logger.debug("Using: " + sel.toString()); result = fetchElement(sel, contextId); } catch (final ElementNotFoundException ignored) { } if (result != null) { break; } } }else { List<AndroidElement> foundElements = new ArrayList<AndroidElement>(); for (final UiSelector sel : selectors) { // With multiple selectors, we expect that some elements may not // exist. try { Logger.debug("Using: " + sel.toString()); List<AndroidElement> elementsFromSelector = fetchElements(sel, contextId); foundElements.addAll(elementsFromSelector); } catch (final UiObjectNotFoundException ignored) { } } if (strategy == Strategy.ANDROID_UIAUTOMATOR) { foundElements = ElementHelpers.dedupe(foundElements); } result = elementsToJSONArray(foundElements); } ... }而fetchElement最終調用的控件哈希表類的getElements:
private ArrayList<AndroidElement> fetchElements(final UiSelector sel, final String contextId) throws UiObjectNotFoundException { return elements.getElements(sel, contextId); }AndroidElementHash的這個方法我們在前一篇文章《Appium Android Bootstrap源碼分析之控件AndroidElement》已經分析過,我們今天再來溫習一下.
WebElement addNote = driver.findElement(By.name("Add note"));
WebElement el = driver.findElement(By.className("android.widget.ListView")).findElement(By.name("Note1"));以上的腳本會先嘗試找到Note1這個日記的父控件ListView,并把這個控件保存到控件哈希表,然后再根據父控件的哈希表鍵值以及子控件的選擇子找到想要的Note1:
public AndroidElement addElement(final UiObject element) { counter++; final String key = counter.toString(); final AndroidElement el = new AndroidElement(key, element); elements.put(key, el); return el; }
作者 | 自主博客 | 微信 | CSDN |
天地會珠海分舵 | http://techgogogo.com | 服務號:TechGoGoGo 掃描碼:
| 向AI問一下細節 免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。 猜你喜歡最新資訊相關推薦相關標簽AI
助 手
南木林县|
寿光市|
湟中县|
库尔勒市|
永宁县|
格尔木市|
封开县|
新蔡县|
特克斯县|
泰安市|
锦州市|
永胜县|
利津县|
吐鲁番市|
全南县|
鄄城县|
华蓥市|
保德县|
桐城市|
开远市|
丘北县|
双桥区|
沧源|
达尔|
织金县|
宝兴县|
揭东县|
万宁市|
万盛区|
诸暨市|
河东区|
延长县|
兖州市|
西藏|
神农架林区|
牡丹江市|
于田县|
朝阳市|
安阳县|
山阳县|
明溪县|
|