从build.gradle(Project)说起
//buildscript中的声明是gradle脚本自身需要使用的资源
//可以声明的资源包括依赖项、第三方插件、maven仓库地址等。
buildscript {
repositories {
jcenter() //使用jcenter库
//mavenCentral()
}
dependencies {
// Google 在推出 AS 的时候选中了 Gradle 作为构建工具,为了支持 Gradle 能在 AS 上使用,
// Google 做了个 AS 的插件叫 Android Gradle Plugin ,所以我们能在 AS 上使用 Gradle 完全是因为这个插件的原因。
// 比如:apply plugin: 'com.android.application'就是这个插件库提供的。
classpath 'com.android.tools.build:gradle:2.2.2'
//注意:不要在这里配置项目所需要的依赖
}
}
//项目自身所需要的一些配置
allprojects {
repositories {
jcenter()
}
}
1. com.android.tools.build:gradle
提到这个文件主要是为了介绍一下tools.build:gradle这个依赖。这个通常容易被误解为就是gradle的版本,但这个其实是Google为了让我们能够在AS中使用Gradle而提供的一个插件库。Gradle设计时有一个理念就是,他只负责一些最基础的任务,而特性化的功能都交于插件来封装与实现。例如:我们熟知的apply plugin: ‘com.android.application’就是来自这个插件库。有兴趣查看其版本更新日志的详见:http://tools.android.com/tech-docs/new-build-system
2. Gradle版本
从这个目录下我们便可以直接看出Gradle版本 和 插件的版本。
我们已经知道了插件版本的配置了,关于Gradle版本的配置位置见:
3. Gradle版本与插件库的关系
Gradle 是新一代的自动化构建工具,他是一个独立的项目,跟 AS、Android 无关。但是Google在开发和设计AS时,选择了Gradle来作为他的构建工具,因此为了在AS中可以使用Gradle,也就有了我们上面所提到的tools.build:gradle所对应的这个插件库(Android Gradle Plugin)。由此可见,我们Gradle的版本应该是与插件版本是相关的,从官网([Android Plugin for Gradle Release Notes][3])可以看到这张关系图:
(ps:现在Gradle的版本3.+应该是对应插件版本2.2.+)
4. Gradle版本与插件库的版本升级
插件版本:直接修改版本号,然后点击Sync now,处理完即可。由于这个版本是直接有Google来控制的,因此当有新的版本出现时,这个位置将会给出一个警告的提示甚至是直接弹出提示你可以升级了。
classpath 'com.android.tools.build:gradle:2.2.2'
Gradle版本:按原理来讲,这个版本的升级也是非常方便的。但是这一下载升级的步骤交给AS来处理,会发现是出奇的慢。至于最新的版本是多少,可以直接通过该网站:https://services.gradle.org/distributions 查看。
我们先从正常步骤开始(以Window平台以及更新为3.1版本为例):
- 修改Gradle版本:即修改 “distributionUrl=https://services.gradle.org/distributions/gradle-3.1-all.zip” 这个位置
- 在Terminal终端输入指令并执行,已gradlew -v为例。这时候AS检查发现要不是不存在你所指定的gradle版本,那么他就会开始下载(过程在终端呈现),然而坑也在这时候出现了。
- 当你在该目录下发现已经存在对应的目录时就可以在终端点击终止按钮了(左侧关闭终端按钮),这前提应该要求你选择的是Use default gradle wrapper
- 从 https://services.gradle.org/distributions 下载3.1的版本后,直接将压缩包放在上图对应的ejgg…m74目录中即可。
- 最后还是开启终端,输入并执行gradlew -v ,这时候剩下就是解压关联工作了,等他运行完即可。
还是build.gradle(Module)
//表示该module是一个应用(application)模块,应用了com.android.application插件;
//(如果是一个android library,那么这里的是apply plugin:'com.android.library')
apply plugin: 'com.android.application'
//安卓项目相关的配置,后续章节将进行更为详细的介绍
android {
//编译项目所用的SDK版本(即编译时的API版本),com.android.support的版本需要与这个一致
//建议(总是)采用最新版本
compileSdkVersion 23
//构建工具版本
buildToolsVersion "23.0.3"
defaultConfig {
//安装时,依据该ID区分是否为同一个应用
applicationId "com.wiky.supporttest"
//最低支持的系统版本(必须>=所有依赖库所支持的最低版本)
minSdkVersion 9
//举例说明其作用:假设我们compileSdkVersion采用了23(6.0),但是项目暂时还未对6.0的特性(如运行时权限)做相应的处理,
//那么可以设置targetSdkVersion的版本低于23。这样,应用仍可以正常运行在6.0的机子上(当然也就不具有运行时权限的特性)。
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
//
productFlavors {
lct {
}
}
// buildTypes是构建类型,常用的有release和debug两种,可以在这里面启用混淆,启用zipAlign以及配置签名信息等。后面再具体介绍
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
buildConfigField "boolean", "LOG_DEBUG", "false"
}
}
}
//该module所需的依赖库配置
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
}
1. apply plugin: ‘com.android.application’
在前面提及过,这个插件即来自tools.build:gradle插件库,在文件开头声明使用application插件,才使得gradle文件支持android{}等语法已经相关关键字的使用。
2. buildToolsVersion
这个是构建工具版本,即…\SDK\build-tools该目录所对应,其中包括的工具有aapt(将资源文件打包转换成二进制文件)、 dx(生词dex文件)、zipalign(打包生成apk)等工具,这些都是app构建过程中需要使用的。
3.productFlavors 与 buildTypes
通常我们的buildTypes分为debug与release两个版本,这便意味着,我们可以在项目中创建对应的目录,进行对不同版本的代码进行差异性设计,如:
但是,在一些情况下,两个版本(debug/release)并不能满足我们的需求,这时候就需要借助productFlavors,如配置了lct后,我们就有了lctDebug、lctRelease,如此我们便可以处理更多的情况。具体使用参考:[Gradle Recipes for Android][7] 第三章
4.buildConfigField
BuildConfig.java是Android Gradle自动生成的一个java类文件,无法手动编译,但是可以通过Gradle控制,也就是说他是动态可配置的。比如在build.gradle中配置buildConfigField “boolean”, “LOG_DEBUG”, “false”后,我们点击“Sync now”后,即可在代码中使用BuildConfig.java新加的LOG_DEBUG属性,如:
public final class BuildConfig {
//...
// Fields from build type: debug
public static final boolean LOG_DEBUG = true;
}
buildConfigField 一共有3个参数,第一个是数据类型,即新增成员变量的类型(与Java的类型是对等);第二个参数是成员变量名,如:LOG_DEBUG;第三个参数是常量值。
以下我们介绍一种常见的用法,场景:我们需要在debug版本包中输出log,而不希望在release版本中输出log,那么就可以通过以下方法进行配置(当然,我们代码中的log开关是使用BuildConfig中相关属性进行设置的):
buildTypes {
debug {
// 显示Log
buildConfigField "boolean", "LOG_DEBUG", "true"
//...
}
release {
// 不显示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
//...
}
}
另外,还用一种常见的情况是:当我们的服务器有debug和release环境时,我们可能也需要在App对应的版本中配置对应的信息。如在debug版本中配置服务端debug环境对应的url。这样我们在开发的过程中将减少很多麻烦的工作
Android Plugin DSL
android 的DSL容器(详见:[Android Plugin DSL Reference][8] )
android {
defaultConfig {
//默认配置项
}
buildTypes {
// 编译配置,release或debug版本的内容
}
compileOptions {
// Java 的版本配置
}
sourceSets {
//源码设置(项目目录结构的设置)
}
packagingOptions {
//打包时的相关配置
}
lintOptions {
//编译的 lint 开关,程序在buid的时候,会执行lint检查,有任何的错误或者警告提示,都会终止构建,我们可以将其关掉。
//abortOnError false
}
productFlavors {
//产品发布的一些东西,比如渠道、包名等
flavor1 {
}
flavor2 {
}
}
signingConfigs {
//签名的配置
release {
}
}
//Request the use a of Library. The library is then added to the classpath.
useLibrary 'org.apache.http.legacy'
}
5. buildTypes–编译配置
这里主要是对release与debug版本做些不同的配置,如是否启用混淆、修改对应版本的包名、对应版本使用的签名等,默认为debug与release两个类型,当然也可以自定义添加新类型,如下:(更多配置可以查看:[Build Types(构建类型)][9])。
buildTypes {
release {
//为发布版本启用混淆
minifyEnabled true
//混淆文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
//将debug版本的包名后缀设置为.debug以便能够同时在一台设备上安装debug和release版本的apk。
applicationIdSuffix ".debug"
}
//创建了一个名为jnidebug的新构建类型,并且这个构建类型是debug构建类型的一个副本。
jnidebug.initWith(buildTypes.debug)
jnidebug {
jnidebugBuild true //继续配置jnidebug构建类型,允许使用JNI组件
}
}
这里有一些可能用到的属性以及他们的默认值:
除了以上属性之外,Build Type还会受项目源码和资源影响: 对于每一个Build Type都会自动创建一个匹配的sourceSet。默认的路径为:
src/(buildtypename)/
6. compileOptions–配置JDK版本
- sourceCompatibility : JAVA(源码)版本
- targetCompatibility : 生成JAVA字节码的版本
类似compileSdkVersion与targetSdkVersion
compileOptions {
//配置使用JDK1.8(8),比如需要使用Lambda特性时,那么就可以在这里进行JDK版本的配置
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
7. sourceSets
Gradle约定了一个默认的文件夹结构:
src/main
src/androidTest/对于Java和Android这两个插件来说,他们的Java源代码和Java资源的位置是:
java/
resources/对于Android插件来说,它还有以下特性文件和文件夹:
AndroidManifest.xml
res/
assets/
aidl/
rs/
jni/
配置项目的目录结构,其中较为常见的一个应用场景是,将Eclipse 中的项目迁移至AS,由于两者目录结构相差较大,所以需要手动指定,部分代码如:
( 更多介绍可以查看:工程结构)
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
jniLibs.srcDirs = ['libs']
}
}
8. packagingOptions 打包时的相关配置
当项目中依赖的第三方库越来越多时,有可能会出现两个依赖库中存在同一个(名称)文件。如果这样,Gradle在打包时就会提示错误(警告)。那么就可以根据提示,然后使用以下方法将重复的文件剔除。
packagingOptions {
//这个是在同时使用butterknife、dagger2做的一个处理。同理,遇到类似的问题,只要根据gradle的提示,做类似处理即可。
exclude 'META-INF/services/javax.annotation.processing.Processor'
}
9. lintOptions
lint是一种静态程序分析工具,用来标记源代码中,某些可疑的、不具结构性(可能造成bug)的段落。
可以为特定 variant 运行 lint,例如 ./gradlew lintRelease,或为所有 variants 运行(./gradlew lint),这种情况下会生成一份包含特定版本存在的问题的详细报告。我们可以在AS里对报告样式、级别等继续设置:
而对于Lint功能的配置,可以见下图:
lintOptions {
// if true, stop the gradle build if errors are found
abortOnError false
// if true, only report errors
ignoreWarnings true
// if true, treat all warnings as errors
warningsAsErrors true
// turn off checking the given issue id's
disable 'TypographyFractions','TypographyQuotes'
// turn on the given issue id's
enable 'RtlHardcoded','RtlCompat', 'RtlEnabled'
// check *only* the given issue id's
check 'NewApi', 'InlinedApi'
// if true, generate an XML report for use by for example Jenkins
xmlReport false
}
查看issue id的方式:在SDK的toosl目录下(有lint相关的文件),运行cmd并输入lint –list,如:
Example : [lint hardCoded text][14]
10. productFlavors
这个配置是经常会使用到的,通常在适配多个渠道的时候,需要为特定的渠道做部分特殊的处理,比如设置不同的包名、应用名等。场景:当我们使用友盟统计时,通常需要设置一个渠道ID,那么我们就可以利用productFlavors来生成对应渠道信息的包,如:
android {
productFlavors {
wandoujia {
//豌豆荚渠道包配置
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
//manifestPlaceholders的使用在后续章节(AndroidManifest里的占位符)中介绍
}
xiaomi {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
applicationId "com.wiky.gradle.xiaomi" //配置包名
}
_360 {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "_360"]
}
//...
}
}
当然也有更简洁的方式:
android {
productFlavors {
wandoujia {}
xiaomi {}
_360 {}
//...
}
productFlavors.all {
//批量修改,类似一个循序遍历
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
配置完之后,在命令行窗口中(Terminal)中输入gradlew assembleRelease(window)即可开始打包,在Mac系统中对应指令应该是./gradlew assembleRelease。当然,如果想要debug版本的包,将指令中assembleRelease改为assembleDebug即可。最后生成的包还是在app/build/outputs/apk中,默认命名格式如app-wandoujia-release-unsigned.apk。
11. signingConfigs–应用签名配置
为release版本配置签名,如:
android {
signingConfigs {
release {
//签名证书文件
storeFile file("release.keystore")
//别名
keyAlias "release"
//key的密码
keyPassword "123456"
//证书的密码
storePassword "123456"
}
debug {
}
}
//需要注意的是:配置好签名信息后,需要在buildTypes配置使用
buildTypes {
release {
signingConfig signingConfigs.release
}
debug {
}
}
}
统一依赖管理
1. gradle.properties(Project)全局配置
在gradle的目录结构下,项目配置(自定义参数)的作用域为:在Project中配置的参数在各个子module中都可以使用,反正则不行。这很好理解,与我们平时的编程习惯一致。从google开源的项目中,我们可以看到他的依赖管理正式是利用了gradle.properties(Project)这个文件,如:我们添加了support_version = 23.3.0后,在build.gradle进行添加依赖时即可写为:
compile "com.android.support:appcompat-v7:$support_version" //注意使用双引号已经$符号
2. 在build.gradle(Project)中配置
写法如:
allprojects {
ext{
support_version = '25.0.0'
}
//或者ext.support_version = '25.0.0'
repositories {
jcenter()
}
}
使用还是:
compile "com.android.support:appcompat-v7:$support_version" //注意使用双引号已经$符号