Android Studio是采用gradle来构建项目的,gradle是基于groovy语言的,若是只是用它构建普通Android项目的话,是能够不去学groovy的。当咱们建立一个Android项目时会包含两个Android build.gradle配置详解文件,以下图:javascript
对应的build.gradle代码以下:php
// 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时能够不用加()。
task clean(type: Delete) {
delete rootProject.buildDir
}
复制代码
该闭包中声明了jcenter()和google()的配置,其中jcenter是一个代码托管仓库,上面托管了不少Android开源项目,在这里配置了jcenter后咱们能够在项目中方便引用jcenter上的开源项目,从Android Studio3.0后新增了google()配置,能够引用google上的开源项目。java
该闭包使用classpath声明了一个Gradle插件,因为Gradle并不仅是用来构建Android项目,所以此处引入相关插件来构建Android项目,其中'3.0.0'为该插件的版本号,能够根据最新的版本号来调整。android
从文件内容能够看出,主要分为三大部分,以下图所示:c++
// 声明是Android程序,
//com.android.application 表示这是一个应用程序模块
//com.android.library 标识这是一个库模块
//而这区别:前者能够直接运行,后着是依附别的应用程序运行
apply plugin: 'com.android.application'
复制代码
文件中第一行使用apply plugin表示应用了一个插件,该插件通常有两种值可选:git
这个闭包主要为了配置项目构建的各类属性:github
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添加,具体步骤以下图所示:windows
签名配置完成后能够方便带签名打包,在module的Build Variants中有两个Type,分别是debug和release,能够选择任意一个类型进行打包,而且他们会利用各自配置的Key进行打包,执行 Run app或者Build->Build apk就会自动在module name/app/build/outputs/apk路径下生成Apk文件。另外一种打包方式是Build->Generate Signed APK填写签名信息生成Apk。api
compileSdkVersion 27//设置编译时用的Android版本
defaultConfig {
applicationId "com.billy.myapplication"//项目的包名
minSdkVersion 16//项目最低兼容的版本
targetSdkVersion 27//项目的目标版本
versionCode 1//版本号
versionName "1.0"//版本名称
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"//代表要使用AndroidJUnitRunner进行单元测试
}
复制代码
这个闭包主要指定生成安装文件的主要配置,通常包含两个子闭包,一个是debug闭包,用于指定生成测试版安装文件的配置,能够忽略不写;另外一个是release闭包,用于指定生成正式版安装文件的配置。二者能配置的参数相同,最大的区别默认属性配置不同,两种模式支持的属性配置以下图:缓存
buildTypes {// 生产/测试环境配置
release {// 生产环境
buildConfigField("boolean", "LOG_DEBUG", "false")//配置Log日志
buildConfigField("String", "URL_PERFIX", "\"https://release.cn/\"")// 配置URL前缀
minifyEnabled false//是否对代码进行混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
signingConfig signingConfigs.release//设置签名信息
pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,通常使用的很少
zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减少zip体积,增长运行效率
applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,通常使用的很少
versionNameSuffix 'test'//在applicationId 中添加了一个后缀,通常使用的很少
}
debug {// 测试环境
buildConfigField("boolean", "LOG_DEBUG", "true")//配置Log日志
buildConfigField("String", "URL_PERFIX", "\"https://test.com/\"")// 配置URL前缀
minifyEnabled false//是否对代码进行混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
signingConfig signingConfigs.debug//设置签名信息
debuggable false//是否支持断点调试
jniDebuggable false//是否能够调试NDK代码
renderscriptDebuggable false//是否开启渲染脚本就是一些c写的渲染方法
zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减少zip体积,增长运行效率
pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,通常使用的很少
applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,通常使用的很少
versionNameSuffix 'test'//在applicationId 中添加了一个后缀,通常使用的很少
}
}
复制代码
sourceSets {//目录指向配置
main {
jniLibs.srcDirs = ['libs']//指定lib库目录
}
}
复制代码
配置 jniLibs.srcDirs = ['libs'],能够在Android studio的Android视图下生成jniLibs文件夹,能够方便咱们存放jar包和库文件,其中Android视图下的jniLibs和project视图下的libs指向同一文件夹(app→libs),以下图所示:
当项目中依赖的第三方库愈来愈多时,有可能会出现两个依赖库中存在同一个(名称)文件。若是这样,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'
}
复制代码
这个配置是常常会使用到的,一般在适配多个渠道的时候,须要为特定的渠道作部分特殊的处理,好比设置不一样的包名、应用名等。场景:当咱们使用友盟统计时,一般须要设置一个渠道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"
}
Lint 是Android Studio 提供的 代码扫描分析工具,它能够帮助咱们发现代码结构/质量问题,同时提供一些解决方案,并且这个过程不须要咱们手写测试用例。
Lint 发现的每一个问题都有描述信息和等级(和测试发现 bug 很类似),咱们能够很方便地定位问题,同时按照严重程度进行解决。
//程序在编译的时候会检查lint,有任何错误提示会中止build,咱们能够关闭这个开关
lintOptions {
abortOnError false //即便报错也不会中止打包
checkReleaseBuilds false //打包release版本的时候进行检测
}
复制代码
该闭包定义了项目的依赖关系,通常项目都有三种依赖方式:本地依赖、库依赖和远程依赖。本地依赖能够对本地的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'
}
复制代码
// 声明是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'
}
}
compileSdkVersion 27//设置编译时用的Android版本
defaultConfig {
applicationId "com.billy.myapplication"//项目的包名
minSdkVersion 16//项目最低兼容的版本
targetSdkVersion 27//项目的目标版本
versionCode 1//版本号
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前缀
minifyEnabled false//是否对代码进行混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
signingConfig signingConfigs.release//设置签名信息
pseudoLocalesEnabled false//是否在APK中生成伪语言环境,帮助国际化的东西,通常使用的很少
zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减少zip体积,增长运行效率
applicationIdSuffix 'test'//在applicationId 中添加了一个后缀,通常使用的很少
versionNameSuffix 'test'//在applicationId 中添加了一个后缀,通常使用的很少
}
debug {// 测试环境
buildConfigField("boolean", "LOG_DEBUG", "true")//配置Log日志
buildConfigField("String", "URL_PERFIX", "\"https://test.com/\"")// 配置URL前缀
minifyEnabled false//是否对代码进行混淆
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'//指定混淆的规则文件
signingConfig signingConfigs.debug//设置签名信息
debuggable false//是否支持断点调试
jniDebuggable false//是否能够调试NDK代码
renderscriptDebuggable false//是否开启渲染脚本就是一些c写的渲染方法
zipAlignEnabled true//是否对APK包执行ZIP对齐优化,减少zip体积,增长运行效率
pseudoLocalesEnabled false//是否在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 {
abortOnError false
//即便报错也不会中止打包
checkReleaseBuilds false
//打包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'
}
复制代码