Android build.gradle配置详解

转自://www.greatytc.com/p/c11862136abf

Android Studio是采用gradle来构建项目的,gradle是基于groovy语言的,如果只是用它构建普通Android项目的话,是可以不去学groovy的。当我们创建一个Android项目时会包含两个Android build.gradle配置详解文件,如下图:

build.gradle位置.png

一、Project的build.gradle文件:

对应的build.gradle代码如下:

// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript {//这里是gradle脚本执行所需依赖,分别是对应的maven库和插件repositories {        google()//从Android Studio3.0后新增了google()配置,可以引用google上的开源项目jcenter()//是一个类似于github的代码托管仓库,声明了jcenter()配置,可以轻松引用 jcenter上的开源项目}    dependencies {        classpath'com.android.tools.build:gradle:3.0.0'////此处是android的插件gradle,gradle是一个强大的项目构建工具//NOTE:Do not place your application dependencies here; they belong// in the individual module build.gradle files}}allprojects {//这里是项目本身需要的依赖,比如项目所需的maven库repositories {        google()        jcenter()    }}// 运行gradle clean时,执行此处定义的task任务。// 该任务继承自Delete,删除根目录中的build目录。// 相当于执行Delete.delete(rootProject.buildDir)。// gradle使用groovy语言,调用method时可以不用加()。taskclean(type: Delete){    delete rootProject.buildDir}

buildscript{}闭包里是gradle脚本执行所需依赖,分别是对应的maven库和插件。

allprojects{}闭包里是项目本身需要的依赖,比如项目所需的maven库。

task clean(type: Delete){}是运行gradle clean时,执行此处定义的task任务,该任务继承自Delete,删除根目录中的build目录。其中buildscript包含repositories闭包和dependencies闭包。

repositories{}闭包:配置远程仓库

该闭包中声明了jcenter()和google()的配置,其中jcenter是一个代码托管仓库,上面托管了很多Android开源项目,在这里配置了jcenter后我们可以在项目中方便引用jcenter上的开源项目,从Android Studio3.0后新增了google()配置,可以引用google上的开源项目。

dependencies{}闭包:配置构建工具

该闭包使用classpath声明了一个Gradle插件,由于Gradle并不只是用来构建Android项目,因此此处引入相关插件来构建Android项目,其中'3.0.0'为该插件的版本号,可以根据最新的版本号来调整。

二、Module的build.gradle文件:

从文件内容可以看出,主要分为三大部分,如下图所示:

Module的build.gradle.png

1、apply plugin:

// 声明是Android程序,//com.android.application 表示这是一个应用程序模块//com.android.library 标识这是一个库模块//而这区别:前者可以直接运行,后着是依附别的应用程序运行apply plugin:'com.android.application'

文件中第一行使用apply plugin表示应用了一个插件,该插件一般有两种值可选:

'com.android.application',表示该模块为应用程序模块,可以直接运行,打包得到的是.apk文件

'com.android.library',表示该模块为库模块,只能作为代码库依附于别的应用程序模块来运行,打包得到的是.aar文件

2、android{}闭包:

这个闭包主要为了配置项目构建的各种属性:

2.1、添加signingConfigs{}闭包:

