多渠道打包与签名
问题
如何高效实现多渠道打包?签名机制是什么?
答案
签名机制
Android 应用必须签名才能安装。签名验证应用完整性和开发者身份:
| 签名方案 | 引入版本 | 签名位置 | 特点 |
|---|---|---|---|
| V1(JAR) | 最初 | META-INF/ | 逐文件签名,可修改 ZIP 元数据 |
| V2 | Android 7.0 | APK Signing Block | 整包签名,防篡改 |
| V3 | Android 9.0 | APK Signing Block | 支持密钥轮换 |
| V4 | Android 11 | 独立 .idsig 文件 | 增量安装加速 |
app/build.gradle.kts
android {
signingConfigs {
create("release") {
storeFile = file("keystore/release.jks")
storePassword = System.getenv("KEYSTORE_PASSWORD")
keyAlias = System.getenv("KEY_ALIAS")
keyPassword = System.getenv("KEY_PASSWORD")
}
}
buildTypes {
release {
signingConfig = signingConfigs.getByName("release")
}
}
}
危险
永远不要将密钥密码硬编码在 build.gradle 中,应使用环境变量或 local.properties(已在 .gitignore 中)。
多渠道打包方案
方案一:Product Flavors(官方)
app/build.gradle.kts
android {
flavorDimensions += "channel"
productFlavors {
create("googlePlay") { dimension = "channel" }
create("huawei") { dimension = "channel" }
create("xiaomi") { dimension = "channel" }
}
}
- 优点:官方支持,可差异化代码/资源
- 缺点:每个渠道独立编译,100 个渠道 = 编译 100 次,极慢
方案二:APK 注释区写入渠道(推荐)
原理:利用 APK(ZIP 格式)的 Comment 区域写入渠道信息,不影响签名:
APK 文件结构:
┌──────────────────────┐
│ ZIP 文件内容 │ ← V1/V2 签名覆盖
├──────────────────────┤
│ APK Signing Block │ ← V2 签名
├──────────────────────┤
│ Central Directory │
├──────────────────────┤
│ End of Central Dir │
│ └─ Comment: xiaomi │ ← 写入渠道,不影响签名
└──────────────────────┘
代表工具:Walle(美团)、VasDolly(腾讯)
- 优点:只编译一次,秒级写入 100+ 渠道
- 缺点:V2 签名方案下注释区方案已失效,需写入 APK Signing Block
方案三:APK Signing Block 方案(推荐)
Walle 2.0 / VasDolly 将渠道信息写入 V2 签名的 APK Signing Block 中的自定义 ID-Value 对:
app/build.gradle.kts
plugins {
id("com.meituan.android.walle") version "1.1.7"
}
walle {
channelFile = file("channel.txt") // 渠道列表文件
}
channel.txt
googlePlay
huawei
xiaomi
oppo
vivo
# 一次性生成所有渠道包
./gradlew assembleReleaseChannels
读取渠道号:
val channel = WalleChannelReader.getChannel(context) ?: "official"
常见面试问题
Q1: V1 和 V2 签名的区别?
答案:
V1 签名基于 JAR 签名机制,对每个文件单独计算摘要并存放在 META-INF/ 目录。V2 签名对整个 APK 文件的字节内容做签名,覆盖 ZIP 条目、中央目录和 EOCD,存放在 APK Signing Block 中。
V2 比 V1 安全性更高(防止 ZIP 元数据被篡改),安装验证也更快。Android 7.0+ 优先验证 V2 签名,但仍建议同时启用 V1 以兼容旧设备。
Q2: 为什么多渠道打包不推荐用 Product Flavors?
答案:
Product Flavors 每个渠道都需要完整的编译→打包流程。如果有 50 个渠道,意味着编译 50 次,耗时可能数小时。而基于 APK Signing Block 的方案只需编译一次 Release APK,然后在签名后的 APK 中快速写入不同渠道标识,生成 50 个渠道包只需几秒。
Product Flavors 适合需要代码/资源差异的场景(如 Google Play vs 华为的不同推送 SDK),而纯渠道标识场景应使用 Walle/VasDolly。