In actual projects, Android Gradle Plugin will be applied. According to the responsibilities of actual project modules, the following four types of plug-ins can be applied.

1, apply the plugin: The actual prototype of ‘com.android.application’ is: Com. Android. Build. Gradle. AppExtension, said the project Module type for android App Module, corresponding to build generated file. Type apk file.

2, apply the plugin: The actual prototype for ‘com.android.library’ is: Com. Android. Build. Gradle. LibraryExtension, said the project Module type for the android Library Module, the corresponding file to build generation. Arr types of files.

3, apply the plugin: The actual prototype for ‘com.android.test’ is: Com. Android. Build. Gradle. TestExtension, said the project Module type for android test Module, can through targetProjectPath designated project in a single Module, used for unit testing for the project.

4, apply the plugin: The actual prototype of ‘com.android.feature’ is: Com. Android. Build. Gradle. FeatureExtension, said the project Module type for android feature Module, mainly used in a single Module to realize feature, to support the android Instant Apps.

The most common of these are the Application and Library plug-in types in general projects.

After the specific Android Gradle Plugin type is applied in the project module, the corresponding configuration can be started, such as the most common configuration items as follows:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.happycorn"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner". } buildTypes { release { minifyEnabledfalse
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}... }... } dependencies { implementation fileTree(dir:'libs', include: ['*.jar'])... }Copy the code

You can hold down CTRL and hover the mouse to view the configuration prototype.

Different types of Android Gradle Plugin correspond to different implementation prototypes and external configuration items.

Similarly, tracing the defaultConfig{} stereotype information leads to the following stereotype description.

/**
     * Specifies defaults for variant properties that the Android plugin applies to all build
     * variants.
     *
     * <p>You can override any <code>defaultConfig</code> property when <a
     * href="https://developer.android.com/studio/build/build-variants.html#product-flavors">
     * configuring product flavors</a>.
     *
     * <p>For more information about the properties you can configure in this block, see {@link
     * ProductFlavor}.
     */
    public void defaultConfig(Action<DefaultConfig> action) {
        checkWritability();
        action.execute(defaultConfig);
    }
Copy the code

DefaultConfig {} specifies the default value for the variant attribute. The Android Plugin can apply the default value of the specified variant attribute to all variants.

To perform the action. The execute (defaultConfig); The specific configuration for the DefaultConfig object is specified.

In actual project development, we often pay attention to the configuration items here, and the corresponding meaning and function of each configuration item.

First, you can query DefaultConfig in the Android Gradle DSL document. See: google.github. IO /android-gra…

This document lists the externally configurable properties, methods, and corresponding descriptions of the DefaultConfig object. You may need to pay attention to the configuration in detail.

In build.gradle, defaultConfig{} is usually configured in the form of a key value. In fact, it can also be configured in the form of a corresponding method prototype. The effect is equivalent, but the condition is that the method prototype does exist. Gradle reports an error. Such as:

defaultConfig { ... minSdkVersion 15 ... } is equivalent to defaultConfig {... minSdkVersion(15) ... }Copy the code

Properties configured in defaultConfig{} are generated by default at build time in the corresponding variants directory in the buildConfig.java file, which converts the previously configured properties into the corresponding Java constant form.

As shown in build.gradle:

android {
    compileSdkVersion 28

    defaultConfig {
        applicationId "com.happycorn"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
    }


    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }

        debug {

        }
    }


    flavorDimensions "default"

    productFlavors {
        demo {
            applicationIdSuffix "demo"
        }

        full {
            applicationIdSuffix "full"}}}Copy the code

Run the./gradlew assembleFull command to generate the BuildConfig file:

If buildType is debug, the corresponding BuildConfig file is:

/**
 * Automatically generated file. DO NOT MODIFY
 */
package com.happycorn;

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.happycorn.full";
  public static final String BUILD_TYPE = "debug";
  public static final String FLAVOR = "full";
  public static final int VERSION_CODE = 1;
  public static final String VERSION_NAME = "1.0";
}
Copy the code

BuildConfig files are at the JAVA source level and will be compiled and packaged into packages at build time, which can be used directly in the corresponding modules.

With this feature, we can often make logical judgment on the variation environment in the project and deal with the corresponding logic. For example, check whether it is DEBUG and output logs.

if (BuildConfig.DEBUG) {
    Log.d(TAG, "come here...");
}
Copy the code

In addition, the DefaultConfig object provides a buildConfigField(Type, name, Value) method specifically for adding new properties to buildConfig.java classes generated at build time.

DefaultConfig {} with buildConfigField(type, name, value) add the following.

defaultConfig { ... InnerTest = project.hasProperty(innerTest = project.hasProperty('innertest')? innertest :'false'
    buildConfigField "boolean"."INNER_TEST", innerTest // Adds the corresponding module name, buildConfigField"String"."MODULE_NAME"."\"${project.name}\ ""
}
Copy the code

The generated buildConfig.java will have corresponding properties generated.

public final class BuildConfig {
  ...
  // Fields from default config.
  public static final boolean INNER_TEST = false;
  public static final String MODULE_NAME = "app";
}
Copy the code

Using this feature, you can skillfully deal with some specific problems in the project. Refer to the two appended attributes in the example above. For example, when Gradle is built, we pass in the -p command key value, which can be added in defaultConfig{} to automatically generate the corresponding properties in buildconfig.java, and then do some special processing in the program.

if(buildconfig.inner_test) {// Some logic that the user tests... }Copy the code

Another example: when calling the project log system, you can pass in the corresponding module name to realize the log filtering display of each module. At this point you can get the module name from project.name and append it to buildConfig.java. It is then available when the log library is called.

CLog.e(BuildConfig.MODULE_NAME, TAG, e)
Copy the code

Further, we can add attributes to buildconfig.java using the defaultConfig{} configuration for each module here:

allprojects {
    ...
    afterEvaluate { project ->
        def android = project.extensions.findByName("android")
        if(android ! = null){ def defaultConfig = android["defaultConfig"]
            defaultConfig.buildConfigField("String"."MODULE_NAME"."\"${project.name}\ "")}}}Copy the code

Makes the overall usage seem very flexible.

In addition to the buildConfigField(type, name, value) method, there is a utility method resValue(String Type, String name, String Value). ResValue (String Type, String Name, String Value) is equivalent to adding a resource to the module RES/Values.

For example, add resources in buildType to debug:

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }

    debug {
        resValue("string"."app_name_debug"."HappyCornDebug")
        resValue("integer"."token"."365")}}Copy the code

After compilation, the corresponding variant directory structure will generate the resource file, and the corresponding resource key value.

Where this resource is needed in the project can also be accessed directly:

getResources().getString(R.string.app_name_debug);
getResources().getInteger(R.integer.token);
Copy the code

If the properties configured in defaultConfig{} are the same as those configured in the Flavor of productFlavors, Android Gradle can look forward to productFlavors. DefaultConfig {} overwrites the corresponding configuration in defaultConfig{}. Except for “applicationIdSuffix” (which is still the appended form).

In real project requirements, the external input parameter key values or values obtained through Gradle/Android Gradle scripts, combined with defaultConfig{} configuration, variants, and the corresponding generated buildConfig. Java or resource files, implement some specific scenario requirements. The whole can be very flexible and have a certain amount of skill.