首先進入點是 UiAutomatorViewer
重要的後端邏輯處裡類別有 DebugBridge、UiAutomatorHelper、UiAutomatorModel ,以及 Action 系列 (在 com.android.uiautomator.actions package 下),而前端操作的邏輯部分為 UiAutomatorView,其中註冊多個 Listener 與 UiAutomatorModel 做溝通
UiAutomatorViewer 在最初開始連結 adb 後,建立基本的操作介面
DebugBridge.init(); ToolBarManager toolBarManager = new ToolBarManager(SWT.FLAT); toolBarManager.add(new OpenFilesAction(this)); toolBarManager.add(new ScreenshotAction(this,false)); toolBarManager.add(new ScreenshotAction(this,true)); toolBarManager.add(new SaveScreenShotAction(this)); ToolBar tb = toolBarManager.createControl(c); tb.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); mUiAutomatorView = new UiAutomatorView(c, SWT.BORDER); mUiAutomatorView.setLayoutData(new GridData(GridData.FILL_BOTH));
這邊以 Screenshot Action 做範例解說,當 ScreenshotAction 被觸發後,會執行 Action 介面中定義的 run 方法,可以看到下方的程式中,透過 UiAutomatorHelper 進行畫面擷取,並且從回傳的拿出資訊透過 setModel 設回給 UiAutomatorViewer,其中 model 為給前端使用的邏輯模型,而 uiHierarchy 為模型的 XML 檔案, screenshot 則為螢幕截圖。
if (!DebugBridge.isInitialized()) { MessageDialog.openError(mViewer.getShell(), "Error obtaining Device Screenshot", "Unable to connect to adb. Check if adb is installed correctly."); return; } final IDevice device = pickDevice(); if (device == null) { return; } ProgressMonitorDialog dialog = new ProgressMonitorDialog(mViewer.getShell()); try { dialog.run(true, false, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { UiAutomatorResult result = null; try { result = UiAutomatorHelper.takeSnapshot(device, monitor, mCompressed); } catch (UiAutomatorException e) { monitor.done(); showError(e.getMessage(), e); return; } mViewer.setModel(result.model, result.uiHierarchy, result.screenshot); monitor.done(); } }); } catch (Exception e) { showError("Unexpected error while obtaining UI hierarchy", e); }
深入 UiAutomatorHelper 後會發現一些與 Android 系統的互動,在 getUiHierarchyFile() 這個方法中,可以直接取用 IDevice 類別執行一些 shell command,或是擷取畫面、取用 SyncService 來 pull/push 檔案...等等的操作,這就是引入 ddmlib 的目的。
device.executeShellCommand(command, new CollectingOutputReceiver(commandCompleteLatch)); device.getSyncService().pullFile(UIDUMP_DEVICE_PATH, dst.getAbsolutePath(), SyncService.getNullProgressMonitor()); try { rawImage = device.getScreenshot(); } catch (Exception e) { String msg = "Error taking device screenshot: " + e.getMessage(); throw new UiAutomatorException(msg, e); }
No comments:
Post a Comment