flavorDimensions和productFlavors——安卓gradle

目录
1、前言
2、flavorDimensions 的意义
3、productFlavors的意义
4、productFlavor
5、写在最后
html

1、前言

有了前两篇博客的铺垫,咱们能够来分享下另外两个参数了 flavorDimensionsproductFlavors,而这两个参数成对出现,能够作一些差分化定义java

前两篇博客为:
一、defaultConfig——安卓gradle
二、buildTypes——安卓gradle
android

须要事先说明的是,接下来所说的 “意义” 并不是官方文档翻译,而是结合了小盆友本身的理解,会比较口语化。git

2、flavorDimensions 的意义

flavorDimensions 从单词字面理解知道是 “风味维度”,是须要结合 “产品风味(即productFlavors)” 来一块儿使用的。程序员

flavorDimensions 的使用会定义出维度,供接下来的 productFlavors 使用。咱们举个例子github

android {
	// 省略其余参数
	
	flavorDimensions('abi', 'version')
}
复制代码

使用上面代码,则会定义出两个维度:version 和 abi。一个参数一个维度,咱们把它形象化,就能够当作下面这样一张图。而他有什么做用,咱们看下一小节。 后端

若是三个参数就能够当作一个三维的空间坐标系,这里的坐标系只是一个形象化的体现。bash

3、productFlavors的意义

productFlavors 从字面了解是“产品风味”。他须要和一个风味维度对接,不然会报错。微信

接着咱们上面的例子,使用 productFlavors 定义维度上的风味,使用 dimension 关联。架构

android{
    // 其余参数
	
    flavorDimensions('abi', 'version')

    // 建立产品风味
    productFlavors {
        v1 {
            // 关联纬度
            dimension 'version'
        }

        v2 {
            dimension 'version'
        }

        v3 {
            dimension 'version'
        }

        x86 {
            dimension 'abi'
        }

        armV7 {
            dimension 'abi'
        }
    }
}
复制代码

经过上面这段代码,会造成下面这张图。在 abi 维度上关联了两个产品,即 “armV7” 和 “x86”,在 version 的维度上关联了三个产品,即 “v1”、“v2” 和 “v3”。

而这些维度的交织就会造成最终的风味,即咱们上面所标出来的 “armV7V1”、“armV7V2”、“armV7V3”、“x86V1”、“x86V2”、“x86V3”。

咱们能够根据不一样的风味,打出不一样的apk包,即可以实现一套核心代码打出多个有些差别的包。

更多的使用咱们在下篇博客讲解,咱们先了解下他可配置的参数。

4、productFlavor

productFlavors 下的每一个项最终形式是 productFlavor,即咱们上面说所的 “v1”,“v2”.....

一、productFlavor 存在形式

咱们知道,每一个配置最终会被映射为一个类,或是一个属性、或一个方法。productFlavor 也不例外,他会被映射为 com.android.build.gradle.internal.dsl.ProductFlavor,继承结构以下

二、productFlavor 的属性意义

咱们先来一个约定,避免使用的代码过于冗长。

android {
    productFlavors{
   		
        zincPower{
		// 咱们下面的 “使用方法” 代码都是基于这一块,除非特殊说明。
     	}
     	
    }
}
复制代码

2.1 applicationId

  • 类型:String
  • 描述:应用的id,这里会覆盖掉 defaultConfig 中配置的 applicationId。从而可让咱们打出不一样的apk包。

defaultConfig 的具体配置能够看小盆友的另外一篇博文,传送门

  • 使用方法:
zincPower {
    // applicationId 应用的包名,会覆盖 defaultConfig 中的 applicationId
    // applicationId 会替换 AndroidManifest.xml 中的 manifest 标签下 package 的 value
    applicationId "com.zinc.power"
	......省略其余配置
}
复制代码

2.2 applicationIdSuffix

  • 类型:String
  • 描述:会追加在 applicationId 字符串的后面,造成最终的包名。这样也能够达到一套代码多个包名的效果。
  • 使用方法:
zincPower {
	applicationIdSuffix '.debug'
}
复制代码

