---
读书笔记之二
---

#### 目录

1. 修改生成的 apk 文件名
2. 动态配置 AndroidManifest 文件
3. 自定义 BuildConfig
4. 动态添加自定义的资源
5. Java 编译选项

#### 修改生成的 apk 文件名

既然要修改生成的 apk 文件名，那么就要修改 Android Gradle 打包的输出。为了解决这个问题，Android 对象为我们提供了三个熟悉：applicationVariants（仅仅适用于 Android 应用 Gradle 插件）、libraryVariants（仅仅适用于 Android 库 Gradle 插件）、testVariants（以上两种 Gradle 插件都适用）。

以上三个属性返回的都是 DomainObjectSet 对象集合，里面的元素分别是 ApplicationVariant、LibraryVariant 和 TestVariant。这三个元素的名字直译来意思是变体，通俗的讲它们就是 Android 构建的产物。它们基于 BuildType 和 ProductFlavor 生成的产物。BuildType 即构建类型，Android 已经内置了 debug 和 release 两种构建类型。ProductFlavor 允许我们根据不同的情况生成多个不同的 APK 包，如果不针对我们自定义的 ProductFlavor 单独配置的话，会为这个 ProductFlavor 使用默认的 defaultConfig 的配置。defaultConfig 里面有我们熟悉的 verisonCode、versionName 等等。

```groovy
android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.demoproject"
        minSdkVersion 26
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        flavorDimensions "versionCode"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
            zipAlignEnabled true
        }
        debug {
            
        }
    }

    productFlavors {
        google {

        }
    }

    applicationVariants.all { variant ->
        variant.outputs.each { output ->
            def timeNow = new Date().format("yyyyMMdd")
            def newName = 'app' + '_' + variant.buildType.name + '_' + variant.versionCode + "_" + timeNow + '.apk'
            output.outputFileName = newName
        }
    }
}
```

 build debug 包生成的 apk 文件名为 app_debug_1_20190521.apk。

#### 动态配置 AndroidManifest 文件

动态配置 AndroidManifest 文件，顾名思义就是可以在构建的过程中，动态修改 AndroidManifest 文件中的一些内容。Android Gradle 提供了非常便捷的办法，那就是使用 manifestPlaceholder，即 Manifest 占位符。

ManifestPlaceholders 是 ProductFlavor 的一个属性，是一个 Map 类型，所以我们可以同时配置很多个占位符。

比如想把 application 下的 meta-data 的 name 替换掉：

```
<meta-data android:name="CHANNEL_ID" android:value="${CHANNEL}"/>
```

```groovy
    productFlavors {
        google {
            manifestPlaceholders.put("CHANNEL", "google")
        }
        baidu {
            manifestPlaceholders.put("CHANNEL","baidu")
        }
    }
```

但是如果，渠道很多的情况下，一个一个添加还是很繁琐的，那就需要遍历添加了：

```groovy
    productFlavors {
        google {
        }
        baidu {
        }
    }

    productFlavors.all { flavor ->
        manifestPlaceholders.put("CHANNEL", name)
    }
```

#### 自定义 BuildConfig

```java
/**
 * Automatically generated file. DO NOT MODIFY
 */
package com.example.demoproject;

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.example.demoproject";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "google";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
}
```

BuildConfig 这个类是自动生成的，不可以修改，但是我们可以往里面添加我们自定义的常量，Android Gradle 提供了 buildConfigField。

```groovy
    productFlavors {
        google {
            buildConfigField('String', 'name', '"Omooo"')
        }
        baidu {
            buildConfigField('String', 'name', '"Omooo"')
        }
    }
```

**注意：**值是放在单引号里面的，所以是 '"Omooo"'！

上面都是在渠道（ProductFlavor）中配置的，其实在构建类型（BuildType）里面也是可以配置的：

```groovy
    buildTypes {
        debug {
            buildConfigField('String', 'name', '"Omooo"')
        }
    }
```

#### 动态添加自定义的资源

这里讲的自定义资源，是专门针对 res/values 类型资源的，它们不光可以在 res/values 文件夹里使用 xml 的方式定义，还可以在我们的 Android Gradle 中定义，大大增加了构建的灵活性。

实现这一功能的正是 resValue 方法，它在 BuildType 和 ProductFlavor 这两个对象中都存在。

```groovy
    productFlavors {
        google {
            resValue('string','name','Omooo_Google')
        }
        baidu {
            resValue('string','name','Omooo_Baidu')
        }
    }
```

然后我们在 app/build/generated/res/resValues/google/debug/values 下查看自动生成的资源文件。

上面演示的是 string 类型，当然也可以使用 id、bool、demin、color 等类型，和 buildConfigField 一样，它也是可以在 BuildType 中使用的。

#### Java 编译选项

```groovy
    compileOptions {
      	encoding = 'utf-8'
        targetCompatibility = JavaVersion.VERSION_1_8
        sourceCompatibility = JavaVersion.VERSION_1_8
    }
```

Android 对象提供了一个 compileOptions 方法，它接受一个闭包作为参数，来对 Java 编译选项进行配置。

compileOptions 是编译配置，它提供了三个属性，分别是 encoding、sourceCompatibility、targetCompatibility。sourceCompatibility 是配置 Java 源代码的编译级别，targetCompatibility 是配置生成的 Java 字节码的版本。