个人博客原文地址html
Gradle是一种构建工具,它抛弃了基于XML的构建脚本,取而代之的是采用一种基于Groovy的内部领域特定语言(DSL),建议能够先熟悉一下Groovy脚本。
Gradle API 文档
Android 配置构建
Android 插件 DSL 扩展
本文只是简单的介绍一下 Gradle 的一些基本配置,若是想进行一些高级的操做或者是想深刻的了解这些配置,请参考个人后面几篇博客。
Gradle 使用指南 – Android DSL 扩展
Gradle 使用指南 – Gradle Task
Gradle 使用指南 – 建立Plugin
Gradle 使用指南 – Plugin DSL 扩展java
gradle明明通常是./gradlew +参数
, gradlew
表明 gradle wrapper
,意思是gradle的一层包装,你们能够理解为在这个项目本地就封装了gradle,即gradle wrapper, 在gradle/wrapper/gralde-wrapper.properties
文件中声明了它指向的目录和版本。只要下载成功便可用grdlew wrapper
的命令代替全局的gradle
命令。react
./gradlew -v
版本号./gradlew clean
清除app目录下的build文件夹./gradlew build
检查依赖并编译打包./gradlew tasks
列出全部task这里注意的是 ./gradlew build
命令把debug、release环境的包都打出来,若是正式发布只须要打Release的包,该怎么办呢,下面介绍一个颇有用的命令 assemble
, 如:android
./gradlew assembleDebug
编译并打Debug包./gradlew assembleRelease
编译并打Release的包除此以外,assemble
还能够和productFlavors
结合使用:git
./gradlew installRelease
Release模式打包并安装./gradlew uninstallRelease
卸载Release模式包好比咱们想根据不一样的参数来进行不用的编译配置,能够在./gradlew
中加入自定义参数。github
./gradlew assembleDebug -Pcustom=true
就能够在build.gradle
中使用下面代码来判断:segmentfault
if (project.hasProperty('custom')){ }
assemble
还能和 Product Flavor
结合建立新的任务,其实 assemble
是和 Build Variants
一块儿结合使用的,而 Build Variants = Build Type + Product Flavor
,举个例子你们就明白了:
若是咱们想打包 wandoujia 渠道的release
版本,执行以下命令就行了:api
./gradlew assembleWandoujiaRelease
若是咱们只打wandoujia渠道版本,则:架构
./gradlew assembleWandoujia
此命令会生成wandoujia渠道的Release和Debug版本
同理我想打所有Release版本:app
./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版本。Gradle构建脚本 build.gradle
Gradle属性文件 gradle.properties
Gradle设置文件 settings.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的版本
某个Moudle的gradle配置文件:
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 就会自动的往远程库下载相应的依赖。//声明引用 com.android.application 插件,那么这个模块就是一个Android应用程序 apply plugin: 'com.android.application'
apply plugin
:声明引用插件的类型。若是是库的话就加apply plugin: 'com.android.library'
apply from
:表示引用其余的配置文件,好比 apply from:"config.gradle"
这个是 Android 插件引入的 Script blocks,想深刻了解的话看我后面的博客。
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'] //指定多个源文件目录 java.srcDirs = ['src/main/java', 'src/main/aidl'] } } //签名配置 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好比在gradle的某个地方想使用版本号,可使用下面的方法:
def getVersionCode() { int code = android.defaultConfig.versionCode return code }
repositories { flatDir { //本地jar依赖包路径 dirs '../../../../main/libs' } }
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' } }
compile
和provided
compile
表示编译时提供并打包进apk。 provided
表示只在编译时提供,不打包进apk。exclude
防止重复依赖,后面会重点介绍transitive
排除全部的传递依赖,后面会重点介绍include
CommonSDK模块的定义能够参考settings.gradle
其余的介绍能够参考 依赖库管理。
repositories
和dependencies
了吗?他们的做用是不同的,在buildscript
里面的那个是插件初始化环境用的,用于设定插件的下载仓库,而外面的这个是设定工程依赖的一些模块和远程library的下载仓库的。这个文件是全局的项目配置文件,里面主要声明一些须要加入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
类的文档。
能够在 gradle.properties 文件中配置一些变量,这些变量在这个工程下的全部module的build.gradle文件里均可以使用。这样就能够把一些共用的变量放到这里,这样后面修改的时候就能够只修改这个变量,不用各个模块都要修改了。
好比咱们在 gradle.properties SDK 版本以及应用的版本号:
MIN_SDK_VERSION=21 TARGET_SDK_VERSION=22 VERSION_CODE=200100 VERSION_NAME=2.1.0 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 /* * 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']
咱们在进行一些配置的时候可能须要知道一些变量的值,这时候能够在 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
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') }
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' }
对于项目依赖android library
的话,在这里须要使用gradle mulit project机制。
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 dependencies
能够检查依赖情况
咱们能够在项目的根目录建立一个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中修改,是否是很方便进行配置的管理呢?
运行命令./gradlew <projectname>:dependencies --configuration compile
(projectname为settings.gradle里面配置的各个project,若是没有配置,直接运行./gradlew dependencies --configuration compile
),会把依赖树会打印出来,依赖树显示了你 build 脚本声明的顶级依赖和它们的传递依赖:
仔细观察你会发现有些传递依赖标注了*号,表示这个依赖被忽略了,这是由于其余顶级依赖中也依赖了这个传递的依赖,Gradle会自动分析下载最合适的依赖。
Gradle容许你彻底控制传递依赖,你能够选择排除所有的传递依赖也能够排除指定的依赖。
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: '***-***' }
Error:java.io.IOException: Duplicate zip entry
报错。// 使用transitive属性设置为false来排除全部的传递依赖 compile project(':extras:ShimmerAndroid'){ transitive = false }
configurations.all{ resolutionStrategy{ force'org.hamcrest:hamcrest-core:1.3' } }
这样,应用中对org.hamcrest:hamcrest-core
依赖就会变成1.3版本。
若是你想使用一个依赖的最新版本,你可使用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
http://www.open-open.com/lib/view/open1431391503529.html
http://www.jianshu.com/p/429733dbbc34
主要借助
android { productFlavors{ …… } }
来实现。
网上可能是相似友盟的配置,copy过来:
http://blog.csdn.net/maosidiaoxian/article/details/42000913
http://www.javashuo.com/article/p-hsxbewvv-gy.html
在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}
的值。
另外这里记录一个 productFlavors 和 applicationId 关系的小知识。
参考文档
每一个 Android 应用均有一个惟一的应用 ID,咱们能够在经过 productFlavors 构建的应用变体中配置不一样的应用 ID。
android { defaultConfig { applicationId "com.example.myapp" } productFlavors { free { applicationIdSuffix ".free" } pro { applicationIdSuffix ".pro" } } }
这样,“免费”的 applicationId 就变为“com.example.myapp.free”。