第6章7节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-注入按键事件实例

在事件生成并放入到命令队列后,Monkey类的runMonkeyCycles就会去调用相应事件源的getNextEvent来获的事件来执行事件注入,那么这一小节我们通过MonkeyKeyEvent这个事件的注入方法来看下事件注入过程是怎么样的。

往系统注入按键事件最终是通过调用InputManager提供的方法来实现的,在Android系统中,按键事件是由InputManager来收集并由WindowManagerService服务来分发给各个Activity处理的,这个系统服务。它是用于管理整个系统的输入部分,包括键盘、鼠标、触摸屏等等。所以MonkeyKeyEvent往系统注入按键事件要做的事情就是要准备好InputManager注入事件的方法 injectInputEvent所需要的参数KeyEvent实例。而KeyEvent实例或者用于构建KeyEvent实例所需要用到的参数在MonkeyKeyEvent的成员变量中都有定义:

 27 public class MonkeyKeyEvent
 28   extends MonkeyEvent
 29 {
 30   private int mDeviceId;
 31   private long mEventTime;
 32   private long mDownTime;
 33   private int mAction;
 34   private int mKeyCode;
 35   private int mScanCode;
 36   private int mMetaState;
 37   private int mRepeatCount;
 38   private KeyEvent mKeyEvent;

代码6-7-1 MonkeyKeyEvent 成员变量

以下我们先简要描述下各个成员变量的意义,其中大部分变量都是用于构建KeyEvent用的:

  • mDeviceId: 产生该事件的设备ID
  • mEventTime:事件发生事件
  • mDownTime: 按键按下时间,用来判断是点击还是长按
  • mAction: 按键动作,如ACTION_DOWN,ACTION_UP或ACTION_MULTIPLE
  • mKeyCode: 按键键码
  • mScanCode: 按键硬件扫描码
  • mMetatState: 指示哪个元键(如ALT这种控制类键)在按下状态
  • mRepeatCount:代表按键键码的重复次数
  • mKeyEvent: 系统按键事件。以上的变量在按键事件KeyEvent类中都有对应的变量

MonkeyKeyEvent支持多个构造函数,其中有两个比较重要。调用者可以传入除mKeyEvent外的所有其他变量进行初始化,也可以直接传入一个KeyEvent实例进行初始化,因为刚才说过了KeyEvent里面包含了所有其他变量。我们往下看下者两个构造函数:

46   public MonkeyKeyEvent(long downTime, long eventTime, int action, int keyCode, int repeatCount, int metaState, int device, int scan    Code)
 47   {
 48     super(0);
 49     this.mDownTime = downTime;
 50     this.mEventTime = eventTime;
 51     this.mAction = action;
 52     this.mKeyCode = keyCode;
 53     this.mRepeatCount = repeatCount;
 54     this.mMetaState = metaState;
 55     this.mDeviceId = device;
 56     this.mScanCode = scanCode;
 57   }
 58
 59   public MonkeyKeyEvent(KeyEvent e) {
 60     super(0);
 61     this.mKeyEvent = e;
 62   }

代码6-7-2 MonkeyKeyEvent构造函数

在准备好注入事件所需要的提供的信息后,下一步就需要去看下MonkeyKeyEvent的注入事件这个方法是怎么实现的了:

 99     @Override
100     public int injectEvent(IWindowManager iwm, IActivityManager iam, int verbose) {
101         if (verbose > 1) {
102             String note;
103             if (mAction == KeyEvent.ACTION_UP) {
104                 note = "ACTION_UP";
105             } else {
106                 note = "ACTION_DOWN";
107             }
108
109             try {
110                 System.out.println(":Sending Key (" + note + "): "
111                         + mKeyCode + "    // "
112                         + MonkeySourceRandom.getKeyName(mKeyCode));
113             } catch (ArrayIndexOutOfBoundsException e) {
114                 System.out.println(":Sending Key (" + note + "): "
115                         + mKeyCode + "    // Unknown key event");
116             }
117         }
118
119         KeyEvent keyEvent = mKeyEvent;
120         if (keyEvent == null) {
121             long eventTime = mEventTime;
122             if (eventTime <= 0) {
123                 eventTime = SystemClock.uptimeMillis();
124             }
125             long downTime = mDownTime;
126             if (downTime <= 0) {
127                 downTime = eventTime;
128             }
129             keyEvent = new KeyEvent(downTime, eventTime, mAction, mKeyCode,
130                     mRepeatCount, mMetaState, mDeviceId, mScanCode,
131                     KeyEvent.FLAG_FROM_SYSTEM, InputDevice.SOURCE_KEYBOARD);
132         }
133         if (!InputManager.getInstance().injectInputEvent(keyEvent,
134             InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_RESULT)) {
135             return MonkeyEvent.INJECT_FAIL;
136         }
137         return MonkeyEvent.INJECT_SUCCESS;
138     }
139 }