signingConfigs {// 自动化打包配置release {// 线上环境keyAlias'test'keyPassword'123456'storeFile file('test.keystore')            storePassword'123456'}        debug {// 开发环境keyAlias'test'keyPassword'123456'storeFile file('test.keystore')            storePassword'123456'}    }

可以手动添加签名配置,也可以通过Project Structure 选中app,点击Singing添加,具体步骤如下图所示:

配置Singing.png

签名配置完成后可以方便带签名打包,在module的Build Variants中有两个Type,分别是debug和release,可以选择任意一个类型进行打包,并且他们会利用各自配置的Key进行打包,执行 Run app或者Build->Build apk就会自动在module name/app/build/outputs/apk路径下生成Apk文件。另一种打包方式是Build->Generate Signed APK填写签名信息生成Apk。

2.2、compileSdkVersion:设置编译时用的Android版本

2.3、buildToolsVersion:设置编译时使用的构建工具的版本,Android Studio3.0后去除此项配置

2.4、defaultConfig{}闭包:

compileSdkVersion27//设置编译时用的Android版本defaultConfig {        applicationId"com.billy.myapplication"//项目的包名minSdkVersion16//项目最低兼容的版本targetSdkVersion27//项目的目标版本versionCode1//版本号versionName"1.0"//版本名称testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"//表明要使用AndroidJUnitRunner进行单元测试}

applicationId:指定了项目的包名。

minSdkVersion:指定项目最低兼容的版本,如果设备小于这个版本或者大于maxSdkVersion(一般不用)将无法安装这个应用,这里指定为16,表示最低兼容到Android 4.1系统。

targetSdkVersion:指定项目的目标版本,表示在该目标版本上已经做过充分测试,系统会为该应用启动一些对应该目标系统的最新功能特性,Android系统平台的行为变更,只有targetSdkVersion的属性值被设置为大于或等于该系统平台的API版本时,才会生效。例如,若指定targetSdkVersion值为22,则表示该程序最高只在Android5.1版本上做过充分测试,在Android6.0系统上(对应targetSdkVersion为23)拥有的新特性如系统运行时权限等功能就不会被启用。

versionCode:表示版本号,一般每次打包上线时该值只能增加,打包后看不见。

versionName:表示版本名称,展示在应用市场上。

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"表明要使用AndroidJUnitRunner进行单元测试。

2.5、 buildTypes{}闭包:

这个闭包主要指定生成安装文件的主要配置,一般包含两个子闭包,一个是debug闭包,用于指定生成测试版安装文件的配置,可以忽略不写;另一个是release闭包,用于指定生成正式版安装文件的配置。两者能配置的参数相同,最大的区别默认属性配置不一样,两种模式支持的属性配置如下图:

buildTypes配置.png

buildTypes {// 生产/测试环境配置release {// 生产环境buildConfigField("boolean","LOG_DEBUG","false")//配置Log日志buildConfigField("String","URL_PERFIX","\"https://release.cn/\"")// 配置URL前缀minifyEnabledfalse//是否对代码进行混淆proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'//指定混淆的规则文件signingConfig signingConfigs.release//设置签名信息pseudoLocalesEnabledfalse//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多zipAlignEnabledtrue//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率applicationIdSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多versionNameSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多}        debug {// 测试环境buildConfigField("boolean","LOG_DEBUG","true")//配置Log日志buildConfigField("String","URL_PERFIX","\"https://test.com/\"")// 配置URL前缀minifyEnabledfalse//是否对代码进行混淆proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'//指定混淆的规则文件signingConfig signingConfigs.debug//设置签名信息debuggablefalse//是否支持断点调试jniDebuggablefalse//是否可以调试NDK代码renderscriptDebuggablefalse//是否开启渲染脚本就是一些c写的渲染方法zipAlignEnabledtrue//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率pseudoLocalesEnabledfalse//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多applicationIdSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多versionNameSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多}    }

release{}闭包和debug{}闭包两者能配置的参数相同,最大的区别默认属性配置不一样:

minifyEnabled:表明是否对代码进行混淆,true表示对代码进行混淆,false表示对代码不进行混淆,默认的是false。

proguardFiles:指定混淆的规则文件,这里指定了proguard-android.txt文件和proguard-rules.pro文件两个文件,proguard-android.txt文件为默认的混淆文件,里面定义了一些通用的混淆规则。proguard-rules.pro文件位于当前项目的根目录下,可以在该文件中定义一些项目特有的混淆规则。

buildConfigField:用于解决Beta版本服务和Release版本服务地址不同或者一些Log打印需求控制的。例如:配置buildConfigField("boolean", "LOG_DEBUG", "true"),这个方法接收三个非空的参数,第一个:确定值的类型,第二个:指定key的名字,第三个:传值,调用的时候BuildConfig.LOG_DEBUG即可调用。

debuggable:表示是否支持断点调试,release默认为false,debug默认为true。

jniDebuggable:表示是否可以调试NDK代码,使用lldb进行c和c++代码调试,release默认为false

signingConfig:设置签名信息,通过signingConfigs.release或者signingConfigs.debug,配置相应的签名,但是添加此配置前必须先添加signingConfigs闭包,添加相应的签名信息。

renderscriptDebuggable:表示是否开启渲染脚本就是一些c写的渲染方法,默认为false。

renderscriptOptimLevel:表示渲染等级,默认是3。

pseudoLocalesEnabled:是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多。

applicationIdSuffix:和defaultConfig中配置是一的,这里是在applicationId 中添加了一个后缀,一般使用的不多。

versionNameSuffix:表示添加版本名称的后缀,一般使用的不多。

zipAlignEnabled:表示是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率,release和debug默认都为true。

2.6、sourceSets{}闭包:配置目录指向

sourceSets {//目录指向配置main {            jniLibs.srcDirs = ['libs']//指定lib库目录}    }

配置 jniLibs.srcDirs = ['libs'],可以在Android studio的Android视图下生成jniLibs文件夹,可以方便我们存放jar包和库文件,其中Android视图下的jniLibs和project视图下的libs指向同一文件夹(app→libs),如下图所示:

jniLibs.png

2.7、packagingOptions{}闭包:打包时的相关配置

当项目中依赖的第三方库越来越多时,有可能会出现两个依赖库中存在同一个(名称)文件。如果这样,Gradle在打包时就会提示错误(警告)。那么就可以根据提示,然后使用以下方法将重复的文件剔除,比较常用的是通过exclude去除重复的文件,例如:

packagingOptions{//pickFirsts做用是 当有重复文件时 打包会报错 这样配置会使用第一个匹配的文件打包进入apk// 表示当apk中有重复的META-INF目录下有重复的LICENSE文件时  只用第一个 这样打包就不会报错pickFirsts = ['META-INF/LICENSE']//merges何必 当出现重复文件时 合并重复的文件 然后打包入apk//这个是有默认值得 merges = [] 这样会把默默认值去掉  所以我们用下面这种方式 在默认值后添加merge'META-INF/LICENSE'//这个是在同时使用butterknife、dagger2做的一个处理。同理,遇到类似的问题,只要根据gradle的提示,做类似处理即可。exclude'META-INF/services/javax.annotation.processing.Processor'}

2.8、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(windows)即可开始打包,在Mac系统中对应指令应该是./gradlew assembleRelease。当然,如果想要debug版本的包,将指令中assembleRelease改为assembleDebug即可。最后生成的包还是在app/build/outputs/apk中,默认命名格式如app-wandoujia-release-unsigned.apk,在module的Build Variants中可以选择相应的渠道。

注:Android Studio3.0需在主app的build.gradle里面的

defaultConfig {

targetSdkVersion:***

minSdkVersion :***

versionCode:***

versionName :***

//版本名后面添加一句话,意思就是flavor dimension 它的维度就是该版本号,这样维度就是都是统一的了

flavorDimensions "versionCode"

}

2.9、lintOptions{}闭包:代码扫描分析

Lint 是Android Studio 提供的 代码扫描分析工具,它可以帮助我们发现代码结构/质量问题,同时提供一些解决方案,而且这个过程不需要我们手写测试用例。

Lint 发现的每个问题都有描述信息和等级(和测试发现 bug 很相似),我们可以很方便地定位问题,同时按照严重程度进行解决。

//程序在编译的时候会检查lint,有任何错误提示会停止build,我们可以关闭这个开关lintOptions {        abortOnErrorfalse//即使报错也不会停止打包checkReleaseBuildsfalse//打包release版本的时候进行检测}

3、dependencies{}闭包:

该闭包定义了项目的依赖关系,一般项目都有三种依赖方式:本地依赖、库依赖和远程依赖。本地依赖可以对本地的jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖可以对jcener库上的开源项目添加依赖关系。从Android Studio3.0后compile引入库不在使用,而是通过api和implementation,api完全等同于以前的compile,用api引入的库整个项目都可以使用,用implementation引入的库只有对应的Module能使用,其他Module不能使用,由于之前的项目统一用compile依赖,导致的情况就是模块耦合性太高,不利于项目拆解,使用implementation之后虽然使用起来复杂了但是做到降低偶合兴提高安全性。

dependencies {//项目的依赖关系implementation fileTree(include: ['*.jar'], dir:'libs')//本地jar包依赖implementation'com.android.support:appcompat-v7:27.1.1'//远程依赖implementation'com.android.support.constraint:constraint-layout:1.1.2'testImplementation'junit:junit:4.12'//声明测试用例库androidTestImplementation'com.android.support.test:runner:1.0.2'androidTestImplementation'com.android.support.test.espresso:espresso-core:3.0.2'}

implementation fileTree(include: ['*.jar'], dir: 'libs'):implementation fileTree是一个本地依赖声明,表示将libs目录下所有.jar后缀的文件都添加到项目的构建路径当中。

implementation 'com.android.support:appcompat-v7:27.1.1':implementation语句为 远程依赖声明,'com.android.support:appcompat-v7:27.1.1'为一个标准的远程依赖库格式,其中com.android.support为域名部分,用于区分不同公司的库;appcompat-v7为组件名称,用于区分同一个公司的不同库;27.1.1为版本号,用于区分同一个库的不同版本。加上这句声明后,Gradle在构建项目时会先检查一下本地是否已经缓存过该库,若没有缓存则自动联网下载,下载后自动添加到项目的构建路径中去。

testImplementation和androidTestImplementation:表示声明测试用例库。

Module完整的build.gradle配置如下:

// 声明是Android程序,//com.android.application 表示这是一个应用程序模块//com.android.library 标识这是一个库模块//而这区别:前者可以直接运行,后着是依附别的应用程序运行apply plugin:'com.android.application'android {    signingConfigs {// 自动化打包配置release {// 线上环境keyAlias'test'keyPassword'123456'storeFile file('test.jks')            storePassword'123456'}        debug {// 开发环境keyAlias'test'keyPassword'123456'storeFile file('test.jks')            storePassword'123456'}    }    compileSdkVersion27//设置编译时用的Android版本defaultConfig {        applicationId"com.billy.myapplication"//项目的包名minSdkVersion16//项目最低兼容的版本targetSdkVersion27//项目的目标版本versionCode1//版本号versionName"1.0"//版本名称flavorDimensions"versionCode"testInstrumentationRunner"android.support.test.runner.AndroidJUnitRunner"//表明要使用AndroidJUnitRunner进行单元测试}    buildTypes {// 生产/测试环境配置release {// 生产环境buildConfigField("boolean","LOG_DEBUG","false")//配置Log日志buildConfigField("String","URL_PERFIX","\"https://release.cn/\"")// 配置URL前缀minifyEnabledfalse//是否对代码进行混淆proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'//指定混淆的规则文件signingConfig signingConfigs.release//设置签名信息pseudoLocalesEnabledfalse//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多zipAlignEnabledtrue//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率applicationIdSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多versionNameSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多}        debug {// 测试环境buildConfigField("boolean","LOG_DEBUG","true")//配置Log日志buildConfigField("String","URL_PERFIX","\"https://test.com/\"")// 配置URL前缀minifyEnabledfalse//是否对代码进行混淆proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro'//指定混淆的规则文件signingConfig signingConfigs.debug//设置签名信息debuggablefalse//是否支持断点调试jniDebuggablefalse//是否可以调试NDK代码renderscriptDebuggablefalse//是否开启渲染脚本就是一些c写的渲染方法zipAlignEnabledtrue//是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率pseudoLocalesEnabledfalse//是否在APK中生成伪语言环境,帮助国际化的东西,一般使用的不多applicationIdSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多versionNameSuffix'test'//在applicationId 中添加了一个后缀,一般使用的不多}    }    sourceSets {//目录指向配置main {            jniLibs.srcDirs = ['libs']//指定lib库目录}    }    packagingOptions{//打包时的相关配置//pickFirsts做用是 当有重复文件时 打包会报错 这样配置会使用第一个匹配的文件打包进入apk// 表示当apk中有重复的META-INF目录下有重复的LICENSE文件时  只用第一个 这样打包就不会报错pickFirsts = ['META-INF/LICENSE']//merges何必 当出现重复文件时 合并重复的文件 然后打包入apk//这个是有默认值得 merges = [] 这样会把默默认值去掉  所以我们用下面这种方式 在默认值后添加merge'META-INF/LICENSE'//这个是在同时使用butterknife、dagger2做的一个处理。同理,遇到类似的问题,只要根据gradle的提示,做类似处理即可。exclude'META-INF/services/javax.annotation.processing.Processor'}    productFlavors {        wandoujia {}        xiaomi {}        _360 {}    }    productFlavors.all {//批量修改,类似一个循序遍历flavor -> flavor.manifestPlaceholders = [IFLYTEK_CHANNEL: name]    }//程序在编译的时候会检查lint,有任何错误提示会停止build,我们可以关闭这个开关lintOptions {        abortOnErrorfalse//即使报错也不会停止打包checkReleaseBuildsfalse//打包release版本的时候进行检测}}dependencies {//项目的依赖关系implementation fileTree(include: ['*.jar'], dir:'libs')//本地jar包依赖implementation'com.android.support:appcompat-v7:27.1.1'//远程依赖implementation'com.android.support.constraint:constraint-layout:1.1.2'testImplementation'junit:junit:4.12'//声明测试用例库androidTestImplementation'com.android.support.test:runner:1.0.2'androidTestImplementation'com.android.support.test.espresso:espresso-core:3.0.2'}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容