DevOps 是一种广为人知的活动,其主要目的是使软件交付自动化。的确,DevOps 的目标是持续测试、代码质量、功能开发和更轻松地进行维护更新。所以,DevOps 的终极目标之一是让开发者能够执行快速可靠、自动化的发布,理想状态下,整个流程都不须要人为操做。这被称为持续交付。撰写本文的目的是展现咱们如今也能在安卓上实现这一目标,同时分享笔者的想法和反馈意见。html
为了实现持续交付,必须确保强大的持续集成。这已经在安卓环境实行一段时间了,可是为了清楚起见,我们仍是回顾一下吧。android
首先,任何安卓应用程序都应具有持续集成。是的,笔者就是这个意思。实际上,这为现代应用程序开发带来了不可忽视的几个好处。在笔者看来,最大的优势是如下几项:git
构建自动化:告别“可是在个人机器上能够构建成功”。应用程序在哪里都能构建。github
尽早试错:每次推送后都进行构建能够确保尽早发现错误。json
测试持续化:确保测试始终进行api
持续打包:在打包二进制代码时避免人为错误。性能优化
发布速度更快:由于咱们对每一步构建都有信心,发布也变得更加简单。服务器
信心加强:终于,咱们能够信任本身的代码和流程,而且减小意料以外的错误。网络
First, we need an integration server like Jenkins or Travis. The following jobs are my standard configuration:app
首先,咱们须要一个 Jenkins 或者 Travis 那样的集成服务器。如下做业是笔者的标准配置:
• 一旦源码存储库(Git、SVN等等)中的推送完成,就会开始一个做业。它会查看 dev 分支、编译代码、运行单元测试,并打包调试 APK。
• 第一个做业成功完成后,运行下一个做业。它会运行集成测试(经过Espresso 或 Robotium),经过重现场景和检查图像内容来确保用户体验。你可使用链接设备(若是你的 CI 服务器不容易获取的话,就有些困难)、Genymotion 或随 Android Studio 2.0 发布的最新内置模拟器(快去试试吧!)来操做。
• 一个做业会运行代码测量(举个例子,经过 Sonarqube)以监测代码质量。例如,笔者会在天天半夜运行这个做业。
• 最后,在咱们推送 master 分支或发布分支后运行一个做业。它会编译代码,并生成发布 APK。
好啦!如你所见,操做很是简单,并且能保证笔者以前列举的全部优势。
笔者曾写过一篇关于安卓测试的文章。测试很是重要,由于它是能自动证实咱们的应用按计划运行的惟一方法。有不少工具能够帮咱们写出优秀的测试代码,因此要明智地进行选择。
同时,在选择集成到应用中的函数库时要实事求是。实际上,你应该明白若是函数库的测试覆盖率较高,测试应用程序就会更轻松。他们已经考虑到如何正确测试和经过测试促进开发的问题了(IMO、OkHttp 和 Retrofit 都是很好的范例)。至关于你在使用的同时就进行了测试。
最后,相似 Dagger 的函数库能够增长可测试性。实际上,它会迫使你遵守单一职责原则,而且将代码正确分离,这样测试就更加容易。
一旦你拥有了强大的持续集成,咱们来看看怎么升级吧。
举个例子,在 Captain Train,咱们每6周发布一个新版本,而且对此很是谨慎。目前:
• We have a beta phase.
• We support 4 locales.
• We support 3 types of device (phone, 7 and 9 inches tablets).
• We always check our Play Store listings.
• We create release notes.
• We use the rollout feature.
• We upload our 72 screenshots (6 screenshots * 4 locales * 3 types)
• We have a wear companion.
这个流程须要花时间,并且不止一点儿。最近,咱们决定是时候尝试把这个流程自动化了。虽然主要目的是为了减小发布版本须要的时间,可是若是同时也能避免人为错误,保持各个发布版本之间的连贯性,就更好了。这也让咱们担负了重大的责任,由于开发者控制了整个发布流程。实际上,市场和传播团队也要跟咱们一块儿看看怎么将他们的变化集成到发布版本中去。
可是坦白说……在安卓,开发者并不能控制全部的事情。谷歌能够。可是,它提供了 HTTP API,使开发者轻易地与谷歌电子商店控制台互动。他们还提供了各类开发语言的客户端,例如 Java(这是必须的!)、Phython、Ruby,等等……
在本文中,笔者将主要讨论 Java 客户端,由于这极可能是安卓开发者最了解的开发语言。
让咱们看看如何编写定制化的谷歌电子市场 publisher。分为两步:首先,咱们要配置控制台,让客户端可以操做,而后探索 API。一般跟谷歌创建链接时最困难的就是配置……相关文档能够在这里找到。请注意,文档也许不是最新版的。
首先,若是没有现成的,你须要在谷歌控制台新建一个项目。接下来,咱们须要启用 Google Play Android Developer API
。
Once it is done, we must create a credential of type Service account key:
完成以后,咱们必须建立一个 Service account key
类型的证书:
最后,填写小表,下载 JSON 格式的证书文件。你须要保存三个值:private_key_id
、private_key
和 client_email
。把 private_key
的值保存到它本身的 secret.pem
文件。
开发者控制台搞定了……如今咱们来看第二个控制台吧!
链接到你的电子市场控制台。你须要依次访问 Settings
> API access
:
接下来,你只须要链接你的项目。最后在 Service accounts
,受权你在 JSON 文件的 client_email
处填写的邮箱地址。
如今好了。一切搞定!
如今让咱们经过 Java 客户端访问接口。咱们在 publisher 上面建立一个单独的 Java 项目,而且添加如下依赖项(在 maven central 有):
compile 'com.google.apis:google-api-services-androidpublisher:
v2-rev20-1.21.0'
下一步是新建一个 AndroidPublisher
。首先,咱们经过如下信息来实例化 GoogleCredential
:一个客户端链接,一个 JSON factory,一个与 private_key_id
对应的私有关键 ID,一个与 client_email
对应的帐户 ID,ANDROIDPUBLISHER
范围,以及与 private_key
对应的、包含私有关键信息的重要文件。是的,全部这些都须要。
而后,咱们用应用程序包建立一个 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 是谷歌 API 的主要入口。它有一个 edits 方法,可让咱们修改想从控制台获取的数据。
要开始一个新版本,你必须用 insert 请求来开始,而后保存它的 id,接下来每次调用都会使用该 id。
AndroidPublisher.Edits edits = publisher.edits(); AppEdit edit = edits.insert(PACKAGE, null).execute(); String id = edit.getId();
如今,咱们能够开始修改控制台数据了。举个例子,若是你想修改排名:
Listings listings = edits.listings(); Listing listing = new Listing(). setFullDescription(description). setShortDescription(shortDescription). setTitle(title); listings.update(PACKAGE, id, "en_US", listing).execute();
You can also upload screenshots:
也能够上传截图:
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();
笔者鼓励你多多探索这个接口。它既强大,又不复杂。
最后一步,你必须提交本身的版本。实际上,谷歌会记录你的每个更改请求,可是只有在你提交版本以后,这些更改才会被保存。笔者同时建议你在提交以前先验证这些更改。
edits.validate(PACKAGE, id).execute();
edits.commit(PACKAGE, id).execute();
如你所见,你在代码开头找回的 id 能够被当作事务 id。经过调用 insert,update/upload
你的更改以开始事务,validate
以及最终 commit
。很是简单。
如今,安卓应用程序也能够呼应 DevOps 活动,拥有强有力的持续交付了。在 Captain Train,咱们选择编写本身的 publisher 工具来确保本身控制每一个步骤和重要步骤的字节。一旦发布任务成功完成,咱们就把它当作一个脚原本运行。不过也有 Jenkins 插件或 Gradle 插件能够帮你完成这些工做。只是要注意了解幕后的运行状况。毕竟你在处理生产。必须当心谨慎。
这样的工具和流程让你只需推送 master 分支便可在生产环境中发布新版本。既简单、快捷,又可靠、节约时间。
显然,在一个应用程序中可行的方法不必定适用于全部的团队、公司和应用程序。还要依靠你的团队以及团队与市场传播团队的关系。不过,在此笔者想要总结的是,持续交付应该成为每一个开发团队的目标,往这个目标迈进的每一步都是一种胜利。
OneAPM Mobile Insight以真实用户体验为度量标准进行 Crash 分析,监控网络请求及网络错误,提高用户留存。访问 OneAPM 官方网站感觉更多应用性能优化体验,想阅读更多技术文章,请访问 OneAPM 官方技术博客。
本文转自 OneAPM 官方博客