gradle是什么
Gradle是一个基于Ant(Apache)和Maven(Ant)概念的项目自动化构建工具。他使用的语言是Groovy的特定领域语言(小语言即该语言不通用,只能用于特定的某个领域)来声明项目设置。在通俗一点解释就是软件开发的时候会用到一些第三方依赖的东西,同时版本发布的时候会打包、部署。在遇到一些特殊需求的时候,需要不同渠道等管理。如果我们不使用构建,单纯的人工来做这个事,就各种build,各种clean等等。这个时候使用构建的话,就大大减少了工作的流程和劳动力成本。
一个Android项目中gradle相关文件
如上图所示,红的部分的是一个项目中基本的gradle相关文件(我没有加入module)。这些文件在项目中的位置如下:
每一个文件说明
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//下载路径
我们在初次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.properties
和ext{}
声明的变量。
各种标签说明:
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