前言:因为当前产品运营策略发生变化,需要把产品给当地运营商运营,所以就需要把App的名称和icon进行定制化改变,并且需要在app接口中增加运营商包的特定channelCode。因为要修改app的名称和icon所以不能够使用pick,所以我们选用productFlavors实现需要,下面进行讲解productFlavors用法。
一、 flavorDimensions
的意义
flavorDimensions
从字面理解知道是“风味维度”,是需要结合“产品风味"(即productFlavors
)来一起使用。
flavorDimensions 的使用会定义出维度,供接下来的productFlavors使用。下面举例说明:
在app:级别下的gradle文件中,加入flavorDimensions name
、icon
android {
//...
//有name、version两个风味维度
flavorDimensions "name","icon"
}
使用上面的代码,会定义出两个维度:name、icon。如下图:
如果三个参数就可以看成一个三维的空间坐标系,这里的坐标系只是一个形象化的体现。
二、productFlavors的意义
productFlavors 从字面了解是“产品风味”,需要和一个风味维度对应,否则会报错(Flavor '***' has no flavor dimension.
)。
下面进行举例说明:
flavorDimensions "name","icon"
productFlavors{
//wh产品,注意(这边的产品名字字母不能大写)
wh{
dimension "name"
manifestPlaceholders = [
appName : "武汉智慧",
]
}
sz{
dimension "name"
manifestPlaceholders = [
appName : "深圳智慧",
]
}
flower{
dimension "icon"
manifestPlaceholders = [
logo : "@mipmap/flower",
]
}
animal{
dimension "icon"
manifestPlaceholders = [
logo : "@mipmap/animal",
]
}
}
上面的代码可以得到如下图中的组合。
在android studio->Build Variants->Active Build Variant中可以看到如下图:
可以看到组合中增加了build Type这一维度,我们可以根据不同的风味,可以打出不同的apk包,便可以实现一套核心代码打出多个有差异的包。
三、productFlavor各属性\方法意义
3.1 dimension
- 类型:
String
- 意义: 产品的风味维度。一个风味必须要有一个风味维度,而且也只能关联一个维度。否则会报错:
Flavor '***' has no flavor dimension.
- 使用:
a{ dimension "name" }
3.2 applicationId
- 类型:
String
- 含义: 应用的
id
,这里会覆盖掉defaultConfig
中的配置的applicationId
。从而可以让我们打出不同的包。 - 使用:
a{ // applicationId 应用的包名,会覆盖 defaultConfig 中的 applicationId // applicationId 会替换 AndroidManifest.xml 中的 manifest 标签下 package 的 value applicationId "com.xyz.service" }
3.3 applicationIdSuffix
- 类型:
String
- 意义: 会追加在
applicationId
字符串的后面,形成最终的包名。这样也可以达到一套代码多个包名的效果。 - 使用:
a{ applicationIdSuffix '.a' }
3.4 applicationIdSuffix
- 类型:
List<File>
- 意义: 这个属性只作用于我们创建的library中,包括我们以arr形式导入的library,或是直接创建的library。它的作用是负责该library被进行编译时的混淆规则,我们在主app的模块下则可以不用再管理各个library的混淆规则,会直接使用各个library的混淆规则。
- 使用:
a{ consumerProguardFiles 'consumer-rules.pro','zincPower-rules.pro' }
3.5 externalNativeBuild
- 类型: ExternalNativeBuildOptions
- 意义: 设置ndk编译过程的一些参数。分为cmake和ndkBuild两个参数。
- 使用:
a{ externalNativeBuild { ndkBuild { // Passes an optional argument to ndk-build. arguments "NDK_MODULE_PATH+=../../third_party/modules" } // For ndk-build, instead use the ndkBuild block. cmake { // Passes optional arguments to CMake. arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang" // Sets a flag to enable format macro constants for the C compiler. cFlags "-D__STDC_FORMAT_MACROS" // Sets optional flags for the C++ compiler. cppFlags "-fexceptions", "-frtti" // Specifies the library and executable targets from your CMake project // that Gradle should build. targets "libexample-one", "my-executible-demo" } } }
3.6 javaCompileOptions
- 类型: JavaCompileOptions
- 意义: 配置编译时Java的一些参数,例如我们使用annotationProcessor时需要的参数。
- 使用:
a{ javaCompileOptions { annotationProcessorOptions{ arguments = [] classNames '' .... } } }
3.7 manifestPlaceholders
- 类型: Map<String,Object>
- 意义: 配置可以在AndroidManifest.xml 中替换的参数,我们可以使用这个参数配置不同的产品的logo和app名称,以及友盟的参数,达到不同产品的差异化配置。
- 使用:
- 配置参数
a{ dimension "name" manifestPlaceholders = [ appName : "武汉智慧", logo : "@mipmap/flower", ] }
- 在AndroidManifest.xml中使用,使用
${变量名}
<application //.... android:label="${appName}" android:roundIcon="${logo}" </application
- 配置参数
3.8 versionName
- 类型: String
- 意义: 应用版本。我们通常所说的该应用的版本号是"1.0.1",就是由这个值配置的。
- 使用:
a{ versionCode 1000 }
3.9 versionNameSuffix
- 类型: String
- 意义: 追加在第 3.8 “版本”的后缀
- 使用:
a{ // 如果 versionName "1.0.0" ,则最终的版本名为 1.0.0.test versionNameSuffix ".test" }
3.10 versionCode
- 类型: Integer
- 意义: 应用应用当前的版本值。
- 使用:
a{ versionCode 11 }
3.11 buildConfigField(type, name, value)
- 意义: 我们可以在 BuildConfig 类中添加值,最终会在 BuildConfig 中添加如下一行代码。
- 使用:
productFlavors {
a{
// 可以通过 BuildConfig 进行获取
buildConfigField('String', 'name', '"xiaomi"')
buildConfigField('int', 'age', '26')
.....
}
}
我们可以通过下面代码进行获取
String name = BuildConfig.name;
int age = BuildConfig.age;
这里有一点需要注意,我们设置String类型的参数时,需要加上""
双引号
3.12 resValue(type,name,value)
- 意义: 添加value资源
- 使用:
a{ // 添加至 res/value,通过 R.string.age 获取 resValue('string', 'age', '12year') }
3.13 matchingFallbacks
- 类型: List
- 意义: 用于处理引入的library中存在不匹配的风味情况。
- 使用:
举例: 我们有一个风味引入一个library,而library中存在同样的风味维度,但是没有相同产品风味,这样会导致无法匹配,此时,就需要用这个参数。
flavor_x86 下的 build.gradleandroid { // 其他配置 flavorDimensions('abi') // 创建产品风味 productFlavors { x86 { dimension 'abi' matchingFallbacks = ['pro'] } } dependencies { // 引入 flavor_x86 library x86Implementation project(':flavor_x86') }
android { // 存在相同的风味维度 flavorDimensions('abi') // 没有相同的产品风味,需要使用 matchingFallbacks 选择需要的产品风味 productFlavors { pro { dimension 'abi' } free{ dimension 'abi' } } }
3.14 missingDimensionStrategy(dimension, requestedValue)
- 参数说明:
- dimension: 维度
- requestedValue:渠道flavors
- 意义: 忽略在 Library 中的渠道设置,即维度(dimension)和风味(flavor),如果不进行忽略,在进行引入的时候会无法进行。
- 使用:
在 zinclibrary 的 build.gradle 中编写了如下渠道配置
此时如果直接在 app 的 build.gradle 中添加依赖,同步时便会出错// 创建 风味维度 flavorDimensions('zinc', 'handsome') // 创建产品风味 productFlavors { minApi13{ dimension 'zinc' } minApi23{ dimension 'zinc' } x86{ dimension 'handsome' } arm64{ dimension 'handsome' } }
所以我们需要在 app 的 build.gradle 中使用这个参数进行忽略 library 中带来的维度和风味,即使用如下代码dependencies { ...忽略其他依赖 implementation project(":zinclibrary") }
zincPower { missingDimensionStrategy 'zinc', 'minApi13', 'minApi23' missingDimensionStrategy 'handsome', 'x86', 'arm64' }