【编者按】Nicolas Frankel 是 hybris 的高级顾问, 在Java / J2EE 领域拥有超过10年的管理经验,本文阐述了他在使用自动化工序去构建 Android 应用程序遇到的一些难题,大家不妨读读,希望能有所收获。

以下系译文:

在我目前的工作中,我必须使用一些自动化工序去构建 Android 应用程序。这篇文章的目的就是描述我所遇到的难题,避免读者在这个过程浪费更多时间。目的就是分享我在这一过程中所遇到的困难,为读者提供前车之鉴,从而节省宝贵的时间。

环境搭建如下:

  • 使用 Puppet 搭建基础设施
  • 使用 Jenkins 搭建 CI 服务器
  • 工程文件
  • 来构建主体
  • 作为主要测试工具

Puppet and Jenkins

事实上,我的准备工作已经相当完备。同事们已经使 Jenkins 服务器可以自动安装,以及准备好了所需的软件包——包括 Java 和已提供的可复用的 Puppet 类。Jenkins 的工作完全依赖于一个单一 config.xm 文件,即不同部分的封装。每部分都由一个专门的模板处理。因此,在我看来,创建一个简单的 Gradle 任务就如同在公园里散步一般轻松,最多几天时间便可以完成。

第一步非常容易:只需一个最新版 Puppet 清单,能帮助你添加 Gradle 插件到 Jenkins 服务器。

The Gradle wrapper

如果你是我博客的忠实读者,那你大概知道我对 Gradle 的看法。不过,我必须得承认,Maven 的确缺乏这种兼容性,即不论安装哪个版本的工具都确保编译成功——虽然它应该具备该功能。为了实现这一目标,Gradle 通过提供一个 JAR、一个 shell 脚本和一个属性文件,属性文件还包含了从 URL 到 Gradle ZIP 的分发,组装成所谓的包装机制。这三个需求都被存储在 SCM 中。

然而这正是麻烦的开始。在一个企业环境中进行下载,意味着要通过和验证代理。最简单的选择莫过于在工作配置下设置好一切,包括代理凭证。然而,从安全的角度来看,这样的做法并不理想,因为任何人访问 Jenkins 接口或文件系统,都能够读取这些凭据。显然,我们需要一个更好的方式。

用户已经拥有了配置代理完备的 Nexus 库。上传所需的 Gradle 分布,并更新指向它的 gradle.properties,简直易如反掌。

The Android SDK



Android SDK 只是一个 ZIP 文件。我用同样的方法:先下载文件然后将其上传到 Nexus。这一步之后,一个 Puppet 脚本会负责下载、提取,并为它设置正确的权限。

然而,事情并没有想象的那么简单。Android 开发者都知道,Android SDK 需要手动操作:开发者必须手动检查所需平台和工具,并将其下载在本地文件系统。这看上去很简单不是吗,但如果转为自动操作则会让很多开发者头疼,尽管有一个命令行相当于可以通过 SDK「带有 --no-ui 参数」来安装/更新包。如果你想了解更多,请点击这里

谷歌工程师未能提供的两个重要参数:

  • Proxy credentials – login/password
  • Accepting license agreements

为了解决这一问题,网上有很多蹩脚的方案,最诱人的应该要数配置文件了,但我却发现它们没多大用。然而,通过 expect 命令的使用,我反而发现了一种创造性的解决办法。Expect 是一个漂亮的命令,用来读取标准输出,并用标准输入进行相应的填写。值得一提的是,它竟然还可以接受正则表达式。所以,在请求代理登录时,你键入登录名、填写密码,当它要求许可证接受时,你键入「同意」就能轻松搞定。虽然我反复多次试验,历经很多错误,才达到预期结果。但这个方法非常简单、直接。

我最初的设计是,使所有可能用到的装有 Puppet 的 Android 包,成为服务器配置的一部分。在标准化操作中「如文件创建或系统包安装」,Puppet 可以确定这项配置是否必要。例如:如果某文件已经存在,那就没有必要再重复创建了。在最后的 Log 中,Puppet 会报告它执行的每一个操作。起初,我试图通过在配置过程中,人为地告诉 Puppet 哪个包是已配置的,因为 Android SDK 为每个包都创建一个文件夹。但要命的是,Puppet 只接受单一文件夹来验证。对于某些包来说,并没有任何版本信息「例如 Google 游戏服务」。

因此,一个同事提出将 Puppet 配置的更新,移动到每个任务的预先步骤中。这样能修复非幂等问题,同时,还能在每个任务中更新所需配置。

Robolectric



说到这里,我本以为一切都搞定了。但非常不幸,并不是这么回事,就因为这个库—— Robolectric。

此前,我对 Robolectric 没什么了解,只知道这是一个测试库,能够在 Android 上运行测试,而无需任何物理设备的连接。在 Jenkins 上试图编译时,我偶然发现了一个「有意思」的问题:尽管 Roboletric 提供了一个具有完整依赖性的 POM, 但 MavenDependencyResolver 类硬编码库应该从哪里下载?

唯一的解决办法是通过扩展上面的类来实现。我用的就是上面提到的企业 Nexus 库。

上传并发布任务

为了实现前面的任务,我只需添加一个自定义 Gradle 任务,从 settings.xml 得到 Nexus 设置「由 Puppet 调配」。基于此,我成功地上传了任务。最后,对于每个任务执行的型号,我添加到所上传的工件集的输出文件中。因此,不管编译文件是哪种型号配置,下面的命令都将只上传 XXX 和 YYY:

 ./gradlew assembleXXX assembleYYY upload