代码6-7-3 MonkeyKeyEvent - injectEvent

  • 103-107行: 确定这个按键事件是按下事件还起弹起事件
  • 119-132行: 如果MonkeyKeyEvent是用KeyEvent构造的,那么直接使用这个KeyEvent,如果不是用KeyEvent而是用另外一个构造函数构造的,那么用该构造函数传进来的所有参数来构造一个KeyEvent来使用
  • 133-134行: 通过调用InputManager来把按键keyEvent注入到系统窗口里面来实现注入一个按键事件的操作。

注:更多文章请关注公众号:techgogogo或个人博客http://techgogogo.com。当然,也非常欢迎您直接微信(zhubaitian1)勾搭。本文由天地会珠海分舵原创。转载请自觉,是否投诉维权看心情。

时间: 2024-10-13 22:16:10

第6章7节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-注入按键事件实例的相关文章

第5章5节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 获取系统服务引用(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 上一节我们描述了monkey的命令处理入口函数run是如何调用optionProcess方法来解析命令行参数的.启动参数主要时去指导Monkey时怎么运行起来的,但Monkey作为MonkeyRunner框架的一部分,

老李推荐: 第8章4节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动AndroidDebugBridge 1

老李推荐: 第8章4节<MonkeyRunner源码剖析>MonkeyRunner启动运行过程-启动AndroidDebugBridge 上一节我们看到在启动AndroidDebugBridge的过程中会调用其start方法,而该方法会做2个主要的事情: 715行startAdb:开启AndroidDebugBridge 722-723行:初始化android设备监控并启动DeviceMonitor设备监控线程. 其中第一点我们上一小节已经做了详尽分析了,那么我们往下就去分析下第2点. Dev

老李推荐:第6章5节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-事件

老李推荐:第6章5节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-事件 从网络过来的命令字串需要解析翻译出来,有些命令会在翻译好后直接执行然后返回,但有一大部分命令在翻译后需要转换成对应的事件,然后放入到命令队列里面等待执行.Monkey在取出一个事件执行的时候主要是执行其injectEvent方法来注入事件,而注入事件根据是否需要往系统注入事件分为两种: 需要通过系统服务往系统注入事件:如MonkeyKeyEvent事件会通过系统的InputManager往系

老李推荐:第6章3节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令翻译类

老李推荐:第6章3节<MonkeyRunner源码剖析>Monkey原理分析-事件源-事件源概览-命令翻译类 每个来自网络的字串命令都需要进行解析执行,只是有些是在解析的过程中直接执行了事,而有些是需要在解析后创建相应的事件类实例并添加到命令队列里面排队执行.负责这部分工作的就是命令翻译类.那么我们往下还是继续在MonkeySourceNetwork这个范畴中MonkeyCommand类是怎么一回事: 图6-3-1 MonkeyCommand族谱 图中间的MonkeyCommand是一个接口,

老李推荐: 第1章1节《MonkeyRunner源码剖析》概述:前言

老李推荐: 第1章1节<MonkeyRunner源码剖析>概述:前言 前言 相信大家做过安卓移动平台UI自动化开发的必然会用过,至少听过MonkeyRunner这个名字.MonkeyRunner是一个针对安卓平台的UI自动化测试框架,这个框架的其中一个但绝不是唯一的优点是支持用当今非常流行和高效的Python语言来进行脚本开发.同时,它相比Instrumentation框架或者基于Instrumentation的自动化测试框架最大的优点之一就是可以跨应用测试. 这本书不会有什么序言或者致谢什么

boost.asio源码剖析(三) ---- 流程分析

* 常见流程分析之一(Tcp异步连接) 我们用一个简单的demo分析Tcp异步连接的流程: 1 #include <iostream> 2 #include <boost/asio.hpp> 3 4 // 异步连接回调函数 5 void on_connect(boost::system::error_code ec) 6 { 7 if (ec) // 连接失败, 输出错误码 8 std::cout << "async connect error:"

第5章7节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 循环获取并执行事件 - runMonkeyCycles(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. Monkey启动之后需要在整个MonkeyRunner的测试生命周期中提供服务,也就是说,一旦我们调用monkeyrunner命令来执行指定的测试脚本的时候,只要monkeyrunner还没有退出,那么Monkey就会

第1章3节《MonkeyRunner源码剖析》概述: 架构(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 原理架构 MonkeyRunner使用起来非常的简单,只需要导入以下几个类基本上就能满足测试脚本编写的需求,比如: monkeyrunner.jar库的MonkeyRunner monkeyrunner.jar库的Mo

第6章3节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-命令翻译类

每个来自网络的字串命令都需要进行解析执行,只是有些是在解析的过程中直接执行了事,而有些是需要在解析后创建相应的事件类实例并添加到命令队列里面排队执行.负责这部分工作的就是命令翻译类.那么我们往下还是继续在MonkeySourceNetwork这个范畴中MonkeyCommand类是怎么一回事: 图6-3-1 MonkeyCommand族谱 图中间的MonkeyCommand是一个接口,主要定义了translateCommand这个方法,它接收的参数是一个字串命令以及参数的列表以及命令队列,所有实