首先進入點是 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