1. 产品风味与多渠道打包:为什么你需要它?
如果你做过Android开发,肯定遇到过这种头疼事:同一个App,要出好几个版本。比如,给A客户做的版本,启动页logo是A公司的,后台接口地址是A的测试环境;给B客户做的版本,logo要换成B公司的,接口地址要指向B的生产环境。更别提那些应用商店了,上架小米应用商店、华为应用市场、还有自己官网的渠道包,每个包的渠道统计标识都不一样。以前你是怎么做的?复制一份代码,改改资源文件和配置常量,然后分别打包?相信我,这么干过的人,最后都陷入了“版本地狱”——改个bug,得在所有副本里改一遍,稍不留神就漏了,维护成本高到吓人。
productFlavors,翻译过来叫“产品风味”,就是Gradle给你的一把瑞士军刀,专门用来优雅地解决这类问题。你可以把它理解为一个“维度化”的构建配置系统。它允许你为同一个App核心代码,定义多套“风味”,每套风味可以独立配置自己的代码、资源、依赖库,甚至是applicationId(也就是包名)。最终打包时,Gradle会像做蛋糕一样,把核心代码和你选定的“风味”原料混合,烘焙出指定口味的APK。
这么做的好处太明显了。首先,维护成本直线下降。所有公共逻辑都在main目录下,各风味独有的差异(如图片、字符串、甚至Java类)放在对应的风味源集(如src/oemA/)里,结构清晰。其次,构建效率飞升。一条命令就能打出所有渠道的包,比如gradlew assembleRelease,或者只打某个风味的包gradlew assembleOemARelease。最后,配置灵活度极高。你可以在风味里配置不同的签名、混淆规则、BuildConfig常量、AndroidManifest中的元数据,真正做到“一份代码,多种形态”。
我经历过一个项目,需要为十几家硬件厂商做定制,每家厂商的硬件芯片(chip)和品牌定制(oem)需求都不同。如果没有productFlavors,项目早就失控了。接下来,我就带你从零开始,手把手搭建一套成熟的多渠道打包体系,并分享我踩过坑之后总结的优化技巧。
2. 实战第一步:构建维度的艺术
开始配置前,我们得先理解一个核心概念:flavorDimensions,也就是风味维度。维度是什么?你可以把它看作是给风味分类的“标签”或“坐标系”。比如,你的App差异可能来自两个方面:一是底层硬件平台(比如用高通芯片还是MTK芯片),二是客户品牌(比如是为客户A还是客户B定制的)。那么你就可以定义两个维度:“chip”和“oem”。
定义维度是第一步,必须在productFlavors之前。在你的app/build.gradle文件的android块里,这样写:
android {
...
// 1. 定义风味维度
flavorDimensions "chip", "oem"
}
这里定义了两个维度:chip和oem。顺序很重要!Gradle会按照这个顺序来确定构建变体(Variant)的优先级和命名。当组合风味时,高优先级的维度(靠前的)会覆盖低优先级维度中相同的配置(比如资源文件)。
接下来,我们就可以在维度下创建具体的“风味”了。每个风味都必须归属于一个维度。这就好比说,“高通芯片”(风味)属于“硬件平台”(维度),“客户A定制版”(风味)属于“品牌”(维度)。
android {
flavorDimensions "chip", "oem"
productFlavors {
// 属于‘chip’维度的风味
qcom {
dimension "chip"
// 可以为高通芯片配置特定的NDK abiFilters
ndk {
abiFilters "arm64-v8a", "armeabi-v7a"
}
}
mtk {
dimension "chip"
// MTK平台可能只需要armv7
ndk {
abiFilters "armeabi-v7a"
}
}
// 属于‘oem’维度的风味
clientA {
dimension "oem"
// 为不同客户分配不同的应用ID后缀,可以同时安装
applicationIdSuffix ".clienta"
// 在BuildConfig中生成一个常量,用于代码逻辑判断
buildConfigField "String", "CLIENT_NAME", "\"ClientA\""
}
clientB {
dimension "oem"
applicationIdSuffix ".clientb"
buildConfigFiel

141

被折叠的 条评论
为什么被折叠?



