DevOps on Android: 加速 App 从代码到上线
DevOps 是一个众所周知的开发方法,其主要目的是自动化软件交付。事实上,DevOps 的目标是不断的测试,代码质量,功能开发,更容易维护版本。因此,DevOps 的一个最终目标是为开发者进行快速,可信赖和自动化发布提供指导,理想化状态是在这个过程中不牵涉任何人工劳动。这就是所谓的持续交付。我写这篇文章来证明,我们现在能在 Android 平台上达成这样的目标,同时和大家分享一下我的想法和听取大家的反馈。
持续集成为出发点
想要达到持续交付,持续集成必须是强制的。在安卓平台上的持续集成已经有一段时间了,为了更清楚的去了解,我们先说一下它的优势。
安卓平台必须采用持续集成方法,是的我说过。确实,持续集成有一些在构建 Android App过程中无法发忽略的好处。在我看来,它的优势在于:
自动化构建:不再只是在我的机器,而是在所有的环境。
早失败:一旦代码提交之后就马上构建,这样就保证错误能被及早的发现。
构建测试:保证每一个测试用例都能正常运行。
不断打包:防止打包过程中的人为错误。
快速发布:既然我们对于每一次构建都有信心,那么发布就变得简单了
增加信心:最后,我们相信我们的代码,我们的过程,我们减少不良的惊喜。
一个典型的持续集成过程
首先,我们需要一个集成服务器像Jenkins 或 Travis 。下面的工作是我的标准配置:
启动一个监视代码推送到我们的代码仓库(Jenkins or Travis)完成事件的任务。该任务监视代码的 dev 分支去自动的编译、单元测试、打包或者 debug APK .
当上面的任务完成之后,另外一个任务就要被启动了。这个任务主要用来跑集成测试(通过 Espresso 或者 Robotium)。在这个过程中,通过模拟用户场景和检查渲染的图形内容的方式来保证最终的用户体验。
另外一个任务就是一个每天晚上都会运行的执行代码质量扫描(例如 Sonarqube )的任务。
最后还有一个任务用来检测一旦代码仓库的 master/release 分支有更新就去构建发布的APK包。
看看吧,正如你看见的,这个过程很简单并且保证能达成我开始所说的优势。
测试是关键
我曾经写过一篇关于测试的文章(testing on Android)。测试是如此的重要因为它是能够保证App按照我们所设定的那样去工作的唯一工具。写单元测试有很多工具和方法,请明智的去选择。
此外,确认一下你要在你的应用程序集成的库。事实上,当你使用的库有一个良好的单元测试覆盖率的时候,就更容易测试您的App。一些被认为恰当测试的并且用测试驱动他们的开发的类库(例如 IMO, OkHttp and Retrofit )。很可能,你将能够在使用它的时候来测试它。
最后,像 Dagger 库可以帮助你提高可测试性。事实上,它会迫使你遵循单一职责原则和正确分开你的代码,从而更容易测试。
一旦你有一个强大的持续集成,让我们来看看如何提高水平。
持续交付: Level++
举例来说,在 Captain Train。我们发布每6周一次,我们都非常小心了。 目前每次发布都要做:
- 我们有一个测试阶段
- 我们支持 4 个区域设置。
- 我们支持 3 种类型的设备(phone, 7 and 9 inches tablets)。
- 我们经常检查我们的的 Play Store。
- 我们写发行说明。
- 我们使用部署功能。
- 我们上传了 72 截图(6 screenshots * 4 locales * 3 types)
整个过程非常消耗时间,最近我们想,是时候去把这个过程给自动化了。即使我们的最终目标是减少发布时间。这种感觉非常好,去防止人为的犯错误以及经常的发布发布。我们能掌握整个过程,这样让我们更加有责任心。
但是,坦白的说,安卓开发者不能控制所有的事情,只有 Google 能做到。
例如,它暴露了一个 HTTP API,使开发人员能够使用 Play 商店控制台轻松互动。他们也提供了很多语言实现的语言包,例如Java ,Ruby 等。
在这篇文章,我讲专注于 Java 语言,因为对于安卓开发者来说,这是最容易的。
编写你自己的 App 发布工具
让我们看看如何编写自己的 App 发布工具来把 APP 发布到 Play Store 。大概有两个步骤:首先,我们将配置我们的控制台,使我们的客户端能够进行操作,进而我们就会发现其中的 API。最困难的事情经常用谷歌去配置。文档()可以在这里找到。请注意,这是一个有点过时。
配置
首先,如果没有做,你必须在谷歌控制台创建一个新的项目。然后,我们需要启用 Google Play Android Developer API。

一旦完成,我们必须创建服务帐户关键的凭证:

