10、Android签名配置:签名文件生成、signingConfigs配置、签名信息保护方案、自动签名与CI/CD集成
签名,是Android应用的身份证。没有签名的APK,连设备都装不上去。我刚开始做Android开发那会儿,对签名的理解就是「随便搞个keystore,能跑就行」。直到有一次,公司内部测试包和生产包签名搞混了,导致用户无法覆盖安装——嗯,那天加班到凌晨两点。
说白了,签名配置看似简单,但坑不少。今天咱们就把这块彻底捋清楚。
签名文件生成:你得先有把「钥匙」
签名文件有两种主流格式:JKS(Java KeyStore)和PEM/PKCS12。我个人习惯用JKS,因为Android Studio原生支持,省事。
生成签名文件,最直接的方式是用Android Studio的菜单:Build → Generate Signed Bundle/APK,然后跟着向导走。但如果你像我一样喜欢命令行,可以用keytool:
keytool -genkey -v -keystore my-release-key.jks \
-keyalg RSA -keysize 2048 -validity 10000 \
-alias my-alias
这里几个参数我解释一下:
- -validity 10000:有效期,单位是天。10000天差不多27年,够用了。别设太短,否则应用到期后无法更新。
- -keyalg RSA -keysize 2048:加密算法和密钥长度。2048位是目前的安全基线,别用1024了。
- -alias:别名,后面在signingConfigs里要用到。
signingConfigs配置:在Gradle里「上锁」
有了签名文件,接下来就是在build.gradle里配置。先看一个标准写法:
android {
signingConfigs {
release {
storeFile file("my-release-key.jks")
storePassword "your-store-password"
keyAlias "my-alias"
keyPassword "your-key-password"
}
}
buildTypes {
release {
signingConfig signingConfigs.release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
这段代码本身没问题,但有个致命缺陷——密码硬编码。你想想看,如果把密码提交到Git仓库,那跟把家门钥匙挂在门外有什么区别?
我在项目中遇到过,有同事直接把密码写在build.gradle里,然后push到了公开仓库。虽然很快删除了,但Git历史里永远留下了痕迹。嗯,那之后我们团队就强制要求签名信息必须外部化。
签名信息保护方案:别把密码写死在代码里
保护签名信息,常见的有三种方案。我按推荐程度排序:
| 方案 | 原理 | 安全等级 | 适用场景 |
|---|---|---|---|
| 环境变量 | 从系统环境变量读取 | ⭐⭐⭐ | 个人项目、小团队 |
| properties文件 | 单独配置文件,不提交Git | ⭐⭐⭐⭐ | 大多数项目 |
| CI/CD密钥管理 | 使用CI平台的内置密钥服务 | ⭐⭐⭐⭐⭐ | 企业级、自动化构建 |
方案一:环境变量
最简单,但需要每个开发者都设置一遍环境变量:
signingConfigs {
release {
storeFile file(System.getenv("KEYSTORE_PATH"))
storePassword System.getenv("STORE_PASSWORD")
keyAlias System.getenv("KEY_ALIAS")
keyPassword System.getenv("KEY_PASSWORD")
}
}
方案二:properties文件(我推荐这个)
创建一个keystore.properties文件,放在项目根目录,但不要提交到Git。在.gitignore里加上它:
# keystore.properties 内容
storeFile=my-release-key.jks
storePassword=your-store-password
keyAlias=my-alias
keyPassword=your-key-password
然后在build.gradle里读取:
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
signingConfigs {
release {
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
}
}
}
keystore.properties.example模板文件,里面填上占位符,提交到Git。这样新同事来了,复制一份改密码就行,不会漏掉配置项。
自动签名与CI/CD集成:让机器替你干活
手动签名太累了,尤其是频繁发测试包的时候。自动签名,说白了就是把签名流程嵌入到构建脚本里,让CI/CD平台(比如Jenkins、GitHub Actions、GitLab CI)自动完成。
以GitHub Actions为例,核心思路是:
- 把签名文件Base64编码后,存入GitHub Secrets
- 在CI脚本里解码还原文件
- 从Secrets读取密码,注入Gradle构建
先看编码签名文件的命令:
base64 my-release-key.jks > keystore_base64.txt
然后把keystore_base64.txt的内容复制到GitHub Secrets,命名为KEYSTORE_BASE64。密码也分别存为STORE_PASSWORD、KEY_PASSWORD。
接下来是.github/workflows/build.yml的关键部分:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: 解码签名文件
run: |
echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > app/my-release-key.jks
- name: 构建Release APK
env:
STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
run: ./gradlew assembleRelease
对应的build.gradle里,从环境变量读取密码:
signingConfigs {
release {
storeFile file("my-release-key.jks")
storePassword System.getenv("STORE_PASSWORD") ?: ""
keyAlias "my-alias"
keyPassword System.getenv("KEY_PASSWORD") ?: ""
}
}
storeFile的路径是相对于项目根目录的。我一开始写的是app/my-release-key.jks,但解码时放到了app/目录下,路径对了才能找到文件。
知识体系总览
下面这张图,把签名配置的完整流程串起来了。你可以看到,从生成签名文件,到配置signingConfigs,再到保护密码、接入CI/CD,每一步都有讲究:
你看,签名配置其实就这几步。但每一步都有细节要注意。比如签名文件的有效期,我见过有人设了365天,结果一年后应用无法更新,用户全在评论区骂。再比如密码保护,别嫌麻烦,用properties文件或者CI密钥管理,花5分钟配置,能省未来无数个加班夜。
最后说一句:签名这事,宁可多花时间做对,也别图快埋坑。毕竟应用一旦发布,签名就绑死了,想换都换不了。
公众号:蓝海资料掘金营,微信deep3321