上一篇文章《UiAutomator源码分析之UiAutomatorBridge框架》中我们把UiAutomatorBridge以及它相关的类进行的描述,往下我们会尝试根据两个实例将这些类给串联起来,我准备做的是用如下两个很有代表性的实例:
- 注入事件
- 获取控件
/* */ UiAutomatorBridge(UiAutomation uiAutomation) /* */ { /* 48 */ this.mUiAutomation = uiAutomation; /* 49 */ this.mInteractionController = new InteractionController(this); /* 50 */ this.mQueryController = new QueryController(this); /* */ }
public boolean pressHome() { 218 Tracer.trace(); 219 waitForIdle(); 220 return getAutomatorBridge().getInteractionController().sendKeyAndWaitForEvent( 221 KeyEvent.KEYCODE_HOME, 0, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED, 222 KEY_PRESS_EVENT_TIMEOUT); 223 }
- 获得UiDevice对象保存的UiAutomatorBridge对象。着两个对象都是在运行时初始化的,不清楚的话请翻看上面提到的文章
- 通过UiAutomatorBridge对象获得上面章节初始化的InteractionController对象
- 调用InteractionController对象的sendKeyAndWaitForEvent方法,里面参数关键是第一个keycode和第二个eventType
- keycode:代表我们要注入的是按下哪个按键的事件,比如这里我们是KEYCODE_HOME
- eventType:代表我们注射了该事件后预期会获得窗口返回来的哪种AccessibilityEvent类型,比如我们这里是TYPE_WINDOW_CONTENT_CHANGE
/* */ public boolean sendKeyAndWaitForEvent(final int keyCode, final int metaState, int eventType, long timeout) /* */ { /* 188 */ Runnable command = new Runnable() /* */ { /* */ public void run() { /* 191 */ long eventTime = SystemClock.uptimeMillis(); /* 192 */ KeyEvent downEvent = new KeyEvent(eventTime, eventTime, 0, keyCode, 0, metaState, -1, 0, 0, 257); /* */ /* */ /* 195 */ if (InteractionController.this.injectEventSync(downEvent)) { /* 196 */ KeyEvent upEvent = new KeyEvent(eventTime, eventTime, 1, keyCode, 0, metaState, -1, 0, 0, 257); /* */ /* */ /* 199 */ InteractionController.this.injectEventSync(upEvent); /* */ } /* */ /* */ } /* 203 */ }; /* 204 */ return runAndWaitForEvents(command, new WaitForAnyEventPredicate(eventType), timeout) != null; /* */ }代码中创建了一个Runnable的线程,线程里面run重写方法要做的事情就是去做注入事件的事情,那么为什么我们不直接去调用事件而需要创建一个线程了,这是因为我们在注入完事件之后还要去等待我们上面定义的预期的eventType是否有出现来判断我们的事件注入究竟是否成功,这个就是204行runAndWaitForEvents做的事情。但我们这里还是先看下线程中是如何注入事件的:
/* */ private boolean injectEventSync(InputEvent event) { /* 655 */ return this.mUiAutomatorBridge.injectInputEvent(event, true); /* */ }再跟踪到UiAutomatorBridge对象:
/* */ public boolean injectInputEvent(InputEvent event, boolean sync) { /* 70 */ return this.mUiAutomation.injectInputEvent(event, sync); /* */ }可以看到最终还是通过UiAutomation来注入事件的,和我们的预期是一致的。
/* */ private AccessibilityEvent runAndWaitForEvents(Runnable command, UiAutomation.AccessibilityEventFilter filter, long timeout) /* */ { /* */ try /* */ { /* 161 */ return this.mUiAutomatorBridge.executeCommandAndWaitForAccessibilityEvent(command, filter, timeout); /* */ } /* */ catch (TimeoutException e) { /* 164 */ Log.w(LOG_TAG, "runAndwaitForEvent timedout waiting for events"); /* 165 */ return null; /* */ } catch (Exception e) { /* 167 */ Log.e(LOG_TAG, "exception from executeCommandAndWaitForAccessibilityEvent", e); } /* 168 */ return null; /* */ }代码又跳到了UiAutomatorBridge这个类
/* */ public AccessibilityEvent executeCommandAndWaitForAccessibilityEvent(Runnable command, UiAutomation.AccessibilityEventFilter filter, long timeoutMillis) throws TimeoutException /* */ { /* 104 */ return this.mUiAutomation.executeAndWaitForEvent(command, filter, timeoutMillis); /* */ }最终把要执行的runnable执行注入事件的线程command和我们预期事件发生后返回来的窗口事件filter以及超时timeoutMillis传进去,UiAutomation就会和AccessibilityService进行交互以注入事件并且等待预期AccessibilityEvent发生或者超时返回。至于UiAutomation是如何和AccessibilityService交互的,这就超出了这个系列文章的范畴了。也许今后有充裕的时间的话我们再来深入去了解分析它。
作者 | 自主博客 | 微信 | CSDN |
天地会珠海分舵 | | 服务号:TechGoGoGo 扫描码: |
![]()
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
举报文章 请选择举报类型
内容侵权
涉嫌营销
内容抄袭
违法信息
其他
补充说明 0/200 上传截图 格式支持JPEG/PNG/JPG,图片不超过1.9M 如有误判或任何疑问,可联系 「小助手微信:cto51cto」申诉及反馈。
我知道了
|