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)
上一篇 2022年1月4日 上午9:00
下一篇 2022年1月4日 上午10:00


相关推荐

  • jediscluster工具类_cannot get jedis connection

    jediscluster工具类_cannot get jedis connectionRedis集群是没法执行批量操作命令的,如mget,pipeline等。这是因为redis将集群划分为16383个哈希槽,不同的key会划分到不同的槽中。原生JedisCluster对批量操作的限制是mgetmset必须在一个槽;四种批量优化的方法1、串行mget在for循环中执行一条条的get; 需要n次网络时间;2、串行IO在客户端对所有key做CR…

    2026年4月13日
    4
  • ARM Linux ELF加壳方案

    ARM Linux ELF加壳方案随着移动应用和IoT设备的普及,大量的硬件抛弃了传统的x86架构,选择使用能耗低、性价比高的ARM芯片,ARM指令级渐渐成为主流,但随之而来的,是愈发严峻的安全问题。早期的加壳产品主要利用压缩加密技术对文件进行整体性保护,但随着逆向技术的提升,整体性的文件保护方案已经被攻克,于是加壳产品引入虚拟机概念,可以实现函数级的代码控制流保护,加密的颗粒度更加细致,激活成功教程难度呈几何级增加。压缩加密技术原理类似桌面应用的「压缩壳」,将SO文件中的代码段压缩或加密,在入口函数中解密再执行。这种保护方式可

    2022年10月11日
    3
  • top命令输出解释以及load average 详解及排查思路

    top命令输出解释以及load average 详解及排查思路昨天nagios报警warning,没来得及留下报警截图,nagios值设定的值是当1分钟多于15个进程等待,5分钟多于10个,15分钟多于5个则为warning状态当1分钟多于30个进程等待,5分钟多于25个,15分钟多于20个则为critical状态————————————————————-

    2022年7月17日
    24
  • Monkey测试详解「建议收藏」

    Monkey测试详解「建议收藏」概念:monkeytest,也有人叫做搞怪测试,一般指用毫无规律的指令或操作去测试被测系统,观察被测系统的稳定性和容错性。这种测试方式在产品周期中的早期阶段会找到很多很好的bug,为用户节省不少的时

    2022年7月3日
    39
  • 典型相关分析原理(CCA)

    典型相关分析原理(CCA)CCA 典型相关分析 canonicalcor 利用综合变量对之间的相关关系来反映两组指标之间的整体相关性的多元统计分析方法 它的基本原理是 为了从总体上把握两组指标之间的相关关系 分别在两组变量中提取有代表性的两个综合变量 U1 和 V1 分别为两个变量组中各变量的线性组合 利用这两个综合变量之间的相关关系来反映两组指标之间的整体相关性 Canonical

    2026年3月18日
    2
  • 微信小程序页面收录推送

    微信小程序页面收录推送

    2021年11月11日
    43

发表回复

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

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