上面的任务都搞定了,那发布岂不是更简单:唯一需要的就是设置 Gradle 插件,它添加了一个发布任务,类似于 Maven 的 deploy。

结束语

作为后端开发人员,我已经习惯于持续集成设置,毫无疑问,我可以在几天内搞定 Android CI 的进程。对于 Android 系统在 CI 上的欠缺,我觉得不可思议。每一步都苦不堪言,糟糕的记录「如果有的话」和解决方案似乎更像黑客般具有破坏性。如果你想沿着这条路走下去。呐,别说我没告诉你……Good Luck!

原文链接: Fully Automated Android Build

本文系 OneAPM 工程师编译整理。OneAPM 是应用性能管理领域的新兴领军企业,能帮助企业用户和开发者轻松实现:缓慢的程序代码和 SQL 语句的实时抓取。想阅读更多技术文章,请访问 OneAPM 官方博客

全自动化的 Android 编译管线的更多相关文章

  1. 6.6 Android 编译机制的变迁

    我们使用Java开发android,在编译打包APK文件时,会经过以下流程 Java编译器将应用中所有Java文件编译为class文件(JVM运行的是.class文件,而DVM是.dex文件) dx工 ...

  2. [Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程

    本文转载自:[Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程 1 前言 经过3天奋战,终于在Ubuntu 16.04上把Android 6. ...

  3. 【Linux】CentOS下升级Python和Pip版本全自动化py脚本

    [Linux]CentOS下升级Python和Pip版本全自动化py脚本 CentOS7.6自带py2.7和py3.6 想要安装其它版本的话就要自己重新下载和编译py其它版本并且配置环境,主要是软链接 ...

  4. Android编译优化系列-kapt篇

    作者:字节跳动终端技术---王龙海 封光 兰军健 一.背景 本文是编译优化系列文章之 kapt 优化篇,后续还会有 build cache, kotlin, dex 优化等文章,敬请期待.本文由Cli ...

  5. Android编译环境折腾记

    题记:感觉是时候写点什么了=_=! 第一次安装了ubuntu14.04.5,官网下载的iso,官网下的jar,编译android4.x需要安装jdk6,更高的版本会有问题,baidu到很多搭建环境的步 ...

  6. Cocos2d-x3.6 Android编译问题

    在Cocod2d-x论坛上看到越来越多人吐槽新版本更新太快,改动太大,而且经常有BUG导致升级要折腾很久很久..但我就是喜欢折腾,喜欢升级到最新版本,看看有了哪些新功能,哪些改进.为此也折腾了不少,遇 ...

  7. Xamarin.Android编译CPU类型选择方式

    Xamarin.Android编译CPU类型选择方式 在Xamarin.Android编译的时候,默认提供了5种CPU类型供大家选择.它们分别为armeabi.armeabi-v7a.arm64-v8 ...

  8. Xamarin.Android编译提示找不到mscorlib.dll.so文件

    Xamarin.Android编译提示找不到mscorlib.dll.so文件 错误信息:AOT module ‘mscorlib.dll.so’ not found: Cannot load lib ...

  9. Android编译过程详解(一)

    Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...

随机推荐

  1. hdu 2034 人见人爱A-B

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=2034 人见人爱A-B Description 参加过上个月月赛的同学一定还记得其中的一个最简单的题目, ...

  2. poj 1338 Ugly Numbers

    原题链接:http://poj.org/problem?id=1338 优先队列的应用,如下: #include<cstdio> #include<cstdlib> #incl ...

  3. o2o家庭助手demo

    前段时间跟一个同事出去游玩,在回来的大巴上面我们聊到了现在比较热门的o2o,说实话我自己早就想要在这个领域好好地玩一把.但是一直苦于没有很好地idea,再加上自己之前一直没有这方面的创业经验,所以一直 ...

  4. android几种定时器机制及区别

    在android中,经常用到的定时器主要有以下几种实现:一.采用Handler与线程的sleep(long )方法二.采用Handler的postDelayed(Runnable, long) 方法三 ...

  5. Asp.Net MVC如何返回401响应码

    需求:     在默认创建的Asp.Net MVC项目中(这里使用VS2013),需要手动返回一个401响应码给浏览器.我们的代码可能是下面这样子的.   public ActionResult Un ...

  6. [转]p2p端口映射工具 dog-tunnel

    [转]p2p端口映射工具 dog-tunnel http://www.oschina.net/p/dog-tunnel 狗洞是一个高速的 P2P 端口映射工具,同时支持Socks5代理. 0.5版后开 ...

  7. [转]Win7 UAC的安全、兼容及权限

    [转]Win7 UAC的安全.兼容及权限 http://www.cnblogs.com/mydomain/archive/2010/11/24/1887132.html 网上关于这个问题讨论较多,但也 ...

  8. 16位CPU多周期设计

    16位CPU多周期设计 这个工程完成了16位CPU的多周期设计,模块化设计,有包含必要的分析说明. 多周期CPU结构图 多周期CPU设计真值表 对应某一指令的情况,但仅当对应周期时才为对应的输出,不是 ...

  9. iOS10推送必看UNNotificationServiceExtension

    转:http://www.cocoachina.com/ios/20161017/17769.html (收录供个人学习用) iOS10推送UNNotificationServic 招聘信息: 产品经 ...

  10. iOS开发HTTPS实现之信任SSL证书和自签名证书

    iOS开发HTTPS实现之信任SSL证书和自签名证书 转自:http://www.jianshu.com/p/6b9c8bd5005a/comments/5539345 (收录一下供自己学习用的) 字 ...