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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • c# 加壳工具推荐[通俗易懂]

    c# 加壳工具推荐[通俗易懂]当前C#.net语言的应用范围越来越广泛,IIS的服务器架构后台代码、桌面应用程序的winform、Unity3d的逻辑脚本都在使用。C#.net具备强大的便捷特性,使得开发成本极低。而作为一款.net语言,也有它让开发者头疼的弊病——非常容易被反编译。市面上的Dnspy,ILspy,de4dot等工具可以非常容易反编译出被混淆保护的C#.net程…

    2022年6月27日
    54
  • 从零和使用mxnet实现softmax分类

    1.softmax从零实现(1797,64)(1797,)(1797,10)epoch:50,loss:[1.9941667],accuracy:0.3550361713967724

    2021年12月30日
    39
  • 防止三极管饱和_稳压二极管稳压时处于什么偏置状态

    防止三极管饱和_稳压二极管稳压时处于什么偏置状态下图为一个分立器件搭建的BUCK电路,但是不明白图中的两个肖特基二极管(D1.D2)的作用是什么防止Q1饱和,但沒深度。

    2025年9月3日
    6
  • C++int转char型并存入char数组「建议收藏」

    C++int转char型并存入char数组「建议收藏」只需在赋值语句后面加上‘0’,如下:inta=10;chara[10];a[1]=a+’0′;

    2022年10月8日
    2
  • j2me开发环境搭建[通俗易懂]

    j2me开发环境搭建[通俗易懂]学习j2me的开发也有半年了,很多东西需要记住并不断实践。 j2me的环境搭建过程。 要准备的东东:1.JDK;2.开发工具Eclipse;3.eclipseMe;4.WTK;   一、下载jdk,并安装,安装好后配置环境变量,假设现在jdk的安装目录是E:/ProgramFiles/Java/jdk1.6.0_10,那么按如下配置环境变量:

    2022年7月11日
    15
  • Raid0、Raid1、Raid5及Raid10的区别

    Raid0、Raid1、Raid5及Raid10的区别一、概况Raid(RedundantArrayofIndepentDisk独立冗余磁盘阵列)技术是加州大学伯克利分校1987年提出,最初是为了组合小的廉价磁盘来代替大的昂贵磁盘,同时希望磁盘失效时不会对数据的访问造成影响而开发的数据保护技。raid就是由多块磁盘构成的冗余阵列,在操作系统下是作为一个独立的大型存储设备出现的。它可以充分发挥出多块硬盘的优势,可以提升硬盘的读写速度,提高硬盘的利用率,日工容错功能确保数据的安全性,易于管理等优点。在任何一块硬盘出现问题的情况下都可以继续工作,不受损

    2022年7月25日
    7

发表回复

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

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