UiAutomator喷射事件的源代码分析

UiAutomator喷射事件的源代码分析

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

上一篇文章《UiAutomator源代码分析之UiAutomatorBridge框架》中我们把UiAutomatorBridge以及它相关的类进行的描写叙述,往下我们会尝试依据两个实例将这些类给串联起来,我准备做的是用例如以下两个非常有代表性的实例:

  • 注入事件
  • 获取控件
这一篇文章我们会通过分析UiDevice的pressHome这种方法来分析UiAutomator是怎样注入事件的,下一篇文章会描写叙述怎样获取控件,敬请期待。


1. UiObject.pressHome顺序图

首先我们看一下我手画的非规范的顺序图,从中我们能够看到pressHome这个动作到底须要和多少个类进行交互,以及它们是怎么交互的。

UiAutomator喷射事件的源代码分析

2.这些类是什么时候初始化的

在我们编写測试用例脚本的时候我们不会对以上全部的类进行初始化,包含UiObject对象都是通过直接在脚本中调用父类UiAutomationTestCase的getUiDevice()这种方法来获得的。事实上这些都是在uiautomator执行时由RunTestCommand类的start()这种方法进行初始化的,详细请看《
UIAutomator源代码分析之启动和执行》的 3.6章节“初始化UiDevice和UiAutomationBridge“。这里就不做累述。我们这里会看下在初始化UiAutomatorBridge的时候是怎样把QuneryControoler和InteractionController一并初始化了的。详细请看UiAutomatorBridge的构造函数:
/*     */   UiAutomatorBridge(UiAutomation uiAutomation)
/*     */   {
/*  48 */     this.mUiAutomation = uiAutomation;
/*  49 */     this.mInteractionController = new InteractionController(this);
/*  50 */     this.mQueryController = new QueryController(this);
/*     */   }

3. 代码跟踪

首先看UiDevice的pressHome方法:
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    }

220行:
  • 获得UiDevice对象保存的UiAutomatorBridge对象。着两个对象都是在执行时初始化的,不清楚的话请翻看上面提到的文章
  • 通过UiAutomatorBridge对象获得上面章节初始化的InteractionController对象
  • 调用InteractionController对象的sendKeyAndWaitForEvent方法。里面參数关键是第一个keycode和第二个eventType
    • keycode:代表我们要注入的是按下哪个按键的事件,比方这里我们是KEYCODE_HOME
    • eventType:代表我们注射了该事件后预期会获得窗体返回来的哪种AccessibilityEvent类型,比方我们这里是TYPE_WINDOW_CONTENT_CHANGE

进入InteractionController类的sendKeyAndWaitForEvent:

/*     */   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来注入事件的,和我们的预期是一致的。

我们继续看InteractionController中真正运行注入事件线程的runAndWaitForEvents方法:
/*     */   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

天地会珠海分舵

http://techgogogo.com


服务号:TechGoGoGo

扫描码:

UiAutomator喷射事件的源代码分析

http://blog.csdn.net/zhubaitian


版权声明:本文博客原创文章。博客,未经同意,不得转载。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/117541.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Element.clientWidth

    Element.clientWidthElement.clientWidth

    2022年7月22日
    6
  • 小米wifidhcp服务器没有响应,小米路由器dhcp服务没有响应怎么解决[通俗易懂]

    小米wifidhcp服务器没有响应,小米路由器dhcp服务没有响应怎么解决[通俗易懂]摘要腾兴网为您分享:苹果手机,番茄小说,闲聊app,蚂蚁深林,微博等知识经验教程,欢迎大家关注腾兴网。小米路由器是很多家庭的选择,使用中也会碰到一些问题,很多小伙伴碰到的问题是dhcp服务没有响应,怎么解决呢,小编来为大家介绍。小米路由器dhcp服务没有响应怎么解决本地服务中的wiredautoconfig服务没有设为自动。解决方法:1、运行->services.msc2、找到wire…

    2022年6月27日
    375
  • Netty in action—Netty中的ByteBuf[通俗易懂]

    Netty in action—Netty中的ByteBuf[通俗易懂]正如之前所说,网络传输的基本单位是字节。JavaNIO提供了ByteBuffer作为它的容器,但是这个类使用起来比较复杂和麻烦。Netty提供了一个更好的实现:ByteBuf。ByteBuf的APINetty为数据处理提供的API通过抽象类ByteBuf和接口ByteBufHolder暴露出来。下面列出ByteBufAPI的优点:可扩展到用户定义的buffer类型中通过内置的复合buf

    2022年9月17日
    0
  • java脑裂_zookeeper脑裂

    java脑裂_zookeeper脑裂出现:在搭建hadoop的HA集群环境后,由于两个namenode的状态不一,当active的namenode由于网络等原因出现假死状态,standby接收不到active的心跳,因此判断active的namenode宕机,但实际上active并没有死亡。此时standby的namenode就会切换成active的状态,保证服务能够正常使用。若原来的namenode复活,此时在整个集群中就出现2个…

    2022年10月24日
    0
  • Java实现扫雷小游戏【优化版】

    Java实现扫雷小游戏【优化版】游戏的设计类似windows扫雷,用户在图形化用户界面内利用鼠标监听事件标记雷区,左上角表示剩余雷的数量,右上角动态显示使用的时间。用户可选择中间组件按钮重新游戏。在使用Java编写扫雷小游戏时遇到了很多问题,在解决问题时,确实对java的面向对象编程有了更加深入的理解。虽然GUI现在并没有很大的市场,甚至好多初学者已经放弃了学习GUI,但是利用GUI编程的过程对于培养编程兴趣,深入理解Java编程有很大的作用。

    2022年7月15日
    13
  • 遗传算法python(含例程代码与详解)「建议收藏」

    遗传算法python(含例程代码与详解)「建议收藏」遗传算法1.算法简介2.算法流程3.算法示例4.算法实现5.算法应用

    2022年9月13日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号