老李推荐:第14章7节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-装备ViewServer-获取版本号 2

代码先是发送”LIST”命令到ViewServer列出所有的打开的窗口,然后把每个窗口都保存起来。342行起按照源码的注释解析就是说:从协议版本3以后开始加入了窗口自动更新的功能,但是在此之前,如果用户想要获得一个获得焦点的窗口的话,需要通过显式的创建一个特殊的哈希值为-1的Window实例来完成。怎么知道它的哈希值是-1呢?请看Window类的getfocusedWindow方法:

return new Window(device, "<Focused Window>", -1);

}

代码14-7-2 Window-getFocusedWindow方法

然后再看其调用的Window的构造函数和对应的传入参数:

public Window(IHvDevice device, String title, int hashCode)

{

this.mHvDevice = device;

this.mTitle = title;

this.mHashCode = hashCode;

this.mClient = null;

}

代码14-7-3 Window-构造函数

最终创建的就是一个标题是”<Focused Window>”,哈希值是-1的Window实例。

通过以上的示例,主要是想说明,ViewServer的版本会影响到代码的不同处理方式,所以我们还是很有必要去看下这些版本信息是如何获得和保存起来的。

好,那么我们继续分析HierarchyViewer在装备ViewServer时的方法setupViewServer最后一个调用方法DeviceBridge.loadViewServerInfo,这个方法有点长,我们对它分开来分析,先看第1部分:

260     public static ViewServerInfo loadViewServerInfo(IDevice device) {

261         int server = -1;

262         int protocol = -1;

263         DeviceConnection connection = null;

264         try {

265             connection = new DeviceConnection(device);

266             connection.sendCommand("SERVER"); //$NON-NLS-1$

267             String line = connection.getInputStream().readLine();

268             if (line != null) {

269                 server = Integer.parseInt(line);

270             }

271         } catch (Exception e) {

272             Log.e(TAG, "Unable to get view server version from device " + device);

273         } finally {

274             if (connection != null) {

275                 connection.close();

276             }

277         }

...

}

代码14-7-4 DeviceBridge - loadViewServerInfo获取ViewServer版本

265行显示的代码的第一个重要的部分是去建立一个DeviceConnection的连接,传入的参数依然是ddmlib的Device类的实例:

36     public DeviceConnection(IDevice device) throws IOException {

37         mSocketChannel = SocketChannel.open();

38         int port = DeviceBridge.getDeviceLocalPort(device);

39         if (port == -1) {

40             throw new IOException();

41         }

42         mSocketChannel.connect(new InetSocketAddress("127.0.0.1", port)); //$NON-NLS-1$

43         mSocketChannel.socket().setSoTimeout(40000);

44     }

代码14-7-5 DeviceConnection - 构造函数

整个代码所做的事情很清晰明了:

  • 创建一个SocketChannel
  • 根据Device实例获得对应的ViewServer本地转发端口号
  • 把SocketChannel连接上本地的ViewServer转发端口

这里值得提一提的倒是如何根据Device实例获得ViewServer本地转发端口号这个事情。大家还记得第4小节我们说端口转发的时候,最终Device实例和对应的本地转发端口号是保存在DeviceBridge的一个名叫sDevicePortMap的静态成员HashMap里面的。所以这里所做的事情就是去到这个HashMap里面以Device实例为键把端口号这个值取出来而已:

155     public static int getDeviceLocalPort(IDevice device) {

156         synchronized (sDevicePortMap) {

157             Integer port = sDevicePortMap.get(device);

158             if (port != null) {

159                 return port;

160             }

161             Log.e(TAG, "Missing forwarded port for " + device.getSerialNumber());

162             return -1;

163         }

164     }

代码14-7-6 DeviceBridge - getDeviceLocalPort

时间: 2024-12-14 18:05:06

老李推荐:第14章7节《MonkeyRunner源码剖析》 HierarchyViewer实现原理-装备ViewServer-获取版本号 2的相关文章

老李推荐:第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是一个接口,

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

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

第5章2节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动流程概览(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 每个应用都会有一个入口方法来供操作系统调用执行,Monkey这个应用的入口方法就是在Monkey.java这个类里面的,也就是说Monkey.java就是整个Monkey应用的入口类. Monkey作为一个命令行应用,

第6章1节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览

在上一章中我们有简要的介绍了事件源是怎么一回事,但是并没有进行详细的描述.那么往下的这几个小节我们就需要把这方面的知识给补充完整. 这一节我们先主要围绕MonkeySourceNetwork这个事件源来学习事件源的框架结构.首先,要理解事件源,必须先搞清楚几个问题: 事件从哪里来? Monkey的事件来源有多个方面,但是作为MonkeyRunner框架的一部分,它的事件来源主要是来自MonkeyRunner通过网络Socket(USB/TCP协议)发送过来的命令字串.MonkeySourceNe

第6章2节《MonkeyRunner源码剖析》Monkey原理分析-事件源-事件源概览-获取命令字串

从上一节的描述可以知道,MonkeyRunner发送给Monkey的命令是以字符串的形式交互的,那么事件处理的第一步当然是先去获得MonkeyRunner发送过来的字串命令了. 在事件源MonkeySourceNetwork初始化的时候构造函数会创建一个ServerSocket来监听来自客户端的链接和数据,但这个时候客户端并不能真正实现和服务端通信,因为该ServerSocket尚处于阻塞状态.既然ServerSocket是MonkeySourceNetwork的构造函数创建的,那么建立通信的又

第5章3节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 启动脚本(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 本节我们先看下Monkey是怎么启动起来的.在今后分析到MonkeyRunner的原理的时候我们会看到客户端是通过ADB往Android目标测试机器发送一个"monkey -port 12345"的

第5章4节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 命令行参数解析(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 设置好Monkey的CLASSPATH环境变量以指定"/system/framework /framework/monkey.jar"后,/system/bin/monkey这个shell脚本就会通

第5章6节《MonkeyRunner源码剖析》Monkey原理分析-启动运行: 初始化事件源(原创)

天地会珠海分舵注:本来这一系列是准备出一本书的,详情请见早前博文"寻求合作伙伴编写<深入理解 MonkeyRunner>书籍".但因为诸多原因,没有如愿.所以这里把草稿分享出来,所以错误在所难免.有需要的就参考下吧,转发的话还请保留每篇文章结尾的出处等信息. 事件源代表要注入系统的命令事件数据是从哪里过来的.这一小节我们不会对事件源的实现进行深入的分析,因为下一章会做这个事情.这里大家对事件源有个基本概念就足够了. 对Monkey来说,事件的来源可以有多个地方,比如我们用它

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

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