Gradle for Android ( 构建变体 )

  有时候咱们一个app须要有不一样的版本,不一样的版本又会使用不一样的配置,咱们可使用gradle进行管理。
  
  Build types
  
  Product flavors
  
  Build variants
  
  Signing configurations
  
  1、构建版本Build types:
  
  常见的构建版本有debug与release。
  
  复制代码
  
  buildTypes {
  
  release {
  
  minifyEnabled false
  
  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  
  }
  
  }
  
  复制代码
  
  自定义构建版本:
  
  复制代码
  
  custom {
  
  applicationIdSuffix ".custom"
  
  versionNameSuffix ".custom"
  
  minifyEnabled false
  
  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  
  signingConfig signingConfigs.readerDaquanConfig
  
  }
  
  复制代码
  
  除了debug构建版本不须要签名外,其它的都是须要配置签名的,否则没法运行在手机上,该版本定义了新的applicationId与版本号。不一样构建版本的applicationId以下:
  
  Debug: com.package
  
  Release: com.package
  
  Staging: com.package.staging
  
  也能够采用继承的方式:
  
  复制代码
  
  custom.initWith(buildTypes.debug)
  
  custom {
  
  applicationIdSuffix ".custom"
  
  versionNameSuffix ".custom"
  
  minifyEnabled false
  
  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  
  signingConfig signingConfigs.readerDaquanConfig
  
  }
  
  复制代码
  
  custom继承debug构建版本的配置,custom中的配置会覆盖debug的配置。
  
  在BuildConfig中添加变量
  
  复制代码
  
  custom {
  
  applicationIdSuffix ".custom"
  
  versionNameSuffix ".custom"
  
  buildConfigField("String", "name","\"custom app\"")
  
  buildConfigField("int", "id", "0")
  
  minifyEnabled false
  
  proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
  
  signingConfig signingConfigs.readerDaquanConfig
  
  }
  
  复制代码
  
  以后咱们能够看到:
  
  注意若是要添加的是String,那么双一号里面须要再一个双引号标识字符串"\"custom app\"",斜杆是对里面双引号进行转义。
  
  Source sets
  
  当建立了一个新的build type以后,Gradle也会建立一个新的source set。默认的source set目录会放在相同的Build Type的目录下。当你建立一个新的build type时,该目录不会自动建立,你必须在你使用代码与资源前本身为每个build type建立source set目录。
  
  三种buildType的目录结构以下:
  
  复制代码
  
  app
  
  └── src
  
  ├── debug
  
  │ ├── java
  
  │ │   └── com.package
  
  │ ├── res
  
  │ │ └── layout
  
  │ │       └── activity_main.xml
  
  │ └── AndroidManifest.xml
  
  ├── main
  
  │ ├── java
  
  │ │   └── com.package
  
  │ ├── res
  
  └── MainActivity.www.rmutk.net java
  
  └── Constants.java
  
  │ └── AndroidManifest.xml
  
  ├── custom
  
  │ ├── java
  
  │ │   └── com.package
  
  ├── drawable
  
  └── layout
  
  └── activity_main.xml
  
  │ ├── res
  
  │ │ └── layout
  
  │ │       └── activity_main.xml
  
  │ └── AndroidManifest.xml
  
  └── release
  
  ├── java
  
  │   └── com.package
  
  │       └── Constants.java
  
  └── AndroidManifest.xml
  
  复制代码
  
  假如咱们本身创建custom的source set
  
  咱们使用不一样的构建版本便会使用不一样的source set。当使用不一样的source sets的时候,资源文件的处理须要特殊的方式。Drawables和layout文件将会复写在main中的重名文件,可是values文件下的资源不会。gradle将会把这些资源连同main里面的资源一块儿合并。(若是出现资源重复异常,请clean一下工程)
  
  例如,在main中的string.xml为:
  
  <resources>
  
  <string name="app_name">BuildTypeProject</string>
  
  <string name="hello_name">BuildTypeHello</string>
  
  </resources>
  
  在custom版本中为:
  
  <resources>
  
  <string name="app_name"www.xcdeyiju.com>BuildTypeCustomProject</string>
  
  </resources>
  
  当咱们构建custom版本的时会合并为:
  
  <resources>
  
  <string name="app_name">BuildTypeCustomProject</string>
  
  <string name="hello_name">BuildTypeHello</string>
  
  </resources>
  
  当你建立一个新的构建版本而不是custom,最终的strings.xml将会是main目录下的strings.xml。
  
  manifest也和value文件下的文件同样。若是你为你的构建版本建立了一个manifest文件,那么你没必要要去拷贝在main文件下的manifest文件,你须要作的是添加标签。Android插件将会为你合并它们。
  
  可是须要注意,当咱们添加.java文件到custom版本中,你能够添加相同的类到debug和release版本,可是不能添加到main版本。若是你添加了,会抛出异常。这时候咱们若是构建custom版本,那么便会使用custom对应source set中的.java文件。
  
  依赖包
  
  每个构建版本都有本身的依赖包,gradle自动为每个构建的版本建立不一样的依赖配置。若是你想为debug版本添加一个logging框架,你能够这么作:
  
  复制代码
  
  dependencies {
  
  compile fileTree(dir: 'libs', include: ['www.osgjyl.com*.jar'])
  
  compile 'com.android.support:appcompat-v7:22.2.0'
  
  debugCompile 'de.mindpipe.android:android-logging-log4j:1.0.3'
  
  }
  
  复制代码
  
  product flavors
  
  不一样的生产版本。
  
  product flavors极大简化了基于相同的代码构建不一样版本的app。
  
  建立product flavors
  
  复制代码
  
  android {
  
  productFlavors {
  
  vivo {
  
  applicationId "vivo"
  
  versionCode 1
  
  minSdkVersion 15
  
  }
  
  oppo {
  
  applicationId "oppo"
  
  versionCode 2
  
  minSdkVersion 15
  
  }
  
  }
  
  }
  
  复制代码
  
  这时候AS 3.0以上会报错ERROR: All flavors must now belong to a named flavor dimension
  
  没有给它们设置一个风味维度,咱们能够加上
  
  flavorDimensions "default"
  
  复制代码
  
  flavorDimensions "default"
  
  android {
  
  productFlavors {
  
  vivo {
  
  applicationId www.oushengguoj.com "vivo"
  
  versionCode 1
  
  minSdkVersion 15
  
  }
  
  oppo {
  
  applicationId "oppo"
  
  versionCode 2
  
  minSdkVersion 15
  
  }
  
  }
  
  }
  
  复制代码
  
  给这些产品版本默认一个风味维度,具体有何做用,等会会讲。
  
  这时候咱们会在左下角的窗口看到这么多个变体:
  
  若是找不到该窗口,能够在这里打开:
  
  因为咱们以前在custom构建版本上设置了applicationIdSuffix ".custom",因此,当咱们运行oppoCustom版本的时候,applicationId为oppo.custom
  
  Source Set
  
  product Flavors也有本身的代码文件夹。建立一个特殊的版本就像建立一个文件夹那么简单。以下图所示:
  
  可是值得注意的是,咱们没法再vivo文件夹里相同的包中添加构建版本已经有的.java文件,添加了会报异常。而对于资源文件,咱们能够添加构建版本里面有的文件,可是这个产品版本所对应的目录的优先级低于Build type,也就是说,当Custom目录有一张图片,vivo目录也有一张图片,那么当咱们运行打包vivoCustom版本的时候,使用的是custom里面的图片。除非咱们创建的文件夹是vivoCustom,那么它的优先级便会是最高的。
  
  Multiflavor variants
  
  在某些状况下,你可能但愿建立一些联合的Product Flavors,这个时候便要使用到咱们刚刚所说的flavorDimensions 了。
  
  设想一下,假如咱们须要打包两个渠道的app:vivo和oppo,而这两个渠道的app各自有付费版与免费版,那么咱们就须要用到多维度了。
  
  首先定义两个维度:渠道channel,付费与免费:money
  
  flavorDimensions "channel","money"
  
  复制代码
  
  flavorDimensions www.xgjrfwsc.cn "channel","money"
  
  android {
  
  productFlavors {
  
  vivo {
  
  dimension "channel"
  
  applicationId "vivo"
  
  versionCode 1
  
  minSdkVersion 15
  
  }
  
  oppo {
  
  dimension "channel"
  
  applicationId "oppo"
  
  versionCode 2
  
  minSdkVersion 15
  
  }
  
  free {
  
  dimension "money"
  
  }
  
  vip {
  
  dimension www.yunyouuyl.com"money"
  
  }
  
  }
  
  }
  
  复制代码
  
  当你添加了flavor dimensions,你就须要为每一个flavor添加dimension,不然会提示错误。
  
  以后咱们能够看到这么多个变体:
  
  而咱们定义多个维度的顺序是很重要的,由于当你在各个维度各自定义了同一个常量的值,好比:buildConfigField("String", "name","\"custom app\""),老是以第一维度的为准。
  
  Build variants
  
  构建变体
  
  构建变体是构建版本和生产版本的结合体。当你建立了一个构建版本或者生产版本,一样的,新的变体也会被建立。
  
  像咱们上图便有这么多的变体:
  
  咱们能够在这个窗口进行切换,而后运行不一样的变体。
  
  tasks
  
  Android Plugin会为每个配置的Build Variant建立Tasks。一个新的Android App拥有Debug和Release两种Build Types,因此默认的就会有两个Task,一个是assembleDebug一个是assembleRelease来构建不一样的APK。当添加一个新的Build Type的时候,一个新的Task也就会被建立,一旦你开始添加Flavors,一整套Tasks就会被建立,由于每个BuildType的Tasks都会为每一个Product Flavor联合。
  
  Source sets
  
  构建变体也能够有本身的资源文件夹,举个例子,你能够有src/vivoVipCustom/java/。原理与上面的相似
  
  Resource and mainfest merging
  
  Android Plugin须要在打包前对Main的SourceSet以及BuildType的SourceSet进行一次Merge。并且Library工程也会提供额外的资源,它们也会被Merge,例如Manifest.xml等等。也会在其中声明一些权限等。
  
  Resource和Manifest.xml的优先级顺序以下:
  
  若是一个资源在main中和在flavor中定义了,那么那个在flavor中的资源有更高的优先级。这样那个在flavor文件夹中的资源将会被打包到apk。而在依赖项目申明的资源老是拥有最低优先级。
  
  固然,若是你创建的目录是变体的目录入:vivoVipCustom,那么它的优先级天然是高于Build type
  
  建立构建变体
  
  关于如何构建变量,上面已经说了,再也不重复。
  
  复制代码
  
  flavorDimensions www.yuchengyuLe.com"channel","money"
  
  android {
  
  productFlavors {
  
  vivo {
  
  dimension "channel"
  
  applicationId "vivo"
  
  versionCode 1
  
  minSdkVersion 15
  
  }
  
  oppo {
  
  dimension "channel"
  
  applicationId "oppo"
  
  versionCode 2
  
  minSdkVersion 15
  
  }
  
  free {
  
  dimension "money"
  
  resValue "color", "colorfree", "#ff8888"
  
  }
  
  vip {
  
  dimension "money"
  
  resValue "color", "colorfree", "#ff0000"
  
  }
  
  }
  
  }
  
  复制代码
  
  resValue "color", "colorfree", "#ff8888"表示添加颜色名为colorfree的颜色
  
  变体过滤器
  
  忽略某个变体也是可行的。这样你能够加速你的构建当使用assemble的时候,这样你列出的tasks将不会执行那么你不须要的变体。你可使用过滤器,在build.gradle中添加代码以下所示:
  
  复制代码
  
  android.variantFilter { variant ->
  
  if(variant.buildType.name.equals('release')) {
  
  variant.getFlavors().each() { flavor ->
  
  if (flavor.name.equals('vivo')) { variant.setIgnore(true);
  
  }
  
  }
  
  }
  
  }
  
  复制代码
  
  发现相关的变体不见了:
  
  Signing Configurations
  
  在你发布你的应用以前,你须要为你的app私钥签名。若是你有付费版和免费版,你须要有不一样的key去签名不一样的变体。这就是配置签名的好处。配置签名能够这样定义:
  
  复制代码
  
  android {
  
  signingConfigs {
  
  custom.initWith(signingConfigs.debug)
  
  release {
  
  storeFile file("release.keystore")
  
  storePassword"secretpassword"
  
  keyAlias "gradleforandroid"
  
  keyPassword "secretpassword"
  
  }
  
  }
  
  }
  
  复制代码
  
  在这个例子中,咱们建立了2个不一样的签名配置。debug配置是as默认的,其使用了公共的keystore和password,因此没有必要为debug版本建立签名配置了。custom配置使用了initWith()方法,其会复制其余的签名配置。这意味着custom和debug的key是同样的。
  
  release配置使用了storeFile,定义了key alias和密码。固然这不是一个好的选择,你须要在 Gradle properties文件中配置。
  
  当你定义了签名配置后,你须要应用它们。构建版本都有一个属性叫作signingConfig,你能够这么干:
  
  复制代码
  
  android {
  
  buildTypes {
  
  release {
  
  signingConfig signingConfigs.release
  
  }
  
  }
  
  }
  
  复制代码
  
  上例使用了buildTypes,可是你可能须要对每一个版本生成不一样的验证,你能够这么定义:
  
  复制代码
  
  android {
  
  productFlavors {
  
  vivo{
  
  signingConfig signingConfigs.release
  
  }
  
  }
  
  }
  
  复制代码
  
  当签名一个Flavor版本的时候,你须要重写BuildType中的签名配置。当须要使用相同的BuildType不一样版本的Flavors的签名时,能够经过下述方式:
  
  复制代码
  
  android {
  
  buildTypes {
  
  release {
  
  productFlavors.vivo.signingConfig signingConfigs.vivo
  
  productFlavors.oppo.signingConfig signingConfigs.oppo
  
  }
  
  }
  
  }
  
  复制代码
  
  上面这个例子展现了如何在vivo和oppo的Release版本使用不一样的签名,可是却不影响Debug和Custom的BuildType。java

相关文章
相关标签/搜索