全自动化的 Android 编译管线
【编者按】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 编译管线的更多相关文章
- 6.6 Android 编译机制的变迁
我们使用Java开发android,在编译打包APK文件时,会经过以下流程 Java编译器将应用中所有Java文件编译为class文件(JVM运行的是.class文件,而DVM是.dex文件) dx工 ...
- [Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程
本文转载自:[Android 编译(一)] Ubuntu 16.04 LTS 成功编译 Android 6.0 源码教程 1 前言 经过3天奋战,终于在Ubuntu 16.04上把Android 6. ...
- 【Linux】CentOS下升级Python和Pip版本全自动化py脚本
[Linux]CentOS下升级Python和Pip版本全自动化py脚本 CentOS7.6自带py2.7和py3.6 想要安装其它版本的话就要自己重新下载和编译py其它版本并且配置环境,主要是软链接 ...
- Android编译优化系列-kapt篇
作者:字节跳动终端技术---王龙海 封光 兰军健 一.背景 本文是编译优化系列文章之 kapt 优化篇,后续还会有 build cache, kotlin, dex 优化等文章,敬请期待.本文由Cli ...
- Android编译环境折腾记
题记:感觉是时候写点什么了=_=! 第一次安装了ubuntu14.04.5,官网下载的iso,官网下的jar,编译android4.x需要安装jdk6,更高的版本会有问题,baidu到很多搭建环境的步 ...
- Cocos2d-x3.6 Android编译问题
在Cocod2d-x论坛上看到越来越多人吐槽新版本更新太快,改动太大,而且经常有BUG导致升级要折腾很久很久..但我就是喜欢折腾,喜欢升级到最新版本,看看有了哪些新功能,哪些改进.为此也折腾了不少,遇 ...
- Xamarin.Android编译CPU类型选择方式
Xamarin.Android编译CPU类型选择方式 在Xamarin.Android编译的时候,默认提供了5种CPU类型供大家选择.它们分别为armeabi.armeabi-v7a.arm64-v8 ...
- Xamarin.Android编译提示找不到mscorlib.dll.so文件
Xamarin.Android编译提示找不到mscorlib.dll.so文件 错误信息:AOT module ‘mscorlib.dll.so’ not found: Cannot load lib ...
- Android编译过程详解(一)
Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...
随机推荐
- 决策树的基本ID3算法
一 ID3算法的大致思想 基本的ID3算法是通过自顶向下构造决策树来进行学习的.我们首先思考的是树的构造从哪里开始,这就涉及到选择属性进行树的构造了,那么怎样选择属性呢?为了解决这个问题,我们使用统 ...
- C 的 一些写法格式 交流
好久以前刚开始学习前辈们的代码的时候,发现好多代码感到好奇怪. 1)代码看不懂 2)代码格式看不懂 网上也没见同学们分享.当自己代码写多了,也渐渐的理解为什么要这样写了. 说主题之前 还是 说一些 题 ...
- brew mac osx 上软件包管理工具
今天推荐 Mac OSX 下,方便高效的包管理工具 brew brew 的全名叫做 Homebrew 它的功能类似于 ubuntu 下同下 apt-get ,或者 Cent OS 下的 yum 等包管 ...
- bc命令
bc 命令: bc 命令是用于命令行计算器. 它类似基本的计算器. 使用这个计算器可以做基本的数学运算. [tough@localhost *|bc [tough@localhost expr ...
- Get 和 Post方法的登录
1. Get & Post 1> Get请求直接从服务器拿数据 性能好 效率高 在地址栏会显示所有的参数,从直观上安全性不高 由于Get不提交数据给服务器,因此实际的安全性高 实际应用: ...
- 慎把“DataContext”静态化 或则单例
之前在项目里由于把DataContext静态化,最后在测试阶段发现了很多奇怪的问题,后来经过同事的指点 然后上网搜了一翻终于发现 MSDN上说: "请不要试图重用 DataContext ...
- Eclipse快捷键壁纸-0基础必备
- JSP动作学习一
创建一个简单的模拟登陆功能的网页,没有用数据库技术,只是简单的学习jsp语法 首先创建一个登陆页面 <%@ page language = "java" import=&qu ...
- SQL SERVER定时任务执行跟踪--供远程查看 [原创]
一.背景 每次查需要优化的SQL都需要上外网,通过Profiler,报表或者DMV执行特定sql来查找,来回跑很麻烦,能不能在本地直接监控外网的好性能的SQL呢?方法是有的,我们可以通过把Profil ...
- 课堂练习:给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数。
题目 1 给定一个十进制的正整数,写下从1开始,到N的所有整数,然后数一下其中出现“1”的个数. 2 要求: (1) 写一个函数 f(N) ,返回1 到 N 之间出现的“1”的个数.例如 f(12) ...