To summarize gradle briefly:

Gradle is a build tool that helps you manage differences, dependencies, build, package, and deploy in your project…… You can define build logic that meets your needs and write it to build.gradle for later reuse.

Gradle is not a programming language. It does not help you implement any of the actual functions in your software

Gradle basic

When you create a new project with Android Studio, by default you generate a bunch of gradle stuff, the most important of which is a build.gradle file that looks like this:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    buildToolsVersion "26.0.0"

    defaultConfig {
        minSdkVersion 19
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

dependencies {
    compile 'com. Android. Support: support - v4:26.0 +'
}
Copy the code

Reading:

The apply plugin:: specifies which plugin to use. Common values in development are:'com.android.application': Android APP plugin (package is.apk file)'com.android.library':Android library plug-in (packaged as an.aar file)'java': common Java plugin (package is.jar file) I currently use also: Kotlin-Android: Kotlin Bugly. Gradle: Tencent Bugly Walle. Gradle: Meituan Walle packageCopy the code
Android {} is used to specify the properties of the Android package plug-in, including the following nodes: BuildToolsVersion (buildToolsVersionName) : Set the build tool version to be used at compile time. DefaultConfig: Set some default properties. The available properties are buildTypes(Debug, Release, Other +) and productFlavors(Google Store, Peandou, Xiaomi App Store). The final number of APKs that can be typed is buildTypes times productFlavors. The variable name of the build is productFlavors+buildTypes.Copy the code
Dependencies: External dependencies are handled in one line of code. Among them the compile fileTree (dir:'libs', include: ['*.jar'Jar files in the libs directory.Copy the code
buildscript {
    repositories {
        google()
        jcenter()
        mavenCentral()
    }
    dependencies {
        classpath 'com. Android. Tools. Build: gradle: 3.2.1'}}Copy the code

Buildscript node, which basically means support for Maven, Google, and Gradle versions. If some other plug-ins are used, they also need to be declared here.

signingConfigs {
    myConfig {
        storeFile file("xxx.keystore")
        storePassword "123123"
        keyAlias "xxx"
        keyPassword "123123"
        v2SigningEnabled true}} buildTypes{release {// apply myConfig signingConfig SigningConfigs. myConfig minifyEnabledtrue
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'}}Copy the code
Signature configuration: storeFile: keystore file storePassword: password keyAlias: alias keyPassword: alias password v2SigningEnabled: Enable the V2 signature scheme minifyEnabled: Whether to enable shrinkResources: Whether to remove unnecessary resource files. ShrinkResources depend on minifyEnabled and must be used together with minifyEnabledCopy the code

The above is just the simplest gradle configuration. In the actual project, our app will be very complicated. For example, we may reference not only some JAR files, but also some Android Library projects and some.so files. There are currently dozens of Android platforms, large and small, and Gradle can handle it with a few other configurations. Gradle, by the way, is strongly supported by Google.

The advanced configuration

Configure the Manifest variable

Many third-party SDKS need to configure some of your key information in androidmanifest.xml. Take Rongcloud as an example, the key of the test package is different from that of the formal package, so you can write:

<meta-data
    android:name="RONG_CLOUD_APP_KEY"
    android:value="${rongKey}" />
Copy the code

Then add different information to each version of productFlavors, so that the appkeys for each package you make are different.

manifestPlaceholders = [rongKey: "8luwapkv8jrrl"]
Copy the code

The code reads variables

Sometimes we want to set different values of the same variable according to different versions. The most common use scenario is the Log utility class, which determines whether to print logs by setting different values of isDubug. Others include obtaining package names and channel names

buildConfigField "String"."PlatformSource"."\"Google\""
buildConfigField "String"."showProjName"."\"TestProj\""
Copy the code

The last call: BuildConfig. PlatformSource

public final class BuildConfig {
  public static final boolean DEBUG = Boolean.parseBoolean("true");
  public static final String APPLICATION_ID = "com.xxx.xxxx";
  public static final String BUILD_TYPE = "debug";
  public static final String PlatformSource = "Google";
  public static final String showProjName = "TestProj";
Copy the code

The above is added to defaultConfig, and adding buildTypes or productFlavors will have different values for different builds. If you configure different Applicationids, you can install different builds of applications on the same phone at the same time.

ProductFlavors {// Domestic version China {applicationId"com.shy.china"
        versionCode "2.0.0"
        versionName "30"} // Korean version Korea {applicationId"com.shy.korea"
        versionCode "1.0.0"
        versionName "1"}}Copy the code

BuildTypes and productFlavors are similar definitions, but they differ in:

  • BuildType doesn’t change the application code, they just deal with different things, and you can use buildType to get more technical details (for example: Build Optimization,log level minifyEnabled, etc.), but the content of the app will not change.

  • The productFlavor configuration can change the contents of your app (think package, buildType can’t change applicationId).

BuildVariants variant

BuildTypes +productFlavors is a combination of buildTypes and productFlavors. BuildTypes buildTypes are debug(test),pre(pre-release), and release(online). ProductFlavors is a variety of flavors. Combining the two will build different versions of APK (total number of APKs = number of build types * number of channels). Look at the picture:

  • BuildTypes builds types
    buildTypes {
        release {
            multiDexKeepProguard file('multidex-config.pro')
            minifyEnabled true// Whether to enable shrinkResourcestrue
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            multiDexKeepProguard file('multidex-config.pro')
            minifyEnabled falseProguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}Copy the code
  • ProductFlavors multidimensional

    FlavorDimensions is used when you need to differentiate app versions from multiple dimensions, such as paid or channelled

    flavorDimensions "channel"."env"

    productFlavors {
        china {
            dimension "channel"
            applicationId "com.shy.china"
            versionCode project.CHINA_VERSION_CODE as int
            versionName project.CHINA_VERSION_NAME
            signingConfig signingConfigs.china

            buildConfigField "String"."PlatformSource"."\"china\""
            buildConfigField "String"."showProjName"."\"projName_china\""

            manifestPlaceholders = [
                    package_name : applicationId,
                    JPUSH_PKGNAME: applicationId,
                    JPUSH_APPKEY : "xxxxxxxxxxxx"// the package name registered on JPush corresponds to appkey.jpush_channel:"developer-default"]} Korea {dimension"channel"
            applicationId "com.shy.korea"

            versionCode project.KOREA_VERSION_CODE as int
            versionName project.KOREA_VERSION_NAME
            signingConfig signingConfigs.korea

            manifestPlaceholders = [
                    package_name : applicationId,
                    JPUSH_PKGNAME: applicationId,
                    JPUSH_APPKEY : "xxxxxxx"// the package name registered on JPush corresponds to appkey.jpush_channel:"developer-default"] buildConfigField"String"."PlatformSource"."\"korea\""
            buildConfigField "String"."showProjName"."\"projName_korea\""
        }
 
        dev {
            dimension "env"
        }
        pre {
            dimension "env"
        }
        produce {
            dimension "env"}}Copy the code

At this point in the build, will be generated in the BuildVariants 12 variant (total number = apk build number type channel number dimension number) :

ChinaDevRelease chinaPreDebug chinaPreRelease KoreaDevDebug (common) koreaDevRelease koreaPreDebug koreaPreRelease(common) koreaProduceDebug koreaProduceRelease(common)

Attention! warning:

FlavorDimensions must be added for each productFlavors, otherwise an error will be displayed

In gradle:3.0.0, build. Gradle must contain flavorDimensions, even if there is only one dimension

packaging

Generate all channel packages at once Open a command line window, go to the root directory of the project, and type

gradle assembleChinaProduceRelease


Other skills

1.Gradle task

Gradle Task is designed for repetitive manual tasks that are tedious and error-prone, such as batch modifying, copying, or renaming files. For example, the applicationVariants. All task can set various attributes for each build, such as changing the apK name generated by each build:

applicationVariants.all { variant ->
        variant.outputs.each { output ->
            output.outputFile = new File(
                    new File("${project.rootDir.absolutePath}/apk/"Chinadev-googleplay-1.0.0-20181126-193438. apk ()"${flavorName}-${channel}-${buildType}-v${versionName}-${buildTime}.apk)
        }
    }
Copy the code

2.Moudle dynamic dependency

In a componentized app, we may need to rely on different components in the test package and the formal package. For example, the test environment requires debugging modules, but the formal environment does not. If productFlavors is any of the following, the debugging module name is module-test

productFlavors {
    test{
    }
    publish{
    }
}
Copy the code

Add test to your dependencies:

ceshiCompile project(':module-test')

BuildTypes also applies, and can be used together or separately:

debugCompile project(':module-test')
ceshidebugCompile project(':module-test')
Copy the code

3. Define global variables

Create an ext_settings.gradle file in the project root directory:

ext {
    CHINA_VERSION_NAME = '2.0.0'
    KOREA_VERSION_NAME = '1.0.0'

    CHINA_VERSION_CODE = 20
    KOREA_VERSION_CODE = 1

    androidToolsVersion = '28.0.3'
    supportLibraryVersion = '27.1.1'

    fireBaseVersion = '12.0.1'
    minSdkVersion = 19
    androidSdkVersion = 27
    kotlin_version = '1.3.0'
    gradlePlugin = '3.2.1'
    sourceCompatibilityVersion = JavaVersion.VERSION_1_8
    targetCompatibilityVersion = JavaVersion.VERSION_1_8
}
Copy the code

Gradle can then be referenced in each module’s build.gradle via rootproject.ext:

defaultConfig {
    minSdkVersion rootProject.ext.minSdkVersion
    targetSdkVersion rootProject.ext.androidSdkVersion
}
Copy the code

Dependency can also be moved:

ext.deps = [
junit                : 'junit: junit: 4.12',
truth                : 'com.google.truth:truth:0.28',
recyclerview         : "com.android.support:recyclerview-v7:$supportLibraryVersion",]Copy the code

Call:

dependencies {
    implementation deps.recyclerview
}
Copy the code

4. Configure independent signature information & Configure files such as passwords in a unified manner

Sensitive information such as passwords and signatures can be stored uniformly without hard coding. In gradle.properies, we can define key-value at will.

STORE_FILE_PATH=.. /china.keystore STORE_PASSWORD=123456 KEY_ALIAS=china KEY_PASSWORD=test123
Copy the code
SigningConfigs {China {// Use gradle.properies configuration file(STORE_FILE_PATH) storePassword STORE_PASSWORD keyAlias KEY_ALIAS keyPassword KEY_PASSWORD v2SigningEnabledtrue} {//'korea.keystore')
            storePassword "123456"
            keyAlias "kkk"
            keyPassword "123456"
            v2SigningEnabled true}}Copy the code

5. Reduce compile errors and ignore Lint checks

    packagingOptions {
        //Espresso excludes
        exclude 'META-INF/DEPENDENCIES.txt'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/notice.txt'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/dependencies.txt'
        exclude 'the meta-inf/LGPL2.1'
        exclude 'LICENSE.txt'
    }
Copy the code
lintOptions {
        checkReleaseBuilds true
        abortOnError false
    }
Copy the code

6. Refer to the local AAR

1. Place the AAR file in a directory, for example in the Libs directory of a Module 2. In the build.gradle file of this module add:

api fileTree(include: ['*.aar'], dir: 'libs')
Copy the code

Finally attach: gradle Google official: developer.android.com/studio/buil… The translation version: avatarqing. Dead simple. IO/Gradle c-plug…

A summer night in Amphiboles Intro: A Japanese anime star, Wu Shi Ren, rescues a brothel woman and sees her sailing away in a boat. Song from the initial D movie episode, Rattan original too in this life will never dream of his wife will leave him, so whether the driver needs love, also from the Japanese god anime initial D

If there are mistakes, please point out that I correct in time!