老李推荐:第8章6节《MonkeyRunner源码剖析》MonkeyRunner启动运行过程-启动Monkey 2

有了以下的基本认知之后,我们就可以通过分析代码来阐述Monkey是怎么在用户调用MonkeyRunner.waitForConnection的方法引发的一系列调用过程中启动起来的了,我们先看下MonkeyRunner的这个waitForConnection方法:

 

62   public static MonkeyDevice waitForConnection(PyObject[] args, String[] kws)  

63   {  

64     ArgParser ap = JythonUtils.createArgParser(args, kws);  

65     Preconditions.checkNotNull(ap);  

66     long timeoutMs;  

67     try  

68     {  

69       double timeoutInSecs = JythonUtils.getFloat(ap, 0);  

70       timeoutMs = (timeoutInSecs * 1000.0D);  

71     } catch (PyException e) {  

72       timeoutMs = Long.MAX_VALUE;  

73     }  

74   

75     IChimpDevice device = chimpchat.waitForConnection(timeoutMs, ap.getString(1, ".*"));  

76   

77     MonkeyDevice chimpDevice = new MonkeyDevice(device);  

78     return chimpDevice;  

79   }  

代码8-6-1 MonkeyRunner - waitForConnection

脚本调用到的MonkeyRunner,MonkeyDevice等这些类都是通过JAVA来编写的,而脚本自身却是通过jython(可以被调用JAVA的python)编写的,所以它们之前的参数需要有一个转换的机制,至于它们是怎么转换的不是重点,所以我自己都没有去研究过jython的实现原理,因为这不影响我对MonkeyRunner框架的理解。好,我们继续对上面代码的分析:

  • 75行: 调用chimpchat对象的waitForConnection方法来获得一个AdbChimpDevice的高层抽象设备实例
  • 79-78行: 将上面的AdbChimpDevice实例作为参数传入到MonkeyDevice来构造一个MonkeDevice对象并返回给测试代码,这样测试代码就可以通过操作该MonkeyDevice实例来控制目标设备了

我们重点往下分析ChimpChat的waitForConnection方法,至于MonkeyDevice构造函数,我们在下一章会对整个MonkeyDevice的运行原理进行一个详尽的分析,所以这里就不重复了。

 

 89   public IChimpDevice waitForConnection(long timeoutMs, String deviceId)  

90   {  

91     return this.mBackend.waitForConnection(timeoutMs, deviceId);  

92   }  

98   public IChimpDevice waitForConnection()  

99   {  

100     return this.mBackend.waitForConnection(2147483647L, ".*");  

101   }  

代码8-6-2 ChimpChat - waitForConnection

 

ChimpChat提供了两个waitForConnection方法,其中一个是不带参数的,相当于用户在脚本直接调用MonkeyDevice.waitForConnection();另外一个是带参数long类型超时和设备序列号的。无论是哪个方法ChimpChat都是很简单只有一行,调用的是mBackend的waitForConnection,只是如果用户没有提供参数的话,ChimpChat会默认初始化超时和设备序列号这两个参数,其中设备序列号会被初始化为一个正则表达式”.*”,代表任意一个首先找到的设备。这里的mBackend就是前面分析“启动AndroidDebugBridge”的过程中实例化的AdbBackend对象,所以我们要定位到该类的waitForConnection方法。

 

116   public IChimpDevice waitForConnection(long timeoutMs, String deviceIdRegex)  

117   {  

118     do {  

119       IDevice device = findAttachedDevice(deviceIdRegex);  

120   

121       if ((device != null) && (device.getState() == IDevice.DeviceState.ONLINE)) {  

122         IChimpDevice chimpDevice =   

new AdbChimpDevice(device);  

123         this.devices.add(chimpDevice);  

124         return chimpDevice;  

125       }  

126       try  

127       {  

128         Thread.sleep(200L);  

129       } catch (InterruptedException e) {  

130         LOG.log(Level.SEVERE, "Error sleeping", e);  

131       }  

132       timeoutMs -= 200L;  

133     } while (timeoutMs > 0L);  

134      

135   

136     return null;  

137   }  

代码8-6-3 AdbBackend - waitForConnection

该方法会做一个while循环一直等待找到一个跟用户提供的或者默认的序列号吻合的设备知道超时,如果找到了该设备就会以该设备作为参数去构造一个AdbChimpDevice的实例对象并返回:

  • 133行: 进入while循环,如果在超时时间内还没有连接上目标设备的话就一直循环下去
  • 128和132行: 每次循环如果没有连接上目标设备的话就睡眠0.2秒再进行下次循环
  • 119行: 根据提供的设备序列号(正则表达式)查找目标Device设备,去哪里查找呢?其实就是去DeviceMonitor监控线程对象维护的最新Device设备队列中查找
  • 122行: 找到目标Device设备后,将该设备对象传进去到AdbChimpDevice的构造函数中去实例化AndroidChimpDevice对象并返回。我们往下会看到AdbChimpDevice在实例化的过程中会去实现ChimpManager对象来启动monkey进行通信
原文地址:https://www.cnblogs.com/poptest/p/5092324.html