Chapter4:创建构建Variant
- Variant 英文翻译:变体。
4.1 构建类型
在Gradle的Android插件中,构建类型用来定义如何构建一个应用或依赖库。可以在 buildTypes代码块 中定义:
android { buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } } }
minifyEnabled :清除无用资源。
创建构建类型:除了debug/release构建类型外,可以自定义构建类型,只需要在 buildTypes代码块 中新增一个类似debug/release的对象即可。
android { buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } staging{ applicationIdSuffix ".staging" versionNameSuffix "-staging" } } }
自定义构建类型staging定义了一个新的applicationId后缀,表示相同设备可以同时安装release版本和staging版本。版本名也添加了新的后缀,用于在同一设备上区分多个应用版本。
//另一种创建方式,复制一个已存在的构建类型并在其基础上覆写或定义额外属性。 staging.initWith(buildTypes.release) staging{ applicationIdSuffix ".staging" versionNameSuffix "-staging" }
源集:**一个源集(sorce set)就是一组源文件,他们会被一起执行和编译。**当创建一个新的构建类型时,Gradle会创建一个新的源集。
在Android Studio中需要手动创建源集的目录。
源集使得我们可以针对特定的构建类型覆写某些属性,为某些构建类型添加自定义代码,以及为不同的构建类型添加自定义布局或字符串。
注意:添加Java类到构建类型时时互相排斥的。比如添加了example.java到staging源集,可以往debug和release源集中加入example.java,但是不能添加example.java到main源集。
使用不同源集时,资源文件会被特殊处理。Drawables 和 layout 文件将完全覆盖在 main 源集中有相同名称的资源;values文件夹中的文件不会被覆盖,而是整合到main资源中,同一子属性会被非main源集中的替代。
<!--main源集--> <resources> <string name="app_name">main</string> <string name="other">abc</string> </resources> <!--staging源集--> <resources> <string name="app_name">staging</string> </resources> <!--合并后--> <resources> <string name="app_name">staging</string> <string name="other">abc</string> </resources>
依赖:每个构建类型都可以有自己的依赖。在依赖前加入源集的名称即可。
//在debug源集中定义的依赖 debugImplementation 'androidx.cardview:cardview:1.0.0' //在staging源集中定义的依赖 stagingImplementation 'androidx.cardview:cardview:1.0.0'
4.2 product flavor
与配置相同的App/Library的不同构建相反,product flavor用来创建不同版本。比如:免费版和收费版。product flavor简化了基于相同代码构建多个版本的应用的过程。当你需要一个全新的App,度已于已有的发布的App时,你需要用到product flavor。
创建product flavor:
在 productFlavor代码块 中添加新的product flavor:
android { flavorDimensions "version" productFlavors { red { flavorDimension "version" applicationId "com.virtual.red" versionCode 21 } blue { flavorDimension "version" applicationId "com.virtual.blue" minSdkVersion 24 versionCode 19 } } }
注意:新版Android Studio或要求为所有类型都指定的一个类型维度,否则会报错ERROR: All flavors must now belong to a named flavor dimension.
解决办法:添加
flavorDimensions "version"
。具体参考官方说明。源集:和建构类型相似,product flavor也可以创建自己的源集目录。甚至,可以为一个特定的构建类型和flavor的结合体创建文件夹,文件夹名称为 flavor名+构建类型名 ,比如 blueRelease,合并的文件夹比flavor文件夹和构建类型文件夹拥有更高的优先级。
多种定制版本:
举例一种情况,客户A和客户B想在他们的App中都有免费版和付费版,并且是基于相同代码、不同的品牌。创建4中不同的flavor需要多个拷贝,不是最佳做法。结合flavor维度可以高效的解决:
android{ flavorDimensions "color","price" productFlavors{ red{ flavorDimension "color" } bule{ flavorDimension "color" } free{ flavorDimension "price" } paid{ flavorDimension "price" } }
注意:flavor维度数组的顺序决定了那个flavor配置将被覆盖,color将覆盖price,该顺序也决定了variant的名称。比如:buleFreeDebug、buleFreeRelease、bulePaidDebug、bulePaidRelease、redFreeDebug、redFreeRelease、redPaidDebug、redPaidRelease。
4.3 构建variant
- 构建 variant 是构建类型和product flavor的结合的结果。当创建一个构建类型或product flavor时,新的variant 便会被创建。Android Studio在 Build variants 工具窗口中列举了所有的variant并允许切换,选中要构建的variant,Run时将允许该variant:
没有product flavor时variant将只包含构建类型。不可以没有构建类型。(Gradle的Android插件会默认创建debug构建类型。)
任务:
- Gradle 的 Android插件会为你配置的每一个构建variant创建任务。
- 使用 assemble+product flavor+构建类型 创建特定variant的APK(比如:assembleBlueDebug)。使用assemble创建所有variant的APKs。
源集:
构建variant是一个构建类型和一个或多个product flavor的结合体,可以有自己的源集文件夹。文件夹名称为 flavor名+构建类型名 。
对于资源和manifest文件的优先度:
Build type > Flavor >Main >Dependencies
关于manifest文件合并更详细的内容参考:官方文档
variant 过滤器:当你需要忽略某些variant时:1.会加快assemble命令构建所有variant的进程;2.任务列表不会被无需执行的任务污染;3.Android Studio的构建variant切换器中也不会出现过滤的构建variant。
android{...} //过滤掉blueRelease的variant构建 android.variantFilter{ variant -> if (variant.buildType.name.equals('release')){ variant.getFlavors().each(){ flavor-> if(flavor.name.equals('blue')){ variant.setIgnore(true); } } } }
签名配置:在发布App之前,需要用私钥给它签名。每个flavor要使用不同的私钥签名。
android{ signingConfigs{ staging.initWith(signingConfigs.debug) release{ storeFile file("release.keystore") storePassword "123456" keyAlias "gradleforandroid" keyPassword "654321" } } }
- Android插件会使用通用的 keystore和一个已知密码自动创建debug的签名配置,不需自己创建。
- 这里使用两种方式配置:1. .initWith() 方法从另一个签名配置中复制所有属性。2.realease通过storeFile来指定keystore文件的路径,之后定义秘钥别名和两个密码。
定义前面配置后,将配置用用到构建类型或flavor中。
//1.对于构建类型的签名配置 android{ buildTypes{ release{ signingConfig signingConfigs.release } } } //2.对于flavor的签名配置,会覆盖构建类型的签名配置 android{ productFlavors{ blue{ signingConfig signingConfigs.release } } } //3.在使用flavor是,为每个构建类型的每个flavor分配不同的秘钥 android{ buildTypes{ release{ productFlavors.red.signingConfig signingConfigs.red productFlavors.blue.signingConfig signingConfigs.blue } } }
4.4 参考资料
- Gradle For Android