最后填写表格,并下载一个 json 格式的凭证。你需要保存三个值:private_key_id, private_key 、 client_email. 把 private_key 的值保存在 secret.pem 中.
我们正在与开发者控制台交互......现在让我们去到第二个控制台! \ O /
连接到您的控制台。你必须进入 Settings > API access:

然后,你必须简单地链接您的项目。最后,在 Service accounts,授予权限给你下的 JSON 文件中的的客户端邮件的client_email。
到现在为止,一切都准备好了。
API发现
现在,让我们深入到 Java 客户端 API。我们创建了一个单独的 Java 项目为我们的发布工具,我们添加下面的依赖(Maven的中央仓库有):
compile 'com.google.apis:google-api-services-androidpublisher:
v2-rev20-1.21.0'
下一个步骤是创建一个 AndroidPublisher。首先我们通过提供 transport client, JSON factory,和 private_key_id 对应的 private key ID,和 client_email 对应的账户 ID 来实例化一个 GoogleCredential。ANDROIDPUBLISHER 是一个包含了私钥的关键文件。
http = GoogleNetHttpTransport.newTrustedTransport();
json = JacksonFactory.getDefaultInstance();
Set<String> scopes =
Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER);
GoogleCredential credential = new GoogleCredential.Builder().
setTransport(http).
setJsonFactory(json).
setServiceAccountPrivateKeyId(KEY_ID).
setServiceAccountId(SERVICE_ACCOUNT_EMAIL).
setServiceAccountScopes(scopes).
setServiceAccountPrivateKeyFromPemFile(secretFile).
build();
publisher = new AndroidPublisher.Builder(http, json, credential).
setApplicationName(PACKAGE).
build();
AndroidPublisher 对象是Google控制台的主入口,他有一个 Edit 方法,允许我们编辑控制台的数据。
要开始一个新的版本,你必须以发起插入请求,并存储它的返回值,你会在每一个后续调用中使用这个返回的 ID。
AndroidPublisher.Edits edits = publisher.edits();
AppEdit edit = edits.insert(PACKAGE, null).execute();
String id = edit.getId();
现在我们将改变我们的控制台数据,举例来说改变 listings:
Listings listings = edits.listings();
Listing listing = new Listing().
setFullDescription(description).
setShortDescription(shortDescription).
setTitle(title);
listings.update(PACKAGE, id, "en_US", listing).execute();
你也可以上传截图
Images images = edits.images();
FileContent content = new FileContent(PNG_MIME_TYPE, file);
images.upload(PACKAGE, id, "en_US", "phone5", content).execute();
最后一个例子,让我们上传一个 APK
// APK upload
Apks apks = edits.apks();
FileContent apkContent = new FileContent(APK_MIME_TYPE, apkFile);
Apk apk = apks.upload(PACKAGE, id, apkContent).execute();
int version = apk.getVersionCode();
// Assign APK to Track
Tracks tracks = edits.tracks();
List<Integer> versions = Collections.singletonList(version)
Track track = new Track().setVersionCodes(versions);
tracks.update(PACKAGE, id, "production", track).execute();
// Update APK listing
Apklistings apklistings = edits.apklistings();
ApkListing whatsnew = new ApkListing().setRecentChanges(changes);
apklistings.update(PACKAGE, id, version, "en_US", whatsnew).execute();
我推荐大家使用 API,因为它很完美并且很强大。
最后一步,你必须提交你的版本。事实上,到目前为止,谷歌记录您所请求的每一个变化,但是它只会保存您提交的变化。我也建议你尝试提交之前验证您的更改。
edits.validate(PACKAGE, id).execute();
edits.commit(PACKAGE, id).execute();
正如你看见的那样,开始所获取的 ID,就像是一个事务ID 一样。你开始事务之后,通过 insert, update/upload 来处理变化,并且通过 validate 方法验证 ,通过commit 方法提交。一切都如此简单。
讨论
现在我们可以遵循 devOps 原则,甚至对于安卓开发来说有了比较强大的持续交付能力。在 Captain Train 我们选择去写我们自己的发布工具以此来控制重要的每一个步骤。一旦 release 任务执行成功,我们就执行发布工具来发布 App。当然了Jenkin 和 Gradle 也有一些类似的工具可用。
诸如此类的工具能让你简单的通过向 master 或者 release 分支推送代码的方式来发布你的App。这个过程简单、可信赖、节省时间!
很明显,这个过程不一定适用于每个团队/公司/应用程序~ ,这取决于你所在团队的具体情况。但是,我要强调的是持续交付应该是每一个团队/公司的目标。一旦达成,它将驱动您走向成功。
原文:http://jeremie-martinez.com/2016/01/14/devops-on-android/
OneAPM Mobile Insight,监控网络请求及网络错误,提升用户留存。访问 OneAPM 官方网站感受更多应用性能优化体验,想阅读更多技术文章,请访问 OneAPM 官方技术博客。
本文转自 OneAPM 官方博客
DevOps on Android: 加速 App 从代码到上线的更多相关文章
- Web程序员开发App系列 - 调试Android和IOS手机代码(补图)
Web程序员开发App系列 Web程序员开发App系列 - 认识HBuilder Web程序员开发App系列 - 申请苹果开发者账号 Web程序员开发App系列 - 调试Android和iOS手机代码 ...
- JavaScript调用App原生代码(iOS、Android)通用解决方案
实际场景 场景:现在有一个H5活动页面,上面有一个登陆按钮,要求点击登陆按钮以后,唤出App内部的登录界面,当登录成功以后将用户的手机号返回给H5页面,显示出来.这个场景应该算是比较完整的一次H5中的 ...
- Android蓝牙遥控器APP关键代码 guihub项目
package com.car.demo; import java.io.IOException; import java.io.OutputStream; import java.util.UUID ...
- 【Android】1.0 第1章 C#之Android手机App开发
分类:C#.Android.VS2015:创建日期:2016-01-20 目前Android在全世界市场上大约有75%的占有率,国人Android手机的持有比例更甚,甚至达到90%以上.因此搞计算机的 ...
- Android Studio增加NDK代码编译支持--Mac环境
Android的APP开发基本都是使用Java或者跨平台框架进行开发的,对于很多APP来说已经足够了,但是,对于提供功能给外部使用或者性能要求很高的需求下,如图像处理等,可能会需要C/C++库的支持, ...
- 【Android端APP 安装包检查】安装包检查具体内容及实现方法
一.安装包检查的具体包含内容有哪些? 1.安装包检查的一般内容包括: 安装包基本信息检查: 文件大小: xx MB 包名: com.xx 名称: xx 本次安装包证书与外网证书对比一致性:是 版本号 ...
- Android开发App工程结构搭建
本文算是一篇漫谈,谈一谈关于android开发中工程初始化的时候如何在初期我们就能搭建一个好的架构. 关于android架构,因为手机的限制,目前我觉得也确实没什么大谈特谈的,但是从开发的角 ...
- 【Android - 进阶】之代码打包签名与混淆
代码打包签名 Android Studio为大家集成了代码打包混淆的功能,具体操作流程如下组图所示: 1.点击Android Studio上方工具栏的 Build -> Generate Si ...
- Android动态加载代码技术
Android动态加载代码技术 在开发Android App的过程当中,可能希望实现插件式软件架构,将一部分代码以另外一个APK的形式单独发布,而在主程序中加载并执行这个APK中的代码. 实现这个任务 ...
随机推荐
- Demo1_iOS9网络适配_改用更安全的HTTPS
iOS9把所有的http请求都改为https了:iOS9系统发送的网络请求将统一 使用TLS 1.2 SSL.采用TLS 1.2 协议,目的是 强制增强数据访问安全,而且 系统 Foundation ...
- JavaScript如何获得Select下拉框选中的值
js代码: var mySelect = document.getElementById("resultList2"); var mySelectText = mySelect.o ...
- euqals和hashcode
hashcode这个方法是用来鉴定2个对象是否相等的. 那你会说,不是还有equals这个方法吗? 不错,这2个方法都是用来判断2个对象是否相等的.但是他们是有区别的. 一般来讲,equals这个方法 ...
- java 静态方法
在使用java的时候,你会发现,有些对象,需要new ,有些则不需要时,比如Math类 ); 如果你查看源码就会大致的发现,里面的属性和方法都是静态的: public static double si ...
- Redis 集群常见问题
Redis集群相关问题 1:远程连接问题 远程连接保护模式下,需要做一些配置.
- CSS的!important修改权重
!important语法和描述 !important为开发者提供了一个增加样式权重的方法.应当注意的是!important是对整条样式的声明,包括这个样式的属性和属性值. #example { fon ...
- JS操作CSS样式
一.样式表(css) 使用样式表可以更好的显示WEB文档,也可以结合javascript从而实现很好的控制样式表. 样式(css)与内容(html): HTML是处理文档结构的,HTML可以实现如何把 ...
- [转] c# 数据类型占用的字节数
http://www.cnblogs.com/laozuan/archive/2012/04/24/2467888.html
- 不允许对索引显式地使用 DROP INDEX,该索引正用于 UNIQUE KEY
[转载]http://blog.csdn.net/w87875251l/article/details/7929657 不允许对索引显式地使用 DROP INDEX,该索引正用于 UNIQUE KEY ...
- mongodb下载及安装配置教程【仅供参考】
1 下载 下载页面地址:https://www.mongodb.org/downloads 版本选择:电脑系统是64位的,所以我选择了 Windows 64-bit 2008 R2+ ,msi包 2 ...