Java + Android 在持续集成中的实践
Android 生态走过了快 10 年的光阴,如今已经更迭到了 Android 11 版本。一个完整的 Android APP 生命周期包括了:开发、测试、签名、发布 等过程。如何快速进行迭代,如何进行工程化,相信也是目前 Android 开发者日常会遇到的问题。
本文将演示 “Java - Android” 项目如何在 DevOps 中进行实践,实现自动化的 编译构建
/签名
/上传到 Generic 制品库进行发布
过程。
准备阶段
本地环境需要:
- Git
- Java
- Gradle
- Android SDK
以及一个 CODING DevOps 账号。
初始化代码
使用 Android Studio 创建一个简单的 Android Hello World 项目并上传至 git 仓库。可参考以下的示例项目
示例代码目录结构
.
├── Jenkinsfile
├── README.md
├── app
│ ├── 步骤ild.gradle
│ ├── proguard-rules.pro
│ └── src // android 的核心代码文件
│ ├── androidTest.java.com.example.java_android
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── java.com.example.java_android
│ │ │ └── MainActivity.java
│ │ └── res
│ │
│ └── test.java.com.example.java_android // 单元测试文件
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
编译构建
Android Studio
默认推荐使用 gradle 进行依赖管理和构建。
其中根目录下的 build.gradle 有项目所包含的依赖,以及依赖拉取的来源。
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.6.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Android 应用
一般以 Apk 的形式输出。
在项目根目录下执行 ./gradlew assembleRelease
即可编译输出未签名的 apk 文件,更多的用法可参见Android 开发者官方网站。
运行示例:
运行后生成物:
APK 签名
为什么要为 APK 签名
- 应用升级:当安装应用的更新时,系统会比较新版本和现有版本中的证书。如果证书匹配,则系统允许更新。如果使用不同的证书为新版本签名,您必须为应用分配另一个软件包名称。在此情况下,用户会将新版本作为全新应用进行安装。
- 应用模块化:Android 允许通过同一证书签名的多个 APK 在同一个进程中运行(如果应用请求这样做),以便系统将其视为单个应用。这样一来,您便可以按模块部署您的应用,并且用户可以独立更新每个模块。
- 通过权限共享代码/数据:Android 提供了基于签名的权限执行机制,以便一个应用可以将功能提供给使用指定证书签名的另一个应用。通过使用同一个证书为多个 APK 签名并使用基于签名的权限检查功能,您的应用可以采用安全的方式共享代码和数据。
如何生成 APK 签名
确保本地有 java 环境,在命令行运行 keytool 生成 Android 签名证书。
例如:
keytool -genkeypair -alias android.test -keyalg RSA -validity 36500 -keystore java-android.p12 -storetype pkcs12
其中 android.test 是证书的别名。请记住,后续要使用。
运行后会让输入证书的密码等信息
最终会在当前文件夹下面生成名为 java-android.p12 的证书文件。
使用 Android Studio 进行签名非常快捷,可参考官方《使用 Android Studio 对应用进行签名》。
Android Studio 主要用于本地手动签名,自动化签名的过程将会直接集成到 CI 中,详情见后续步骤六。
使用 CODING 制品库存储管理 APK
目前,APK 没有一个统一的存储方式,没有好的追溯方式,不便于使用或者管理。
Generic 制品库
CODING 提供了 Generic 制品库,可以提供自定义的 Tag 作为版本标签,可以对 APK 文件进行管理和版本追溯。
- 创建一个 Generic 制品库
- 使用页面上传功能上传 APK 文件
- 查看版本列表管理历史版本
使用 CODING 持续集成实现自动化
上述步骤,编译、签名和上传 APK 文件其实都是重复劳动动作。下面介绍一下如何使用持续集成来实现自动化,代替人工执行这些重复操作。
- 在 CODING 中创建一个项目并推送代码到仓库,可以参考示例项目。
- 在持续集成->构建计划 中新建一个构建计划,推荐使用 Java-Android 模版进行创建。
JenkinsFile
pipeline {
agent any
stages {
stage("检出") {
steps {
checkout(
[$class: 'GitSCM',
branches: [[name: env.GIT_BUILD_REF]],
userRemoteConfigs: [[
url: env.GIT_REPO_URL,
credentialsId: env.CREDENTIALS_ID
]]]
)
}
}
// 下述演示的过程依赖于此示例仓库 https://coding-public.coding.net/p/java_android/git
// 您可以根据自己的实际情况调整构建过程
// 步骤二
stage('构建') {
steps {
// 清理旧的生成物
sh "./gradlew clean && rm -rf ./app/build/"
// 编译构建产出
sh "./gradlew assembleRelease"
}
}
// 步骤三
stage("APK 签名") {
steps {
signAndroidApks(
keyStoreId: env.ANDROID_CREDENTIAL_ID, // 凭据ID,凭据证书的使用详见步骤六
keyAlias: env.ANDROID_CREDENTIAL_ALIAS, // 证书别名,在生成证书时输入的别名
apksToSign: "app/build/outputs/apk/**/*.apk", // 需要签名的 APK 的路径
archiveSignedApks: true, // Jenkins 能力,可以在构建产物中输出签名后的 APK
archiveUnsignedApks: true, // Jenkins 能力,可以在构建产物中输出未签名的 APK
skipZipalign: true // 跳过 zipalign 过程
)
}
}
// 步骤四
stage('上传到 Generic') {
steps {
codingArtifactsGeneric(
credentialsId: "${env.CODING_ARTIFACTS_CREDENTIALS_ID}", // 默认的制品库凭据ID,CI 内置的环境变量
withBuildProps: true, // 默认值,是否上传附加属性
files: "app/build/outputs/apk/**/*.apk", // 需要上传的文件路径
repoName: "${env.GENERIC_REPO_NAME}", // 已创建的 Generic 制品库名称
version: "${CI_BUILD_NUMBER}" // 制品版本,可根据需要自定义,这里默认为 CI 构建的序号
)
}
}
}
}
使用凭据管理统一管理安卓证书
团队合作中,共享安全证书会有安全和效率问题,以文件形式储存的证书也不易于管理。
CODING 的凭据管理功能,提供了统一管理证书的能力,使用人仅需知道公开的 credentialId 即可在 CI 中使用凭据。
如何使用凭据
- 在 项目设置->开发者选项->凭据管理 处,点击录入凭据,上传步骤三中生成的证书文件,点击保存。
- 在使用 Java-Android 模版创建构建计划时,直接在选择凭据的下拉框中选择刚创建好的凭据,点击选择并授权。
构建计划创建完成后,选择的凭据会授权至新建的构建计划,并新增环境变量
ANDROID_CREDENTIAL_ID
,填入所选的 credentialId。点击立即构建后,CI 就会自动化地进行编译构建、APK 签名和上传签名后 APK 至 Generic 制品库的操作。
总结
至此,我们已经把整个 Android 开发流程中重要的操作步骤完全自动化流水线化,这极大地简化了人工操作,让开发者能更好的从繁琐的开发流程中脱离出来,专注于代码功能的迭代研发。
目前 CODING 已经在持续集成中内置了上述的整个流程,可以通过简单的配置即可快速使用,轻量易于上手。
完整的代码例子可参见示例项目。

在阅读中是否遇到以下问题?
您希望我们如何改进?