Gradle的介绍

gradle是什么

Gradle是一个基于Ant(Apache)和Maven(Ant)概念的项目自动化构建工具。他使用的语言是Groovy的特定领域语言(小语言即该语言不通用,只能用于特定的某个领域)来声明项目设置。在通俗一点解释就是软件开发的时候会用到一些第三方依赖的东西,同时版本发布的时候会打包、部署。在遇到一些特殊需求的时候,需要不同渠道等管理。如果我们不使用构建,单纯的人工来做这个事,就各种build,各种clean等等。这个时候使用构建的话,就大大减少了工作的流程和劳动力成本。


image.png

一个Android项目中gradle相关文件

image.png

如上图所示,红的部分的是一个项目中基本的gradle相关文件(我没有加入module)。这些文件在项目中的位置如下:

image.png

每一个文件说明

setting.gradle

include ':app'

声明包含了项目中的module,因为没有添加别的module,所以这里面只有一个app(app也是一个module,只不过是application级别的)。

gradle.properties

在项目根目录下,内容如下:

# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
###################################################
#############  gradle 优化(确实快了不少) #############
###################################################
# Project-wide Gradle settings.
# IDE (e.g. Android Studio) users:
# Settings specified in this file will override any Gradle settings
# configured through the IDE.
# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html
# The Gradle daemon aims to improve the startup and execution time of Gdradle.
# When set to true the Gradle daemon is to run the build.
# TODO: disable daemon on CI, since builds should be clean and reliable on servers
org.gradle.daemon=true
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx10248m -XX:MaxPermSize=256m
org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
org.gradle.parallel=true
# Enables new incubating mode that makes Gradle selective when configuring projects.
# Only relevant projects are configured which results in faster builds for large multi-projects.
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:configuration_on_demand
org.gradle.configureondemand=true
# 版本编译配置
ANDROID_BUILD_MIN_SDK_VERSION=15
ANDROID_BUILD_TARGET_SDK_VERSION=26
ANDROID_BUILD_SDK_VERSION=26
ANDROID_BUILD_TOOLS_VERSION=26.0.0
# 版本号、包名等配置
APPLICATION_ID=com.kotlin.anonyper.testapplication
ANDROID_BUILD_VER_CODE=1
ANDROID_BUILD_VER_NAME=1.0

# 解决RN64位兼容
android.useDeprecatedNdk=true
#java版本
JAVA_VERSION=1.8
#Android Plugin for Gradle的版本
GRADLE_VERSION=3.0.1

上面我加入了很多系统中用到的参数,比如编译的版本,比如包名、版本号等,在里面声明之后,就可以在module中的build.gradle中通过project.getProperties().get("xxx")使用了,如下:

//key为 gradle.properties里定义的变量
//编译的sdk版本
compileSdkVersion project.getProperties().get("ANDROID_BUILD_SDK_VERSION")

具体用法参见Android项目框架思考--配置文件。

gradle-wrapper.properties

该文件在项目根目录下的gradle/wrapper下面,该文件夹下有两个文件,一个是gradle-wrapper.jar(Gradle Wrapper的功能包,在安装AndroidStudio的时候会安装到系统中,每一次新new一个项目时,都会copy一份到项目的该文件夹下),一个是gradle-wrapper.properties,该文件指定了我们项目要用什么版本的Gradle,以及从哪里下载,下载之后存放到哪里。

#Wed Nov 07 15:23:59 CST 2018
distributionBase=GRADLE_USER_HOME//下载gradle压缩包存放的根目录,一般是~/.gradle (Mac)
distributionPath=wrapper/dists//下载的之后解压的路径
zipStoreBase=GRADLE_USER_HOME 压缩包的主路径
zipStorePath=wrapper/dists //压缩包的存放路径
distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip//下载路径
gradle本地存放路径

我们在初次build一个导入的项目的时候,有的时候进度条会一直停留在Building XXX Gradle project info,这是因为我们本地没有对应版本的gradle功能包,但是下载时需要翻墙,所以会一直卡在这个地方,解决的最简单途径就是把其他已经build成功的项目的gradle-wrapper.properties文件拿过来替换一下。

