Gradle是一种构建工具,它抛弃了基于XML的构建脚本,取而代之的是采用一种基于Groovy的内部领域特定语言,建议可以先熟悉一下Groovy脚本。
1. Gradle 常用命令:
1.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 build
命令把debug
、release
环境的包都打出来,如果正式发布只需要打Release
的包,该怎么办呢,下面介绍一个很有用的命令 assemble
, 如:
./gradlew assembleDebug
编译并打Debug包./gradlew assembleRelease
编译并打Release的包
除此之外,assemble
还可以和productFlavors
结合使用:
./gradlew installRelease
Release模式打包并安装./gradlew uninstallRelease
卸载Release模式包
1.2 加入自定义参数:
比如我们想根据不同的参数来进行不用的编译配置,可以在./gradlew
中加入自定义参数。
./gradlew assembleDebug -Pcustom=true
就可以在build.gradle
中使用下面代码来判断:
if (project.hasProperty('custom')){
}
1.3 assemble结合
Build Variants来创建
task
assemble
还能和Product Flavor
结合创建新的任务,其实 assemble
是和 Build Variants
一起结合使用的,而 Build Variants = Build Type + Product Flavor
,举个例子大家就明白了: 如果我们想打包 wandoujia
渠道的release
版本,执行如下命令就好了:
./gradlew assembleWandoujiaRelease
如果我们只打wandoujia渠道版本,则:
./gradlew assembleWandoujia
此命令会生成wandoujia渠道的Release
和Debug
版本 同理我想打全部Release版本:
./gradlew assembleRelease
这条命令会把Product Flavor下的所有渠道的Release
版本都打出来。 总之,assemble
命令创建task有如下用法:
assemble<Variant Name>:
允许直接构建一个Variant版本,例如assembleFlavor1Debug。assemble<Build Type Name>:
允许构建指定Build Type的所有APK,例如assembleDebug将会构建Flavor1Debug和Flavor2Debug两个Variant版本。assemble<Product Flavor Name>:
允许构建指定flavor的所有APK,例如assembleFlavor1将会构建Flavor1Debug和Flavor1Release两个Variant版本。
2. Gradle配置:
- Gradle构建脚本
build.gradle
- Gradle属性文件
gradle.properties
- Gradle设置文件
settings.gradle
2.1 build.gradle
先看整个项目的gradle配置文件:
buildscript {
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的版本某个 Moudle的gradle
配置文件:
2.2 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.3 apply
//声明是Android程序
apply plugin: 'com.android.application'
*apply plugin:
声明构建的项目类型。如果是库的话就加
apply plugin: 'com.android.library'
2.4 android
android {
// 编译SDK的版本
compileSdkVersion 22
// build tools的版本
buildToolsVersion "23.0.1"
//aapt配置
aaptOptions {
//不用压缩的文件
noCompress 'pak', 'dat', 'bin', 'notice'
//打包时候要忽略的文件
ignoreAssetsPattern "!.svn:!.git"
//分包
multiDexEnabled true
//--extra-packages是为资源文件设置别名:意思是通过该应用包名+R,com.android.test1.R和com.android.test2.R都可以访问到资源
additionalParameters '--extra-packages', 'com.android.test1','--extra-packages','com.android.test2'
}
//默认配置
defaultConfig {
//应用的包名
applicationId "com.example.heqiang.androiddemo"
minSdkVersion 21
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
//编译配置
compileOptions {
// java版本
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
//源文件目录设置
sourceSets {
main {
//jni lib的位置
jniLibs.srcDirs = jniLibs.srcDirs << 'src/jniLibs'
//定义多个资源文件夹,这种情况下,两个资源文件夹具有相同优先级,即如果一个资源在两个文件夹都声明了,合并会报错。
res.srcDirs = ['src/main/res', 'src/main/res2']
}
}
//签名配置
signingConfigs {
debug {
keyAlias 'androiddebugkey'
keyPassword 'android'
storeFile file('keystore/debug.keystore')
storePassword 'android'
}
}
buildTypes {
//release版本配置
release {
debuggable false
// 是否进行混淆
minifyEnabled true
//去除没有用到的资源文件,要求minifyEnabled为true才生效
shrinkResources true
// 混淆文件的位置
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
signingConfig signingConfigs.debug
//ndk的一些相关配置,也可以放到defaultConfig里面。
//指定要ndk需要兼容的架构(这样其他依赖包里mips,x86,arm-v8之类的so会被过滤掉)
ndk {
abiFilter "armeabi"
}
}
//debug版本配置
debug {
debuggable true
// 是否进行混淆
minifyEnabled false
//去除没有用到的资源文件,要求minifyEnabled为true才生效
shrinkResources true
// 混淆文件的位置
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
signingConfig signingConfigs.debug
//ndk的一些相关配置,也可以放到defaultConfig里面。
//指定要ndk需要兼容的架构(这样其他依赖包里mips,x86,arm-v8之类的so会被过滤掉)
ndk {
abiFilter "armeabi"
}
}
}
// lint配置
lintOptions {
//移除lint检查的error
abortOnError false
//禁止掉某些lint检查
disable 'NewApi'
}
}
android{}
设置编译android项目的参数,构建android项目的所有配置都写在这里。 除了上面写的,在android{}块中可以包含以下直接配置项:
*productFlavors{ }
产品风格配置,ProductFlavor类型
testOptions{ }
测试配置,TestOptions类型dexOptions{ }
dex配置,DexOptions类型packagingOptions{ }
PackagingOptions类型jacoco{ }
JacocoExtension类型。 用于设定 jacoco版本splits{ }
Splits类型。
几点说明:
- 文件开头
apply plugin
是最新gradle版本的写法,以前的写法是apply plugin: 'android'
, 如果还是以前的写法,请改正过来。
*minifyEnabled
也是最新的语法,很早之前是runProguard,这个也需要更新下。 proguardFiles
这部分有两段,前一部分代表系统默认的android程序的混淆文件,该文件已经包含了基本的混淆声明,免去了我们很多事,这个文件的目录在 sdk目录/tools/proguard/proguard-android.txt
, 后一部分是我们项目里的自定义的混淆文件,目录就在app/proguard-rules.txt
, 如果你用Studio 1.0创建的新项目默认生成的文件名是proguard-rules.pro
, 这个名字没关系,在这个文件里你可以声明一些第三方依赖的一些混淆规则。最终混淆的结果是这两部分文件共同作用的。aaptOptions
更多介绍 http://blog.csdn.net/heqiangflytosky/article/details/51009123
2.5 repositories
repositories {
flatDir {
//本地jar依赖包路径
dirs '../../../../main/libs'
}
}
2.6 dependencies
dependencies {
compile files('libs/android-support-v4.jar')
//在flatDir.dirs下面找依赖的aar
compile (name:'ui', ext:'aar')
// 编译extras目录下的ShimmerAndroid模块
compile project(':extras:ShimmerAndroid')
// 编译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')
}
- compile和provided
compile
表示编译时提供并打包进apk。
provided
表示只在编译时提供,不打包进apk。 - exclude防止重复依赖
- include
CommonSDK模块的定义可以参考settings.gradle其他的介绍可以参考 依赖库管理。
几点说明
- 看到上面的两个一模一样的repositories和dependencies了吗?他们的作用是不一样的,在buildscript里面的那个是插件初始化环境用的,用于设定插件的下载仓库,而外面的这个是设定工程依赖的一些模块和远程library的下载仓库的。
2.7 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能写什么了;
include ':AndroidDemo'
include ':CommonSDK'
project(':CommonSDK').projectDir = new File(settingsDir, '../../CommonSDK/')
include调用后,生成了一个名为:CommonSDK的Project对象,project(’:CommonSDK’)
取出这个对象,设置Project的 projectDir属性。projectDir哪里来的?请看Project
类的文档。
3. 依赖库管理
3.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')
}
3.2 远程依赖
gradle
同时支持maven,ivy
,以maven作为例子:
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'
}
4. 项目依赖
对于项目依赖android library
的话,在这里需要使用gradle mulit projec
t机制。Mulit project
设置是gradle约定的一种格式,如果需要编译某个项目之前,要先编译另外一个项目的时候,就需要用到。结构如下(来自于官方文档):
MyProject/
| settings.gradle
+ app/
| build.gradle
+ libraries/
+ lib1/
| build.gradle
+ lib2/
| build.gradle
需要在workplace目录下面创建settings.gradle
的文件,然后在里面写上:
include ':app', ':libraries:lib1', ':libraries:lib2'
例如:
include ':AndroidDemo'
include ':CommonSDK'
project(':CommonSDK').projectDir = new File(settingsDir, '../../CommonSDK/')
如此,gradle mutil project
就设置完毕。
对于app project如果需要应用libraries目录下的lib1,只需要在app project的build.gradle文件里的依赖中这么写:
compile project(':libraries:lib1')
类似前面的
provided project(':main-host')
即可完成,写完以后可以用gradle AndroidDependencies
可以检查依赖状况
4.1 多渠道打包:
主要借助
android {
productFlavors{
……
}
}
来实现。
网上多是类似友盟的配置,copy过来:
http://blog.csdn.net/maosidiaoxian/article/details/42000913
https://segmentfault.com/a/1190000004050697
在AndroidManifest.xml里面写上:
<meta-data
android:name="UMENG_CHANNEL"
android:value="Channel_ID" />
里面的Channel_ID就是渠道标示。我们的目标就是在编译的时候这个值能够自动变化。
android {
productFlavors {
xiaomi {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
}
_360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"]
}
baidu {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"]
}
wandoujia {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
}
}
或者批量修改
android {
productFlavors {
xiaomi {}
_360 {}
baidu {}
wandoujia {}
}
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
然后用 ./gradlew assembleRelease
这条命令会把Product Flavor下的所有渠道的Release版本都打出来。 assemble<Product Flavor Name>:
允许构建指定flavor的所有APK,例如assembleFlavor1将会构建Flavor1Debug和Flavor1Release两个Variant版本。
在上面当中,我们也可以指定一个默认的渠道名,如果需要的话。指定默认的值是在defaultConfig
节点当中添加如下内容:
manifestPlaceholders = [ CHANNEL_NAME:"Unspecified"]
这里的 Unspecified
换成你实际上的默认的渠道名。 使用manifestPlaceholders
的这种配置,同样适用于manifest的其他配置。比如你需要在不同渠道发布的apk里面,指定不同的启动Activity
。比如在豌豆荚里面发布的,启动的Activity
显示的是豌豆荚首发的界面,应用宝里面启动的是应用宝首发的界面(哈哈,有点坏),你就可以对你的activity的值使用 {activity_name}的方式,然后在productFlavors里面配置这个{activity_name}的值。
5. 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
中修改,是不是很方便进行配置的管理的。