跳到主要内容

多渠道打包与签名

问题

如何高效实现多渠道打包?签名机制是什么?

答案

签名机制

Android 应用必须签名才能安装。签名验证应用完整性和开发者身份:

签名方案引入版本签名位置特点
V1(JAR)最初META-INF/逐文件签名,可修改 ZIP 元数据
V2Android 7.0APK Signing Block整包签名,防篡改
V3Android 9.0APK Signing Block支持密钥轮换
V4Android 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。

相关链接