项目根目录下的build.gradle

此文件存在项目的根目录下,主要定义了项目module用到仓库地址,编译Android用的gradle版本,也可以在此定义一些自定义属性:

def GRADLE_VERSION = project.getProperties().get("GRADLE_VERSION")//读取gradle.properties中定义的参数
buildscript {//声明gradle脚本本身所需要的资源库

    repositories {//代码的托管库,设置之后这样可以在项目中引用对应仓库上面的开源库
        google()
        jcenter()
    }
    dependencies {//配置Gradle需要的插件
        //定义Android Plugin for Gradle的版本
        classpath "com.android.tools.build:gradle:${GRADLE_VERSION}"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {//定义一下依赖仓库包(所有module)
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {//每次执行clean的时候,都删除build下面文件
    delete rootProject.buildDir
}
ext {//定义一些参数变量
    // Sdk and tools
    compileSdkVersion = 26
    supportLibraryVersion = '27.1.1'
    constraintLayoutVersion = '1.1.3'
    picasso_version = '2.71828'
    glide_version = '4.8.0'
}

以上可以看到有几个地方都用到了repositories,一般来说repositories有三种地方用到:

  • buildscript下的repositories
buildscript {  
     repositories {
         ...
     }
     dependencies {
         ...
     }
}

这里面定义的是Gradle脚本自身执行所需要依赖的项目仓库

  • 根目录下的repositories
repositories {
     ...
}
dependencies {
     ...
}
 
 

根目录下的是定义当前项目所需要依赖的项目仓库

  • allprojects块下的repositories
allprojects { 
     repositories {
         ...
     }
     dependencies {
         ...
     }
}

定义所有module共同所需要依赖的项目仓库,每一个module也可以在自己的build.gradle下的repositories中配置自己独特需要的仓库。

重点说明

可能到这里,多少会有一些迷糊,因为上面出现了两个地方关于gradle版本的说明,一个是gradle-wrapper.properties中的https\://services.gradle.org/distributions/gradle-4.1-all.zip,一个是上面的build.gradle中的classpath "com.android.tools.build:gradle:3.0.1",这两个地方说的版本都是什么意义呢?想明白这个问题,我们首先要清晰一下概念:

  • Gradle 本身是一个构建系统,想使用需要下载、安装、部署Gradle包的,不是只用于Android的构建
  • Gradle Wrapper 声明Gradle的下载、安装和部署的路径、地址,这样就简化了Gradle的使用
  • Android Plugin for Gradle 是由Google开发的,适用于Android通过Gradle构建的Gradle插件集合,通过这个,我们很方便的对Android项目进行Gradle构建
    所以,上面两个地方的版本,一个指的是Gradle构建系统的版本,一个是Android Plugin for Gradle 的版本。一个存放在~/.gradle/wrapper/dists目录下,一个会下载到~\.gradle\caches\modules-2\files-2.1\com.android.tools.build/gradle目录下,如果该目录没有或者无法下载(AndroidStudio设置了Offline Work模式),可以将对应版本放到Android Studio安装目录下的gradle\m2repository\com.android.tools.build目录下即可。

module中的build.gradle文件

module中的build.gradle文件声明了当前module的构建信息,是gradle文件中内容较多的一个:

apply plugin: 'com.android.application'

//key为 gradle.properties里定义的变量
//编译的sdk版本
def ANDROID_BUILD_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_SDK_VERSION")
//app min sdk version
def ANDROID_BUILD_MIN_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_MIN_SDK_VERSION")
//app target sdk version
def ANDROID_BUILD_TARGET_SDK_VERSION = project.getProperties().get("ANDROID_BUILD_TARGET_SDK_VERSION")
//app version code
def ANDROID_BUILD_VER_CODE = project.getProperties().get("ANDROID_BUILD_VER_CODE")
//app version name
def ANDROID_BUILD_VER_NAME = project.getProperties().get("ANDROID_BUILD_VER_NAME")
//编译的tools版本
def ANDROID_BUILD_TOOLS_VERSION = project.getProperties().get("ANDROID_BUILD_TOOLS_VERSION")
//app的包名
def ANDROID_APPLICATION_ID = project.getProperties().get("APPLICATION_ID")
def JAVA_VERSION = project.getProperties().get("JAVA_VERSION")


android {
    compileSdkVersion Integer.parseInt("$rootProject.ext.compileSdkVersion" as String)


    defaultConfig {
        applicationId ANDROID_APPLICATION_ID
        minSdkVersion Integer.parseInt(ANDROID_BUILD_MIN_SDK_VERSION as String)
        targetSdkVersion Integer.parseInt(ANDROID_BUILD_TARGET_SDK_VERSION as String)
        versionCode Integer.parseInt(ANDROID_BUILD_VER_CODE as String)
        versionName ANDROID_BUILD_VER_NAME
        multiDexEnabled true

    }

    compileOptions {
        sourceCompatibility JAVA_VERSION
        targetCompatibility JAVA_VERSION
    }

}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "com.android.support:appcompat-v7:$rootProject.ext.supportLibraryVersion"
    implementation("com.squareup.picasso:picasso:$rootProject.ext.picasso_version") {//这样写的作用是从 picasso 的依赖中去除 "com.android.support"
        exclude group: "com.android.support"
    }
    implementation 'com.jakewharton:butterknife:8.5.1'
    annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
    //之所以去除依赖,是因为picasso 和 其他的module 对于com.android.support依赖的版本不一致,不加这句同时引入picasso 和 glide会报错
    //这里面的implementation和低版本的gradle中的compile用法一样


}

上述的用的版本参数,用了上面提到的gradle.propertiesext{}声明的变量。
各种标签说明:

apply plugin 说明

apply plugin 是引入Gradle插件,我们常用到的诸如:
apply plugin: 'com.android.application'
App应用工程,标明可以生成一个可运行的apk应用,一个项目中只有一个module声明成这样。
apply plugin: 'com.android. library'
Library库功能,标明该module可以生成aar包给其他的module使用
apply plugin: 'com.android. test'
测试工程,标明进行单元测试的库。

其他的第三方插件如:
apply plugin: 'com.antfortune.freeline' 使用freeline插件
apply plugin: 'kotlin-android' 使用kotlin插件
apply plugin: 'kotlin-android-extensions' 使用kotlin插件

android{}

在这里我们可以定义我们的项目的配置参数,这也是Android Plugin for Gradle提供的一个类型。里面的参数包含:

android {
//项目编译的sdk版本 
    compileSdkVersion Integer.parseInt(ANDROID_BUILD_SDK_VERSION as String)
//ADT版本
    buildToolsVersion ANDROID_BUILD_TOOLS_VERSION
//默认配置参数
    defaultConfig {
//applicationId
        applicationId ANDROID_APPLICATION_ID
//最小版本
        minSdkVersion Integer.parseInt(ANDROID_BUILD_MIN_SDK_VERSION as String)
//目标版本
        targetSdkVersion Integer.parseInt(ANDROID_BUILD_TARGET_SDK_VERSION as String)
//版本号
        versionCode Integer.parseInt(ANDROID_BUILD_VER_CODE as String)
//版本名
        versionName ANDROID_BUILD_VER_NAME
//可以增加其他编译时的参数
        buildConfigField("String", "SOCKPUPPET", "\"" + SOCKPUPPET + "\"")
        // dex突破65535的限制
        multiDexEnabled true
//ndk配置
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
//manifest中的参数
        manifestPlaceholders = [
                GAODE_APPKEY : GAODE_APPKEY,
                SOCKPUPPET   : SOCKPUPPET,
                JPUSH_PKGNAME: ANDROID_APPLICATION_ID,
                JPUSH_APPKEY : JPUSH_APPKEY, //JPush上注册的包名对应的appkey.
        ]
//打包生成时 修改输出APK名字
        applicationVariants.all { variant ->
            variant.outputs.each { output ->
                def oldFile = output.outputFile

                if (SOCKPUPPET == "") {
                    SOCKPUPPET = "test" //给出打包的默认值
                }
                def releaseApkName = "${SOCKPUPPET}" + "_v" + defaultConfig.versionName + "_${variant.productFlavors[0].name}" + "_${variant.buildType.name}.apk"
                output.outputFile = new File(oldFile.parent, releaseApkName)

            }
        }

    }
    signingConfigs {
        release {
            //签名
            storeFile file(STORE_FILE)
            storePassword STORE_PASSWORD
            keyAlias KEY_ALIAS
            keyPassword KEY_PASSWORD
        }
    }

//资源集合,用定义对应的java资源目录
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
//设置APK包的相关属性
    packagingOptions {
        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 'META-INF/LGPL2.1'
    }

//dex 文件的配置信息
    dexOptions {
        incremental true
        jumboMode true
        preDexLibraries false
        javaMaxHeapSize "4g" //
    }
//编译的类型(一般用debug和release,可以定义其他的)
    buildTypes {
         //debug版本
        debug {
            // 定义LOG_DEBUG变量的参数值
            buildConfigField "boolean", "LOG_DEBUG", "true"
            shrinkResources false
            signingConfig signingConfigs.release
            minifyEnabled false
        }
        //release版本
        release {
            // 定义LOG_DEBUG变量的参数值
            buildConfigField "boolean", "LOG_DEBUG", "false"
            //是否混淆
            minifyEnabled true
            // 移除无用的resource文件
            shrinkResources false
            //设置是否生成debug版的APK
            debuggable false
            //生成的APK是否支持jni
            jniDebuggable false
            //是否对APK进行zip优化
            zipAlignEnabled true
            //混淆的规则
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            //签名信息
            signingConfig signingConfigs.release
        }
    }
    //配置不同渠道信息(不同的logo、版本、applicationID等)
    productFlavors {
        guanwang {}
        Yingyongbao {}
//        YingyongbaoTD {}
        Sanliuling {}
        Xiaomi {
            targetSdkVersion 23
        }
        Vivo {}
//        Baidu {}
//        Huawei {}
        Oppo {}
        Meizu {}
//        Sougou {}
//        Anzhi {}
    }
   //不同渠道打包时 可以通过该方法改变一些内容
    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [CHANNEL_NAME: name, JPUSH_CHANNEL: name]
    }
    //我用到的freeline配置信息
    freeline {
        hack true
        productFlavor 'guanwang'
    }
    //lint信息
    lintOptions {
        //编译时如果发生错误是否终止编译
        abortOnError false
    }
  //编译的java版本信息
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

}

以上信息除了freeline是我这个项目中用到的,其他的都是一个项目常用的配置信息,当然配置信息还有其他更多,但不太常用,就不一一介绍了。

Gradle环境变量配置

上面说了AS中gradle的配置以及相关说明,平时开发的过程中,我们也会用到gradle命令去执行一个task,很多时候我们执行gradle XXX时都会提醒 -bash: gradle: command not found。这是因为我们没有配置gradle的环境变量。

  • Mac环境
    gradle在Android Studio 应用的包下面有一份,理论上也是可以将这个路径配置到环境变量中(.bash_profile),但是在执行gradle命令时,会提示权限找不到。为了简便行事,我们可以通过brew install gradle/usr/local/Cellar/下安装一份gradle。然后在.bash_profile文件中添加
export GRADLE_HOME=/usr/local/Cellar/gradle/5.4.1/bin
export PATH=${PATH}:${GRADLE_HOME}

执行source ~/.bash_profile即可。
-Window
可以尝试配置为AndroidStudoi目录下面的gradle路径(我没有Windwos系统,这是理论上的建议)

以上只是简单介绍了一下gradle的内容,如果想要深入学习gradle以及创建自己的task等,可以参考一下链接:
1、内建和定制任务:https://www.cnblogs.com/gzdaijie/p/5285160.html
2、Gradle基本知识点和配置:http://blog.csdn.net/u010818425/article/details/52268126
3、Groovy学习:http://blog.csdn.net/Linux7985/article/details/52440572

你可能感兴趣的:(Gradle的介绍)