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 官方博客