测试上遇到的困扰
测试一直是软件开发中重要的一环,在“软件测试杂谈”中,提到了一些测试相关的概念,更多深入的文章请参阅简书。Android 的开发里,AVD 则是测试不可或缺的一部份。透过 AVD 可以不用准备大量的实体设备,就可以让所开发的 App 在不同的环境中检视其运作的情况。
使用 Notebook 进行 Android 开发的人,通常都会遇到一个困扰是:Notebook 的磁盘空间大多不是很充裕。在开发 Android App 时,常常要使用多个 AVD,来测试 App 在不同的环境下都可以正常地运作,毕竟 Android 的平台碎片化已经是一种特色了。
然而在空间有限的情况下,建一个 AVD 就要上 Giga 的空间,这还不包含不同版本的 Image 文件。每一个版本还有分 32bit、64 bit,有 Google API、没有 Google API,再加上 TV 和 Wear 这二种设备种类。林林总总的 Image 加起来,配上 AVD 可能要产生出不同画面尺寸的组合,对于有限的磁盘空间来说更是捉襟见肘。
如果要扩充 Notebook 的存储空间,除了价格上的因素以外,往往还会受限于 Notebook 硬体架构上的局限性。就这个缺点来说,PC 相对是一个比较好的选项。但是改为使用 PC 开发,就会失去了原本 Notebook 具备的机动性。想要二者优点兼具,替代性的选项是在二台机器间进行 Source Code 同步,需要机动性就在 Notebook 上开发,需要空间时就转移到 PC 上开发。
这个选项对大型公司而言,是一个再直接不过的选项,因为公司内通常都会有一定程度的版本控管系统在协助,文件移转的负担比较小,甚至更豪华的有专用 Lab 环境。反过来说,不在这样体制内的人,只能苦命地手动将 Source Code 反覆传来传去,费工又容易出错。
对于这样的族群来说,需要将选项的内容再进化,也就是开发仍在 Notebook 上保持机动性,同时选择关键的环境来建立 AVD,做基本的确认。而 PC 上则是可以广泛地建立不同选项的 AVD,要进行测试时就将二个环境结合起来,将 Notebook 建置好的结果传送到 PC 上执行测试。
所以现在的问题是,这样的要求做得到吗?要怎么做?
可行的方案
首先,先来了解负责管理受测装置的工具 - ADB 的运作原理,这个工具包含了三个部份 Client、Daemon、Server:
- Client: 负责接收我们输入的指令,并且传送给所连接的 Server,一般就是我们在 Command-line 使用的
adb
指令。 - Daemon: 驻扎在移动装置上,可以是实体设备或是 AVD,负责在装置上执行由 Server 传来的指令。
- Server: 在计算机上执行,负责管理 Client 与 Daemon 之间的讯息传递。
从上图来看,可行的方案有三个:第一个是透过 Server 转送讯息给 Daemon,第二个是让 Client 连接到远程的 Server,第三个方案则是让 Server 连到远程的 Daemon。
第一个方案是使用 adb forward
的指令,让 Daemon 可以收到所处 PC 向 127.0.0.1 发出的讯息,并转给 AVD 指定的 Port。这个动作最直接的效果,是让所在的 PC 可以不用透过 Console,直接与 AVD 中的 Service 进行沟通。但似乎与跨机器无关,所以先略过。
第二个方案要达成不难,在 adb
的指令中有参数分别是 -H
及 -P
可以指定 Server 的 Address 及 Port。例如以下的指令可以列出 192.168.1.1 计算机上,ADB Server 所管理的装置清单。
adb devices -H 192.168.1.1 -P 5038
但有一个很关键的问题是,如何设定让 Android Studio 使用远程的 ADB Server 来进行部署及测试?IDE 和 Gradle 我都没有找到答案,也许是这样的选项还不存在吧!会有这个结果,最主要的问题应该是卡在如何让远程的 ADB Server 拿到生成好的结果,以传送进 AVD 内。
不过,倒是可以使用以下演示的指令来启动远程ADB Server 的测试,只不过连部署的工作都要在生成完成后,用 adb
自己动手。
adb shell am instrument -w <test_package_name>/<runner_class> -H 192.168.1.1 -P 5038
方案三,也是可以用 adb
的指令来达成,以下的指令可以让 ABD Server 连接到 192.168.1.1 计算机上的 AVD。
adb connect 192.168.1.1:3333
连上之后,就可以在 IDE 的 “Select Deployment Target” 的窗口中,看到远程的 AVD 被列在 “Connected Devices” 清单中。接下来的动作就跟过往一样,选择远程 AVD 的项目后,按下【OK】,等生成完成就可以看到 App 出现在远程 AVD 的画面里。
这个方案比第二个更具优势的是,可以直接在 IDE 或是 Gradle 中就完成部署及测试,维持原本的开发经验一气呵成,不用再另外做设定。
需注意的技术细节
在方案二或方案三的指令中,如果直接进行连接,应该会遇到问题、无法完成连接。主要的原因可以看一下图示:
ADB Server 聆听的 Address 是 127.0.0.1,而外部传入的 Port 是在真实的 IP 上,也就是说讯息并没有传到 ADB Server 所在的 Port 上。为了要解决这样的情况就必须要把真实 IP 接到的讯息 Forward 到 127.0.0.1 所在的 Port。
以 Windows 为例,内建有 netsh
指令来进行这项工作。以下的指令就是把真实 IP 在 5038 上收到的讯息,转送到 ADB 默认的 5037 Port 上:
netsh interface port proxy add v4tov4 listenport=5038 connectaddress=127.0.0.1 connectport=5037
这里有个小细节要注意,在设定 ADB Server 的聆听 Port 转送时,不能使用同一个 5037,会导致 ADB Server 无法启动。
同时,AVD 的 Port 是成对配置的,ADB 管理的范围是由 5554 到 5585,每二个号码分配给一个 AVD,偶数的号码是给 Console 连接用,奇数才是保留给 ADB。第一个 AVD 分配到的会是 5554,而 ADB 使用的则为 5555。以下图的 AVD 为例,显示的是 5558,但要进行远程连接的 Port 应该加一号为 5559。
AVD 的 Port 也不要占用到 5554 到 5585 的范围,否则 ADB 会认为 Port 被分配走,而跳过改取下一组。
这个设定是有持绩性的,不会因为重新开机而消失。而执行这个指令需要有 Administrator 的权限,所以可以一次就设定好清单,毕竟范围也就只有从 5555 到 5585。如此一来,不论 AVD 被分配到哪一个 Port 上,都可以被远程连接上。
所能达到的效果
最后总结一下以这种方式进行开发的好处:
- 节省开发环境的磁盘空间,并且可以更弹性地选择测试设备的规格,不用被开发的机器所限制。
- 有效利用闲置资源、增加工作效率。用 Notebook 开发的人,另外拥有 PC 是很常见的情况,只是很有可能在开发时是闲置的。而开发时最耗资源的都是测试,所以如果可以把耗资源的部份转移到效能相对较好的 PC 上,可以有效地提高效率。
- 减少空转与等待的情况。延续上一点,耗资源的工作被转出去,开发的机器就可以接续进行开发的工作,或是放松休闲一下,上上网、看个影片,等待测试完成。
另外,这次还有汇整其他在尝试过程中所遭遇问题的解决方法,有需要的朋友,可以连到 wznote.blogspot.com 看一下。更多深入的文章请参阅简书 //www.greatytc.com/u/fea63707e07f 或 wznote.blogspot.com