一、日常记录
1.父子模块依赖
1.平级依赖
settings.gradle添加:
includeFlat 'A'
build.gradle添加:
compile project(':A')
2.聚合工程
settings.gradle添加:
include 'C1','C2'
2.生命周期钩子
3.查看项目依赖树
1、用gradle命令查看依赖关系:
gradle dependencies
./gradlew dependencies
2、用idea查看依赖关系:
4.生成指定版本gradlew
gradle wrapper --gradle-version [版本号]
//例:gradle wrapper --gradle-version 6.9.1
5.Java使用Gradle依赖配置compile,implementation和api的区别
Gradle3.4新增了Java-library插件,java-library插件使用了新的依赖配置implementation和api。旧的依赖配置compile被废弃。
Gradle3.4之前的版本:
java插件
apply plugin: 'java'
添加依赖
dependencies {
compile 'commons-httpclient:commons-httpclient:3.1'
compile 'org.apache.commons:commons-lang3:3.5'
}
Gradle 3.4+
使用java-library插件替换java插件
apply plugin: 'java-library'
新的依赖配置:implementation和api
dependencies {
api 'commons-httpclient:commons-httpclient:3.1'
implementation 'org.apache.commons:commons-lang3:3.5'
}
api和implementation两种依赖的不同点在于:它们声明的依赖其他模块是否能使用。
- api:当其他模块依赖于此模块时,此模块使用api声明的依赖包是可以被其他模块使用
- implementation:当其他模块依赖此模块时,此模块使用implementation声明的依赖包只限于模块内部使用,不允许其他模块使用。
二、Gradle命令
1.常用命令
gradle命令一般是 ./gradlew +参数, gradlew代表 gradle wrapper,意思是gradle的一层包装,大家可以理解为在这个项目本地就封装了gradle,即gradle wrapper, 在gradle/wrapper/gralde-wrapper.properties文件中声明了它指向的目录和版本。只要下载成功即可用grdlew wrapper的命令代替全局的gradle命令。
./gradlew -v 版本号
./gradlew clean 清除app目录下的build文件夹
./gradlew build 检查依赖并编译打包
./gradlew tasks 列出所有task
这里注意的是 ./gradlew build 命令把debug、release环境的包都打出来,如果正式发布只需要打Release的包,该怎么办呢,下面介绍一个很有用的命令 assemble, 如:
./gradlew assembleDebug 编译并打Debug包
./gradlew assembleRelease 编译并打Release的包
除此之外,assemble还可以和productFlavors结合使用:
./gradlew installRelease Release模式打包并安装
./gradlew uninstallRelease 卸载Release模式包
2.加入自定义参数
比如我们想根据不同的参数来进行不用的编译配置,可以在./gradlew中加入自定义参数。
./gradlew assembleDebug -Pcustom=true
可以在build.gradle中使用下面代码来判断:
if (project.hasProperty('custom')){
}
三、Gradle配置
Gradle构建脚本 build.gradle
Gradle属性文件 gradle.properties
Gradle设置文件 settings.gradle
1.build.gradle
先看整个项目的gradle配置文件:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
内容主要包含了两个方面:一个是声明仓库的源,这里可以看到是指明的jcenter(), 之前版本则是mavenCentral(), jcenter可以理解成是一个新的中央远程仓库,兼容maven中心仓库,而且性能更优。
另一个是声明了android gradle plugin的版本,android studio 1.0正式版必须要求支持gradle plugin 1.0的版本。
上面的 buildscript 和 allprojects 其实是 Project 类的一个 Script blocks,Gradle 中每个 build.gradle 会转换成一个 Project 对象。
(1).buildscript
buildscript {
repositories {
maven { url 'http://*********' }
}
dependencies {
classpath 'com.android.tools.build:gradle:1.3.1'
}
}
- buildscript{}设置脚本的运行环境。
- repositories{}支持java依赖库管理,用于项目依赖。
- dependencies{}依赖包的定义。支持maven/ivy,远程,本地库,也支持单文件。如果前面定义了repositories{}maven 库,则使用maven的依赖库,使用时只需要按照用类似于com.android.tools.build:gradle:0.4,gradle 就会自动的往远程库下载相应的依赖。
(2).apply
apply plugin: 'com.android.library'
apply from: "config.gradle"
apply from: '../buildscript.gradle', to:buildscript // 导入到 buildscript 块
- apply plugin:声明引用插件的类型。
- apply from:表示引用其他的配置文件
(3).android
略
(4).repositories
repositories {
flatDir {
//本地jar依赖包路径
dirs '../../../../main/libs'
}
}
(5).dependencies
dependencies {
// 单个引入依赖
compile files('libs/android-support-v4.jar')
//在flatDir.dirs下面找依赖的aar
compile (name:'ui', ext:'aar')
// 编译extras目录下的ShimmerAndroid模块
// 使用transitive属性设置为false来排除所有的传递依赖,默认为true
compile project(':extras:ShimmerAndroid'){
transitive = false
}
// 编译CommonSDK模块,但是去掉此模块中对com.android.support的依赖,防止重复依赖报错
compile (project(':CommonSDK')) { exclude group: "com.android.support" }
provided fileTree(dir: 'src/android5/libs', include: ['*.jar'])
provided 'com.android.support:support-v4:21.0.3'
provided project(':main-host')
//通用使用exclude排除support-compat模块的依赖
compile ('com.jakewharton:butterknife:8.5.1'){
exclude module: 'support-compat'
}
// gradle 3.0以后版本支持的写法
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
api 'com.android.support:design:26.1.0'
// 指定使用aar格式的依赖包,但是这样会关闭依赖传递
implementation 'com.android.support:appcompat-v7:22.1.1@aar
}
- compile 和 provided
- compile表示编译时提供并打包进apk。
- provided表示只在编译时提供,不打包进apk。
- implementation 和 api
- 这两个是 Gradle 3.0 以后的依赖方法,implementation 在编译期会将依赖隐藏在内部而不对外公开,就是说使用 implementation 的依赖不会传递。只有在运行时其他模块才能获取依赖。比如:一个项目中app模块依赖A模块,A模块使用 implementation 来依赖 fastjson ,那么app里面如果不添加依赖的话就不能直接引用fastjson,会编译不通过。这样做的好处是1.加快编译速度,2. 隐藏对外不必要的接口。
- api 和以前的 compile 是一样的。
gradle 3.0以后使用 compileOnly 来代替 provided,使用 runtimeOnly 来代替 apk
- exclude 防止重复依赖,后面会重点介绍
- transitive 排除所有的传递依赖,后面会重点介绍
- include
(6).本地依赖
本地依赖指的是我们把jar包或者aar包放到本地依赖的方法,这样就不用发布到远程仓库。
默认情况下,新建的Android工程有一个libs目录,并且被添加为依赖目录。
dependencies {
compile fileTree('libs')
}
还可以添加过滤器,只添加 Jar 依赖包:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
还可以单个添加依赖:
dependencies {
compile files('libs/xxx.jar') // aar 也可以
}
//或者(但是这样会关闭依赖传递)
dependencies {
compile(name:'libraryname', ext:'aar')
}
我们还可以指定目录地址作为放置依赖包的目录:
repositories {
flatDir {
dirs 'jars'
}
}
//指定多个:
repositories {
flatDir {
dirs 'jars';dirs 'aars'
}
}
(7).本地仓库
除了上面的本地直接添加依赖包的方法,我们还可以设置本地仓库:
repositories {
maven {
url "../repo"
}
}
(8).几点说明
- 看到上面的两个一模一样的repositories和dependencies了吗?他们的作用是不一样的,在buildscript里面的那个是插件初始化环境用的,用于设定插件的下载仓库,而外面的这个是设定工程依赖的一些模块和远程library的下载仓库的。
- @aar 的使用:aar(Android Archive)和jar(Java Archive File)之间的区别:aar 可以包含源代码和资源(包含 AndroidManifest.xml 布局文件等资源文件),但是 jar 只能包含源代码。当您在项目的build.gradle 中包含一个带有后缀 @arr 的库时,该库将下载 aar 后缀的库文件。如果没有,默认情况下将下载 jar 文件。当然,您也可以添加后缀@jar使下载 jar 库文件。比如:implementation ‘com.android.support:appcompat-v7:22.1.1@aar’
2.settings.gradle
这个文件是全局的项目配置文件,里面主要声明一些需要加入gradle的module。
一般在setting.gradle中主要是调用include方法,导入工程下的各个子模块。
那我们在setting.gradle里面还能写什么呢?因为setting.gradle对应的是gradle中的Settings对象,那查下Settings的文档(https://docs.gradle.org/current/dsl/org.gradle.api.initialization.Settings.html),看下它都有哪些方法,哪些属性,就知道在setting.gradle
能写什么了;
nclude ':AndroidDemo'
include ':CommonSDK'
project(':CommonSDK').projectDir = new File(settingsDir, '../../CommonSDK/')
include调用后,生成了一个名为:CommonSDK的Project对象,project(‘:CommonSDK’)取出这个对象,设置Project的 projectDir属性。projectDir哪里来的?请看Project类的文档。
3.gradle.properties
可以在 gradle.properties 文件中配置一些变量,这些变量在这个工程下的所有module的build.gradle文件里都可以使用。这样就可以把一些共用的变量放到这里,这样后面修改的时候就可以只修改这个变量,不用各个模块都要修改了。
比如我们在 gradle.properties SDK 版本以及应用的版本号:
MIN_SDK_VERSION=21
TARGET_SDK_VERSION=22
VERSION_CODE=200100
VERSION_NAME=2.1.0
debug=true
RX_ANDROID_VERSION=1.2.0
那么在 build.gradle 中可以通过project进行获取或者 “${RX_ANDROID_VERSION}” 引用:
defaultConfig {
applicationId "com.example.heqiang.testsomething"
minSdkVersion project.MIN_SDK_VERSION as int
targetSdkVersion project.TARGET_SDK_VERSION as int
versionCode project.VERSION_CODE as int
versionName project.VERSION_NAME
// 还可以这样获取
if('true' == project.properties['debug']){
}
/*
* as int 关键字是用来进行类型转换的,因为从配置里面读取出来的默认是字符串
*还可以使用 versionCode Integer.parseInt(project.VERSION_CODE)
* */
}
// 还可以这样用
dependencies {
compile "io.reactivex:rxandroid:${RX_ANDROID_VERSION}"
compile "io.reactivex:rxjava:${RX_JAVA_VERSION}"
}
或者在 gradle.properties 中添加:
systemProp.versionName=1.0.0
systemProp.versionCode=100
可以通过 System.properties进行引用:
def code = System.properties['versionCode']
def name = System.properties['versionName']
4.调试
我们在进行一些配置的时候可能需要知道一些变量的值,这时候可以在 build.gradle 中添加打印进行调试,比如:
defaultConfig {
applicationId "com.example.hq.testsomething"
minSdkVersion project.MIN_SDK_VERSION as int
targetSdkVersion project.TARGET_SDK_VERSION as int
versionCode project.VERSION_CODE as int
versionName project.VERSION_NAME
println('** build versionName=' + versionName)
}
在 Gradle Console 中就可以看到打印
** build versionName=2.1.0
如果找不到 Gradle Console ,可以 View ->Tool Windows -> Gradle, 任意选择一个Task,双击执行即可。
或者使用命令行编译。
四、依赖库管理
1.本地依赖
dependencies {
//单文件依赖
compile files('libs/android-support-v4.jar')
//某个文件夹下面全部依赖
compile fileTree(dir: 'src/android6/libs', include: ['*.jar'])
compile (name:'ui', ext:'aar')
compile (project(':CommonSDK')) { exclude group: "com.android.support" }
provided fileTree(dir: 'src/android5/libs', include: ['*.jar'])
provided 'com.android.support:support-v4:21.0.3'
provided project(':main-host')
}
2.远程依赖
repositories {
//从中央库里面获取依赖
mavenCentral()
//或者使用指定的本地maven 库
maven{
url "file://F:/githubrepo/releases"
}
//或者使用指定的远程maven库
maven{
url "https://github.com/youxiachai/youxiachai-mvn-repo/raw/master/releases"
}
}
dependencies {
//应用格式: packageName:artifactId:version
compile 'com.google.android:support-v4:r13'
}
3.Gradle依赖的统一管理
我们可以在项目的根目录创建一个gradle配置文件config.gradle,内容如下:
ext{
android=[
compileSdkVersion: 22,
buildToolsVersion: "23.0.1",
minSdkVersion: 21,
targetSdkVersion: 22,
versionCode: 1,
versionName: "1.0"
]
dependencies=[
compile:'com.android.support:support-v4:21.0.3',
compile: (project(':CommonSDK')) { exclude group: "com.android.support" },
provided: fileTree(dir: 'src/android5/libs', include: ['*.jar']),
provided: project(':main-host')
]
}
targetSdkVersion的版本还有依赖库的版本升级都在这里进行统一管理,所有的module以及主项目都从这里同意读取就可以了。
在build.gradle文件中加入:
apply from:"config.gradle"
意思是所有的子项目或者所有的modules都可以从这个配置文件中读取内容。
android节点读取ext中android对应项,dependencies读取dependencies对应项,如果配置有变化就可以只在config.gradle中修改,是不是很方便进行配置的管理呢?
4.检查依赖报告
运行命令./gradlew :dependencies (projectname为settings.gradle里面配置的各个project,如果没有配置,直接运行./gradlew dependencies),会把该模块所有配置的依赖树会打印出来,依赖树显示了你 build 脚本声明的顶级依赖和它们的传递依赖。
为了减少输出内容我们只对 compile configuration感兴趣,那么可以运行下面的命令:
./gradlew <projectname>:dependencies --configuration compile
仔细观察你会发现有些传递依赖标注了(*)星号,表示这个依赖被忽略了
,这是因为其他顶级依赖中也依赖了这个传递的依赖,Gradle会自动分析下载最合适的依赖,一般是比较新的版本。(->)箭头表示被强转变依赖于箭头后面的版本
。
如果在 Gradle 3.0 以后可以运行:
./gradlew <projectname>:dependencies --configuration releaseRuntimeClasspath
5排除传递依赖
Gradle允许你完全控制传递依赖,你可以选择排除全部的传递依赖也可以排除指定的依赖。
- exclude:可以设置不编译指定的模块,排除指定模块的依赖。后的参数有group和module,可以分别单独使用,会排除所有匹配项。
// 编译CommonSDK模块,但是去掉此模块中对com.android.support的依赖,防止重复依赖报错
compile (project(':CommonSDK')) { exclude group: "com.android.support" }
compile ('com.jakewharton:butterknife:8.5.1'){
exclude module: 'support-compat'
exclude group: 'com.android.**.***', module: '***-***'
}
- transitive:前面已经介绍过,用于自动处理子依赖项,默认为true,gradle自动添加子依赖项。
设置为false排除所有的传递依赖
,可以用来解决一些依赖冲突的问题,比如一些 Error:java.io.IOException: Duplicate zip entry 报错。
/ 使用transitive属性设置为false来排除所有的传递依赖
compile project(':extras:ShimmerAndroid'){
transitive = false
}
- force:强制设置某个模块的版本。
configurations.all{
resolutionStrategy{
force'org.hamcrest:hamcrest-core:1.3'
}
}
//或
compile ('com.jakewharton:butterknife:8.5.1'){
// 冲突时优先使用该版本
force = true
}
6.动态版本声明
如果你想使用一个依赖的最新版本,你可以使用latest.integration,比如声明 Cargo Ant tasks的最新版本,你可以这样写org.codehaus .cargo:cargo-ant:latest-integration,你也可以用一个+号来动态的声明:
dependencies {
//依赖最新的1.x版本
compile "org.codehaus.cargo:cargo-ant:1.+"
}
然后在依赖树里面可以清晰的看到选择了哪个版本:
\--- org.codehaus.cargo:cargo-ant:1.+ -> 1.3.1
五、gradle部署
1.linuxgradle包位置