2.3 consumerProguardFiles

  • 类型:List< File >
  • 描述:这个属性只做用于咱们建立的 library 中,包括咱们以aar形式导入的 library ,或是直接建立的 library。它的做用是,负责该 library 被进行编译时的混淆规则,咱们在 主App 的模块下则能够不用再管理各个 library 的混淆规则,会直接使用各个 library 的混淆规则文件。
  • 使用方法:
zincPower {
	consumerProguardFiles 'consumer-rules.pro'
	......省略其余配置
}

// 由于该属性是一个 List<File> 类型,若是须要多个文件配置,则以下所示
zincPower {
	consumerProguardFiles 'consumer-rules.pro','zincPower-rules.pro'
	......省略其余配置
}
复制代码

2.4 dimension

  • 类型:String
  • 描述:风味的维度,指定咱们当前风味所所属的维度。一个风味必需要有一个维度,并且也只能关联一个维度。 不然会报如下错误
ERROR: Flavor 'v1' has no flavor dimension.
复制代码
  • 使用方法:
zincPower {
    // 关联纬度
    dimension 'version'
    
	......省略其余配置
}
复制代码

2.5 externalNativeBuild

  • 类型:ExternalNativeBuildOptions
  • 描述:这里咱们设置 ndk 编译过程的一些参数。分为 cmake 和 ndkBuild 两个参数。
  • 使用方法:
zincPower {
    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"
         }
   }
}
复制代码

cmake 具体参数 传送门 ndkBuild 具体参数 传送门

2.6 javaCompileOptions

  • 类型:JavaCompileOptions
  • 描述:配置编译时 java 的一些参数,例如咱们使用 annotationProcessor 时所须要的参数。
  • 使用方法:
zincPower {
    javaCompileOptions {
        annotationProcessorOptions{
    		arguments = []
    		classNames ''
    		....
    	}
    }
    ......省略其余配置
}
复制代码

JavaCompileOptions 能够配置的具体参数,请进传送门

2.7 manifestPlaceholders

  • 类型:Map<String, Object>
  • 描述:配置能够在 AndroidManifest.xml 中替换的参数,咱们可使用这个参数配置不一样风味的 logo 和 app名字,以及友盟的参数,达到不一样风味的差别化配置
  • 使用方法:

咱们配置差别化的 logo 和 app名字,则能够在 gradle 中使用下面这段

android {
    flavorDimensions('abi', 'version')
    productFlavors {
    	// 省略其余的风味配置 
    	
        x86 {
            dimension 'abi'
    		
    		// 配置不一样的包名,达到能两个风味能共存
            applicationId 'com.zinc.bear'
    
            manifestPlaceholders = [
                    logo    : "@drawable/logo_bear",
                    appName : "bear",
            ]
    
    		// 配置签名
            signingConfig signingConfigs.jiangpengyong
        }
    
        armV7 {
            dimension 'abi'
    
    		// 配置不一样的包名,达到能两个风味能共存
            applicationId 'com.zinc.shark'
    
            manifestPlaceholders = [
                    logo    : "@drawable/logo_shark",
                    appName : "shark",
            ]
    
    		// 配置签名
            signingConfig signingConfigs.xiaopenyou
        }
    }
}
复制代码

logo的资源图

而后在 AndroidManifest.xml 中使用,使用 ${你配置的变量名}

<application android:allowBackup="true" android:icon="${logo}" android:label="${appName}" android:roundIcon="${logo}" android:supportsRtl="true" android:theme="@style/AppTheme">
......
复制代码

最终分别运行后,咱们能够看到以下效果

2.8 matchingFallbacks

  • 类型:List< String >
  • 描述:用于处理引入的 library 中存在不匹配的风味状况。
  • 使用方法:

举个例子: 咱们有一个 x86 的风味 在引入一个 library,而 library 中存在一样的风味维度,可是没有相同产品风味,这样会致使无法匹配,此时,就须要用这个参数。代码以下:

app 下的 build.gradle

