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

时间:2022-02-11 08:12:50

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

 

poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标。如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-84505200。

在第2节中我们看到了MonkeySourceNetwork是如何从Socket中获取MonkeyRunner发送过来的命令字串的,但是最后如何将它翻译成事件的代码我们还没有进行分析,因为在那之前我们还没有了解命令翻译类的相关知识。那么经过第3小节对命令翻译类的学习后,我们就可以继续往下分析MonkeySourceNetwork的getNextEvent中是如何翻译命令字串的了。

我们回看下第2小节,最后在获得命令字串之后调用的是MonkeySourceNetwork类的translateCommand方法:

653   private void translateCommand(String commandLine)

654   {

655     Log.d("MonkeyStub", "translateCommand: " + commandLine);

656     List<String> parts = commandLineSplit(commandLine);

657     if (parts.size() > 0) {

658       MonkeyCommand command = (MonkeyCommand)COMMAND_MAP.get(parts.get(0));

659       if (command != null) {

660         MonkeyCommandReturn ret = command.translateCommand(parts, this.commandQueue);

661         handleReturn(ret);

662       }

663     }

664   }

代码6-4-1 MonkeySourceNetwork - translateCommand

  • 653行: 传进来的参数就是一个命令字串。 通过” 表3-3-1 命令字串和对应的命令翻译类参照表”我们可以看到一个命令字串如果带有参数的话它的形式可能是这样的“type line”
  • 656行: 为了方便使用该命令,通过调用commandLineSplit方法把命令字串转换成一个列表分别把命令,每个参数都独立保存在列表里面。这个方法无非就是根据空格等把命令和参数分解出来,所以就不跟踪进去分析了
  • 658行: 将命令和参数分离分别存放到列表后,根据命令去” 代码3-1-2 MonkeySourceNetwork - COMMAND_MAP”所描述的COMMAND_MAP去查找对应的命令翻译类实例。以上面的”touch x y”命令字串为例,就是根据”type”去COMMAND_MAP中查找,对应的将是这一行:

461         COMMAND_MAP.put("type", new TypeCommand());

也就是说找到的对应的命令翻译类是TypeCommand

  • 660行:调用命令翻译类的translateCommand方法来翻译命令列表,注意这里传进去的参数除了命令字串列表之外还有一个MonkeySourceNetwork的成员变量commandQueue,也就是我们一直说的命令队列,传进去的目的就是在解析命令的过程中如果需要创建一个对应事件实例的话,那么创建完后就直接往这个同一个的命令队列里面丢就行了

那么往下我们就看下上面的TypeCommand的translateCommand方法是如何实现的:

294         public MonkeyCommandReturn translateCommand(List<String> command,

295             CommandQueue queue) {

296             if (command.size() == 2) {

297                 String str = command.get(1);

298

299                 char[] chars = str.toString().toCharArray();

300

301                 // Convert the string to an array of KeyEvent's for

302                 // the built in keymap.

303                 KeyCharacterMap keyCharacterMap = KeyCharacterMap.

304                         load(KeyCharacterMap.VIRTUAL_KEYBOARD);

305                 KeyEvent[] events = keyCharacterMap.getEvents(chars);

306

307                 // enqueue all the events we just got.

308                 for (KeyEvent event : events) {

309                     queue.enqueueEvent(new MonkeyKeyEvent(event));

310                 }

311                 return OK;

312             }

313             return EARG;

314         }

代码6-4-2 TypeCommand - translateCommand

  • 299-299行: 在命令字串列表中取得type命令的参数line,也就是一大串需要输入的字符串了。然后把该字符串每个字符拆散开来建立一个字符数组chars,因为下面获得每个字符对应的系统按键事件KeyEvent的的方法接受的参数就是字符数组
  • 304-305行: KeyCharacterMap的getEvents方法官方的解析是用来根据提供的字符数据流生成一个对应按键事件数组,所以这里的意义就是为输入字串的每一个字符都产生一个按键事件,然后组织成一个按键事件队列返回给events变量。这里需要提下的是KeyEvent在Android系统中代表一个按键事件,它内部拥有的每个按键对应的值以及按键对应的Action如ACTION_DOWN/ACTION_UP等等的定义
  • 308-309行: 根据按键事件创建一个MonkeyKeyEvent实例,并把该事件放到传进来的命令队列里面等待执行

这一小节结合TypeCommand这个命令翻译类我们看到了MonkeySourceNetwork从网络获得一个字串命令后是如何通过调用自身的translateCommand方法来解析出里面的命令和参数,然后根据命令来查找COMMAND_MAP来获得对应的命令翻译类实例,最后通过命令翻译类的translateCommand来根据命令字串创建对应的MonkeyEvent的并把它加入到命令队列中。

在下一小节我们就去学习下这个MonkeyEvent和命令队列的相关知识。