android {
    // 其余配置
	
    flavorDimensions('abi')
    // 建立产品风味
    productFlavors {
        x86 {
            dimension 'abi'
            matchingFallbacks = ['pro']
        }
}

dependencies {
	// 引入 flavor_x86 library
    x86Implementation project(':flavor_x86')
}
复制代码

flavor_x86 下的 build.gradle

android {
    // 存在相同的风味维度
    flavorDimensions('abi')
    // 没有相同的产品风味,须要使用 matchingFallbacks 选择须要的产品风味
    productFlavors {
        pro {
            dimension 'abi'
        }

        free{
            dimension 'abi'
        }
    }

}
复制代码

小盆友在github上有个demo,有所帮助就给star吧。

2.9 multiDexEnabled

64K 引用限制问题官方文档 传送门

  • 类型:Boolean
  • 描述:是否开启分包。由于安卓中方法索引值为两个字节,四位十六进制的一个数值,即[0, 0xffff],因此最大方法数为65536个。一旦超出了,就须要进行分包,因此咱们就须要开启这个参数。
  • 值得一提:咱们能够在 defaultConfig 中开启便可,就不须要每一个风味都写一遍,减小冗余。

为了不篇幅过长,使用方法请看小盆友的另外一片博文:defaultConfig——安卓gradle 的 3.8小节

2.10 multiDexKeepFile

  • 类型:File
  • 描述:将咱们须要的类打包进主包,即 classs.dex。咱们在第 2.9 小点,分享到使用了多 dex包处理,有时咱们须要将一些主要的类打包进主包,则可使用该属性。
  • 使用方法:
zincPower {
    multiDexKeepFile file('multidex-config.txt')
    ...
}
复制代码

multidex-config.txt 中的书写则以下,每个文件则为一行

com/example/MyClass.class
com/example/TestClass.class
复制代码

2.11 multiDexKeepProguard

  • 类型:File
  • 描述:将咱们须要的类打包进主包,和第 2.10 点的功能相同,区别在于写法。
  • 使用方法:
zincPower  {
    multiDexKeepFile file('multidex-config.pro')
    ...
}
复制代码

multidex-config.pro 中的写法以下

// 将会保留全部的在com.example package的类
-keep class com.example.** { *; }
复制代码

2.12 ndk

  • 类型:NdkOptions
  • 描述:用于abi过滤
  • 使用方法: 进行以下配置,编译出来的 Apk包只包含armeabi-v7a,不会包含其余的架构,例如 "X86"。
zincPower {
    // ndk中,目前只有 abiFilter 一个属性,因此 ndk 目前来讲只用于 abi 的过滤
    ndk {
        abiFilter 'armeabi-v7a'
    }
	...
}
复制代码

NdkOptions的具体可配参数见官方文档 传送门

2.13 proguardFiles

  • 类型:List< File >
  • 描述:配置混淆规则文件,只有 minifyEnabled 设置为 true 的时候会使用这个参数,文件中须要申明哪些文件不被优化和混淆。
  • 值得一提:由于被混淆后端代码,类名和方法名都会有所变化,因此进行反射会失败,这是咱们就须要进行申明他们不被混淆。(这里只是举了使用这个参数的一个场景,若是应用原本是正常的,开了混淆后,出现了莫名奇妙的bug,那就思考下是否由于混淆致使了这一bug
  • 使用方法:
zincPower {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
复制代码

2.14 signingConfig

  • 类型:SigningConfig

SigningConfig 的可配置参数 传送门

  • 描述:配置签名配置。apk包能被安装是须要被签名的,咱们直接运行的时候,是使用了系统默认的签名证书,当咱们要发布release包时,则须要使用属于我的或企业的签名。
  • 使用方法:

(1)咱们须要先在项目根目录下建立一个 keystore.properties 文件,在文件中写入对应的配置,如图所示

(2)在应用级的 build.gradle 中使用以下代码

// 引入咱们在(1)中建立的配置
def keystorePropertiesFile = rootProject.file("keystore.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))

android {
    compileSdkVersion 28
    buildToolsVersion "29.0.1"
    defaultConfig {
       	// 省略一些配置...
    }

    signingConfigs {
        xiaopenyou {
        	// 使用 keystoreProperties 获取对应的参数
            keyAlias keystoreProperties['keyAlias2']
            keyPassword keystoreProperties['keyPassword2']
            storeFile file(keystoreProperties['storeFile2'])
            storePassword keystoreProperties['storePassword2']
        }
        // ...其余签名配置
    }

    buildTypes {
        // 省略一些配置...
    }

    flavorDimensions('abi', 'version')
    // 建立产品风味
    productFlavors {
		// 省略一些配置...
        armV7 {
            // 省略一些配置...
            signingConfig signingConfigs.xiaopenyou
        }
    }
}
复制代码

2.15 vectorDrawables

  • 类型:VectorDrawablesOptions
  • 描述:配置矢量图的参数
  • 使用方法: VectorDrawablesOptions 中只有两个参数,为 generatedDensitiesuseSupportLibrary。分别的用处以下
zincPower {
    vectorDrawables {
        // 若是 minSdkVersion 小于 21,只生成mdpi的png
        generatedDensities 'mdpi'

        // 设置为 true,会忽略 generatedDensities ,会加入svg兼容包,不会再产生png
        useSupportLibrary true
    }
}
复制代码

矢量图的用法,能够看小盆友的另外一片文章

2.16 versionCode

  • 类型:Integer
  • 描述:应用当前的版本值。和 versionName 的区别在小盆友看来,versionCode 是给程序员看的,versionName 是给产品经理和用户看的。
  • 使用方法:
zincPower {
    versionCode 1000
    ......
}
复制代码

2.17 versionName

  • 类型:String
  • 描述:应用版本。咱们一般所说的该应用的版本是“1.2.0”,则是由这个值配置的。
  • 使用方法:
zincPower {
    versionName "1.0.0"
    .....
}
复制代码

2.18 versionNameSuffix

  • 类型:String
  • 描述:追加在第 2.17 小点“版本”的后缀
  • 使用方法:
zincPower {
    // 若是 versionName "1.0.0" ,则最终的版本名为 1.0.0.test
    versionNameSuffix ".test"
    .....
}
复制代码

三、productFlavor 的方法意义

3.1 buildConfigField(type, name, value)

  • 描述:咱们能够在 BuildConfig 类中添加值,最终会在 BuildConfig 中添加以下一行代码。
// 值的注意的是 value 的值是原样放置,咱们经过使用方法一节来了解
<type> <name> = <value>
复制代码
  • 使用方法:
productFlavors {
    x86 {
        // 能够经过 BuildConfig 进行获取
        buildConfigField('String', 'name', '"XiaoPenYou"')
        buildConfigField('int', 'age', '26')
    	.....
    }
}
复制代码

最终会生成以下图的配置,咱们能够经过下面代码进行获取

String name = BuildConfig.name;
int age = BuildConfig.age;
复制代码

值的一提的是,咱们设置 String 类型的参数时,须要加上 "" 双引号(如例子中的name属性)。切记!

3.2 consumerProguardFile(proguardFile)

  • 描述:和上面分享的 2.3 小点的属性 consumerProguardFiles 是同样的做用。只是这里只能设置一个 混淆文件。
  • 使用方法:
zincPower {
    consumerProguardFile('consumer-rules.pro')
}
复制代码

3.3 consumerProguardFiles(proguardFiles)

  • 描述:和上面分享的 2.3 小点的属性 consumerProguardFiles 是同样的做用,并且也是多个混淆文件。
  • 使用方法:
zincPower {
    consumerProguardFile('consumer-rules.pro', 'zincPower-rules.pro',.....)
}
复制代码

3.4 maxSdkVersion(maxSdkVersion)

  • 描述:设置应用的最高支持版本,通常咱们不会进行设置
  • 使用方法:
zincPower {
    // 最高支持28版本
    minSdkVersion 28
}
复制代码

3.5 minSdkVersion(minSdkVersion)

  • 描述:设置应用的最低支持版本
  • 使用方法:
zincPower {
    // 最低支持19版本
    minSdkVersion 19
}
复制代码

3.6 missingDimensionStrategy(dimension, requestedValue)

  • 类似方法:missingDimensionStrategy(dimension, requestedValues) 区别在于第二个参数能够设置多个风味。
  • 参数说明: (1)dimension:维度 (2)requestedValue:风味(若是为 requestedValues 则是风味列表)
  • 描述:忽略在 Library 中的渠道设置,即维度(dimension)和风味(flavor),若是不进行忽略,在进行引入的时候会没法进行。
  • 使用方法:

咱们的项目结构以下

zinclibrarybuild.gradle 中编写了以下渠道配置

// 建立 风味维度
flavorDimensions('zinc', 'handsome')
// 建立产品风味
productFlavors {
    minApi13{
        dimension 'zinc'
    }
    minApi23{
        dimension 'zinc'
    }
    x86{
        dimension 'handsome'
    }
    arm64{
        dimension 'handsome'
    }
}
复制代码

此时若是直接在 appbuild.gradle 中添加依赖,同步时便会出错

dependencies {
    ...忽略其余依赖
    implementation project(":zinclibrary")
}
复制代码

因此咱们须要在 appbuild.gradle 中使用这个参数进行忽略 library 中带来的维度和风味,即便用以下代码

zincPower {
    missingDimensionStrategy 'zinc', 'minApi13', 'minApi23'
    missingDimensionStrategy 'handsome', 'x86', 'arm64'
}
复制代码

3.7 proguardFile(proguardFile)

  • 描述:添加混淆文件,和 2.13小点 的功能一致,只是传入的是一个文件,这里就再也不赘述
  • 使用方法:
zincPower {
    proguardFile 'proguard-rules.pro'
}
复制代码

3.10 proguardFiles(files)

  • 描述:添加混淆文件,和 2.13小点 的功能一致,这里就再也不赘述
  • 使用方法:
debug {
    proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
复制代码

3.11 resConfig(config)

  • 描述:保留的资源配置。
  • 使用用法:
zincPower {
    // 这样咱们编译出的apk中,只有 “默认” 和 “中文zh” 两种资源
    resConfig "zh"
}
复制代码

3.12 resConfigs(config)

  • 描述:保留的资源配置,和 resConfig 的区别在于,resConfigs 保留多个资源。
  • 使用用法:
zincPower {
    // 这样咱们编译出的apk中,只有 “默认” 、 “中文zh” 和 “英文en” 两种资源
    resConfigs "zh","en"
}
复制代码

3.13 resValue(type, name, value)

  • 描述:添加 value 资源
  • 使用用法:
zincPower {
    // 添加至 res/value,经过 R.string.age 获取
    resValue('string', 'age', '12year')
}
复制代码

3.14 setConsumerProguardFiles(proguardFileIterable)

  • 描述:和 2.3小点 的功能一致,只是写法不一样,这里就再也不赘述
  • 使用方法:
zincPower {
    consumerProguardFiles = [ 'consumer-rules.pro','zincPower-rules.pro' ]
}
复制代码

3.15 setProguardFiles(proguardFileIterable)

  • 描述:添加混淆文件,和 2.13小点 的功能一致,只是写法稍微不一样,这里就再也不赘述
  • 使用方法:
zincPower {
    proguardFiles = [getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro']
}
复制代码

3.16 targetSdkVersion(targetSdkVersion)

  • 描述:应用的目标版本。说明咱们已经对指定的版本进行了测试,在开发过程当中可使用至该版本的API,不然会被提示没法使用。若是不设置,则和 minSdkVersion 的值保持一致。
  • 使用用法:
zincPower {
    targetSdkVersion 28
}
复制代码

5、写在最后

Gradle 的配置文件看起来好像挺乱,实际上是由于咱们没有进行总体的梳理,所谓 “无知最可怕”

若是喜欢的话请给我一个赞,并关注我吧。文章中若有写的不妥的地方,请评论区或加我微信与我讨论吧,共同进步。

欢迎加我微信,进行更多的交流

若是以为文章有很大的帮助,快来赞扬一次吧😄

相关文章
相关标签/搜索