@946898963
2021-06-04T16:22:14.000000Z
字数 15418
阅读 1332
AndroidStudio
Gradle
最近老大在群里扔了一个给Gradle设置代理的链接,设置代理的过程中发现自己对Android Studio中的Gradle的相关知识不是很熟悉了(汗),所以特地在周末查了资料重新熟悉了下。
软件开发过程不仅仅是编写代码,还涉及到对项目的管理,比如:编译、签名、打包、依赖管理等一系列操作,为了复用以及自动运行这些操作,我们可以用代码来描述这些功能,而构建工具就是可以让我们用代码描述这些功能,并为这些功能性代码的运行提供环境支持的工具。
传统的构建工具有Make、Ant、Maven、Ivy等,而Android Studio中使用的是Gradle,所以接下来我们要对Android Studio中的Gradle的相关配置进行讲解。
Gradle
Gradle是一个基于JVM的构建工具,是一款通用灵活的构建工具,基于Groovy,build脚本使用Groovy编写,在android项目中可以自动帮我们完成项目的依赖,打包,签名,发布等一系列操作。
Gradle插件
Android Gradle Plugin作用是对Android项目提供Gradle构建环境,让开发者可以通过Gradle工具来运行构建。Gradle插件为Gradle的运行提供了环境支持。
BuildTools
Android构建的相关工具都在这里面,位于./sdk/build-tools/目录下,它提供了类似aapt、dx这样的工具,gradle则是使用这样的工具来完成相应的构建任务。
总结来说,Gradle插件为Gradle提供了运行环境,而BuildTools则是Gradle完成操作所需要借助的工具的集合。
更新Gradle也有两种方式:
安装Android Studio后就已经帮我安装了Gradle插件.但Gradle插件是独立于Android Studio运行的,所以它的更新也是与Android Studio分开的。
指定Gradle插件版本有两种方式:
下面的例子在build.gradle中设置Gradle插件版本为2.2.0:
buildscript {
...
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
}
}
注意:不应该动态指定版本号,如"com.android.tools.build:gradle:2.+".这样做可能会导致意外的版本更新,并且会给解决版本差异带来困难。
如果指定的版本没有下载下来,那么项目在下次构建的时候Gradle会再去下载。或者你也可以点击Tools > Android > Sync Project with Gradle Files去下载。
补充:Gradle插件的保存路径是
Mac系统默认下载到:/Users/(用户名)/.gradle/caches/modules-2/files-2.1
Windows系统默认下载到:C:\Users(用户名).gradle\caches\modules-2\files-2.1
注意,这个路径恰好是Gradle下载的依赖包的保存路径。
app目录下的build.gradle
apply plugin: 'com.android.application'
android {
....
buildToolsVersion "25.0.2"
defaultConfig {
....
}
buildTypes {
release {
....
}
}
}
dependencies {
....
}
因为Gradle仍在发展,在不断更新,自然Gradle插件和BuildTools也需要不断更新版本才能提供对新版本Gradle的支持,它们之间存在着版本对应关系。
当我们在setting下gradle下设置gradle选择“use defalut gradle wrapper(recommended)”时,as就会根据{project.dir}\gradle\wrapper\gradle-wrapper.properties文件中的配置去查找gradle。
我们用as构建android项目时,配置gradle时我们必须在{project.dir}\gradle\wrapper\gradle-wrapper.properties文件中配置gradle包。
#Mon Sep 11 14:41:13 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
GRADLE_USER_HOME是我们配置的Gradle所在路径的环境变量。配置的时候可以是“用户主目录/.gradle”或者as安装目录下的gradle目录。
这个配置的gradle如果在目录“用户主目录/.gradle/wrapper/dists/..”存在的话,as就不会去https://services.gradle.org/distributions/gradle-3.3-all.zip去下载了,as就会利用该目录下对应版本的gradle进行相应自动编译操作,如果该目录下不存在gradle的话as就会去站点根据gradle的版本去下载到“用户主目录/.gradle/wrapper/dists/gradle-3.3-all”目录下。
当我们在setting下gradle下设置gradle,如果选择的是“use local gradle distribution”的话,表示用的是本地的gradle,一般情况下本地的gradle目录会选择as的主目录下的gradle目录。这个时候{project.dir}\gradle\wrapper\gradle-wrapper.properties文件中的配置就会失效,也就是说as不会去“用户主目录/.gradle/wrapper/dists/gradle-..*”中去查找gradle。
前面的两个配置是查找构建项目所需要的gradle,而如何Offline work(离线模式)则是和gradle管理依赖有关,选择这个选项,开启离线模式后,Gradle将不会联网查找依赖,而是仅从本地缓存中查找,所以要慎重开启此选项。
补充:
Gradle下载的依赖包的缓存目录
Mac系统默认下载到:/Users/(用户名)/.gradle/caches/modules-2/files-2.1
Windows系统默认下载到:C:\Users(用户名).gradle\caches\modules-2\files-2.1
配置用户环境变量的方法
打开终端输入 open .bash_profile,添加如下内容:
GRADLE_HOME=“用户主目录/.gradle”或者as安装目录下的gradle目录
export GRADLE_HOME
export PATH=$PATH:$GRADLE_HOME/bin
保存退出后,在终端输入:source .bash_profile更新配置。
Gradle下载依赖的时候,Gradle默认直连网络,即使Mac设置了全局代理也是一样。就算你给Android Studio设置了代理,它依旧会风轻云淡地直连那个你在中国一辈子也不可能连上的网站……
要让Gradle走代理,加快下载依赖包的速度,你需要给它进行单独的配置。
socks
gradle -DsocksProxyHost=127.0.0.1 -DsocksProxyPort=1080 build
http
gradle -Dhttp.proxyHost=127.0.0.1 -Dhttp.proxyPort=8080 build
https
gradlew -Dhttps.proxyHost=127.0.0.1 -Dhttps.proxyPort=8080 build
在.gradle目录中创建gradle.properties文件,.gradle目录默认在用户目录下(区别window/linux),如果你设置了环境变量GRADLE_USER_HOME=“地址”,那么就在这个地址下。
在gradle.properties加入如下内容:
socks
systemProp.socksProxyHost=127.0.0.1
systemProp.socksProxyPort=1080
systemprop.socksProxyVersion=5
http
systemProp.http.proxyHost=www.somehost.org
systemProp.http.proxyPort=8080
https
systemProp.https.proxyHost=www.somehost.org
systemProp.https.proxyPort=8080
相同代理协议下,命令行方式中参数-Dxxx的xxx与gradle.properties中systemProp.xxx的xxx是一致的。所以,了解其中一种方式即可,需要时转为另一种方式也很简单。
在项目根目录下gradle.properties 文件中,添加以上内容即可。
随着Gradle相关插件的升级,上述的代理设置可能,会失效,如果失效的话,建议参考:Android Studio Gradle 设置代理 socks5进行设置。
Android Studio中项目的文件目录结构图:
从上图中我们可以看到,与 Gradle 有关的文件基本上分为七种:
也许有人会说根目录下还有一个config.gradle文件呢,其实这是我自定义的 gradle文件,自定义Gradle文件会在下面中讲解,这里先搁置一下。好了,那么我们一个一个地来看看他们的作用吧。
apply plugin: 'com.android.application'
android {
compileSdkVersion 23 //编译时候用的sdk的版本
buildToolsVersion "23.0.2" // build工具版本
defaultConfig {
applicationId "com.yuqirong.koku" // 应用包名
minSdkVersion 15 // 最低适用sdk版本
targetSdkVersion 23 // 目标sdk版本
versionCode 1 // 版本号
versionName "1.0" // 版本名称
}
buildTypes {
release {
minifyEnabled true // 开启混淆
zipAlignEnabled true // 对齐zip
shrinkResources false // 删除无用资源
debuggable false // 是否debug
versionNameSuffix "_release" // 版本命名后缀
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' // 混淆文件
}
debug {
zipAlignEnabled false
shrinkResources false
minifyEnabled false
versionNameSuffix "_debug"
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:design:23.2.1'
}
第一句apply plugin:'com.android.application'主要用来申明这是一个Android程序。而dependencies用于引入依赖,这个相信大家都比较了解了。其他的配置比较简单都有注释,就不展开讲了。
CompileSdkVersion是告诉gradle用哪个SDK版本来编译,和运行时要求的版本号没有关系;使用任何新添加的API就需要使用对应Level的Android SDK。
buildToolsVersion是Android构建工具的版本,其中包括了打包工具aapt、dx等等。这个工具的目录位于..your_sdk_path/build-tools/XX.XX.XX,buildToolsVersion的版本需要>=CompileSdkVersion;高版本的build-tools可以构建低版本的android程序。例如:
compileSdkVersion 18
buildToolsVersion "22.0.1"
minSdkVersion最低适用sdk版本,如果compileSdkVersion设置为可用的最新API,那么minSdkVersion则是应用可以运行的最低要求。minSdkVersion是Google Play商店用来判断用户设备是否可以安装某个应用的标志之一。
targetSdkVersion目标sdk版本,targetSdkVersion是Android系统提供前向兼容的主要手段。这是什么意思呢?随着Android系统的升级,某个系统的API或者模块的行为可能会发生改变,但是为了保证老APK的行为还是和以前兼容。只要APK的targetSdkVersion不变,即使这个APK安装在新Android系统上,其行为还是保持老的系统上的行为,这样就保证了系统对老应用的前向兼容性。关于相关的例子和原理,建议阅读:Android targetSdkVersion 原理。
minSdkVersion和targetSdkVersion与compileSdkVersion的另一个不同之处是它们会被包含进最终的APK文件中,如果你查看生成的AndroidManifest.xml 文件,你会看到类似下面这样的标签:
<uses-sdk android:targetSdkVersion="23" android:minSdkVersion="7" />
如果你在manifest文件中手工设置,你会发现Gradle在构建时会忽略它们(尽管其它构建系统可能会明确依赖它们)。
如何选择 compileSdkVersion, minSdkVersion 和 targetSdkVersion
当然除了上面的配置之外,还有很多配置也常常写入到app/build.gradle 中。我们慢慢往下看。
signingConfigs {
release { // 正式版本的签名
storeFile file("../koku.jks") // 密钥文件位置
storePassword "xxxxxxxxx" // 密钥密码
keyAlias "koku" // 密钥别名
keyPassword "xxxxxxxxx" // 别名密码
}
debug { // debug版本的签名
// no keystore
}
}
使用时只要在buildTypes的release中加一句signingConfig signingConfigs.release就好了。
如果你觉得把密钥密码和别名密码放在 app/build.gradle 里不安全,那么可以把相关密码放到不加入版本控制系统的 gradle.properties 文件:
KEYSTORE_PASSWORD=xxxxxxxxxx
KEY_PASSWORD=xxxxxxxxx
对应的 signingConfigs 配置:
signingConfigs {
release {
try {
storeFile file("../koku.jks")
storePassword KEYSTORE_PASSWORD
keyAlias "koku"
keyPassword KEY_PASSWORD
}
catch (ex) {
throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
}
}
}
compileOptions { // java 版本
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
这里需要注意下,如果Java编译版本为1.8的话,另外在defaultConfig 里要配置Jack编译器:
jackOptions {
enabled true
}
lintOptions {
abortOnError false // 是否忽略lint报错
}
productFlavors {
xiaomi {}
googleplay {}
wandoujia {}
}
整个app/build.gradle文件配置如下所示:
apply plugin: 'com.android.application'
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
applicationId "com.yuqirong.koku" // 应用包名
minSdkVersion 15 // 最低适用sdk版本
targetSdkVersion 23 // 目标sdk版本
versionCode 1 // 版本号
versionName "1.0" // 版本名称
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// 默认是umeng的渠道
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "umeng"]
jackOptions {
enabled true
}
}
java 版本
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
signingConfigs {
release {
storeFile file("../koku.jks")
storePassword "xxxxxx"
keyAlias "koku"
keyPassword "xxxxxx"
}
debug {
// no keystore
}
}
buildTypes {
release {
// 开启混淆
minifyEnabled true
// 对齐zip
zipAlignEnabled true
// 删除无用资源
shrinkResources false
// 是否debug
debuggable false
// 命名后缀
versionNameSuffix "_release"
// 签名
signingConfig signingConfigs.release
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
// 输出apk名称为koku_v1.0_2015-01-15_wandoujia.apk
def fileName = "koku_v${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
debug {
zipAlignEnabled false
shrinkResources false
minifyEnabled false
versionNameSuffix "_debug"
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
abortOnError false
}
productFlavors {
xiaomi {}
googleplay {}
wandoujia {}
}
//针对很多渠道
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.android.support:design:23.2.1'
}
def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
再多嘴一句,有了以上的build.gradle配置之后,如果想使用Gradle多渠道打包,需要在AndroidManifest.xml中申明:
<meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" />
最后使用命令 gradlew assembleRelease 打包即可。
gradle文件夹中主要是gradle-wrapper.properties文件比较重要,主要用来声明Gradle目录以及Gradle下载路径等:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
里面参数的具体的意义,前面已经讲解过了,这里就不再复述了。
根目录下的 build.gradle主要作用就是定义项目中公共属性,比如有依赖的总仓库、Gradle插件的版本等:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
mavenCentral()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
这个文件是全局的项目配置文件,里面主要声明一些需要加入gradle的module,一些module被主module依赖后,会在这里进行声明。
include ':app',':brave'
通过上述的setting.gradle,我们可以知道整个项目中包含了app和brave两个module。
配置gradle运行环境的文件,比如配置gradle运行模式,运行时jvm虚拟机的大小,设置gradle的代理等。
local.properties文件在Android Studio中是用来配置SDK目录的,也可以在文件中配置一些本地化的变量。这个文件不会被提交到版本控制中。
为了安全起见签名文件不可以放在项目中,那么可能每个开发人员的存放地方不同,这种情况下就可以使用local.properties来配置路径然后在app目录下的build.gradle中引用。
## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Mon Nov 06 14:20:07 CST 2017
sdk.dir=/Users/baiduo/Library/Android/sdk
#配置keystore文件路径
RELEASE_STORE_FILE=/Users/baiduo/Desktop/Lottery
在build.gradle中引用:
signingConfigs {
autoSigning {
#加载properties
def properties = new Properties()
def inputStream = project.rootProject.file('local.properties').newDataInputStream()
properties.load(inputStream)
keyAlias 'IKicker'
keyPassword '*******'
storeFile file(properties.getProperty('RELEASE_STORE_FILE'))
storePassword '*******'
}
}
其实Gradlew只是一个Gradle的封装,是给Unix用户用的。这个脚本的最前面的注释也说明了这个功能:
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
同样的,gradlew.bat也是一个Gradle的封装,是给Windows用户用的。
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
这两个文件的作用就是,任何机器都可以执行gradle构建任务,即使没有装gradle,例如:
./gradlew assemble
如果运行时,发现系统没有对应版本的gradle,会通过gradle-wrapper.jar下载gradle-wrapper.properties中指定的gradle版本。这样的话,任何人获取代码后,不用安装gradle,就可以构建工程。
gradle-wrapper.properties文件中指定的版本,就是运行gradle wrapper命令时的gradle版本。
当然,也可以手动指定别的版本,在根目录下build.gradle文件中添加:
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
再运行gradle wrapper。
这两个文件最重要的运用就是:
1. 在公司内统一gradle版本
2. 把gradle-wrapper.properties里面的下载gradle的链接切换到公司的公共空间上,那么下载和安装gradle的时间就可以忽略不计了。
在上面我们留了一个悬念,就是如何添加我们自定义的Gradle文件。接下来我们就动手来实践一下。在项目根目录下创建文件config.gradle。然后在根目录下的build.gradle开头添加一句apply from: "config.gradle":
apply from: "config.gradle"
buildscript {
repositories {
jcenter()
}
...
}
...
这句话就代表着把config.gradle添加进来了。然后我们可以在config.gradle中申明一些配置:
ext {
android = [
compileSdkVersion: 23,
buildToolsVersion: "23.0.3",
applicationId : "com.yuqirong.koku",
minSdkVersion : 14,
targetSdkVersion : 23,
versionCode : 3,
versionName : "1.4"
]
dependencies = [
"appcompat-v7":'com.android.support:appcompat-v7:23.0.1',
"recyclerview-v7":'com.android.support:recyclerview-v7:24.2.1',
"design":'com.android.support:design:23.0.1'
]
}
最后在app/build.gradle中去使用:
android {
compileSdkVersion rootProject.ext.android.compileSdkVersion
buildToolsVersion rootProject.ext.android.buildToolsVersion
defaultConfig {
applicationId rootProject.ext.android.applicationId
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
jackOptions {
enabled true
}
}
...
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile rootProject.ext.dependencies["appcompat-v7"]
compile rootProject.ext.dependencies["recyclerview-v7"]
compile rootProject.ext.dependencies["design"]
}
从上面可以看到,我们把一些固定的配置“拎”出来放到config.gradle 中,这样以后直接更改config.gradle就行了,方便多人协作开发。
可以通过View->Tool windows->Gradle打开,也可以从右侧纵向标签页点击打开。
参考链接
Android Gradle和Gradle插件区别
Gradle构建工具与Android对应关系
AndroidStudio gradle配置
Mac下AndroidStudio中手动配置Gradle
IDEA及Gradle使用总结
Gradle中文教程系列-跟我学Gradle-14.1:IDEA中Gradle插件的使用
给ANDROID 初学者的GRADLE知识普及
ANDROID 开发你需要了解的GRADLE配置
关于Android Studio里的Gradle,你所需要知道的都在这里了
AndroidStudio gradle安装配置详解-透过现象看本质
Android local.properties配置文件的使用
使用Gradle构建Android程序(再仔细看看)
请问android studio创建的工程目录下的gradlew文件有什么作用?gradlew 和 gradle 有什么区别?
Gradle 完整指南(Android) //待读
Android Studio中Gradle使用详解 //待读
Android studio Gradle的介绍和部分问题小结//待读
Android Studio中Gradle使用详解//待读
Android中Gradle详细实用指南//待读
Android Studio Gradle使用笔记//待读
Gradle Android插件用户指南翻译
Android Plugin DSL Reference
深入理解Android(一):Gradle详解
Groovy Tip 12 Range的用法
Groovy基础——Closure(闭包)详解
Gradle User Guide
AndroidStudio配置构建
Android Plugin DSL Reference
Gradle-中文用户组一款简洁而优雅的构建工具
Gradle全局变量设置、自定义BuildConfig
Gradle配置全局变量
利用 Android Studio 和 Gradle 打包多版本APK( applicationIdSuffix)
application android:debuggable="false" 有什么用?
android lint选项含义
Gradle lint 配置
解决AndroidStudio导入项目在 Building gradle project info 一直卡住
加速Android Studio/Gradle构建
加快gradle的编译速度总结-亲身经历
解决传说中的 Android 65k 问题
Android Studio 错误 Duplicate files copied in APK META-INF/LICENSE.txt
Duplicate files copied in APK META-INF/license.txt
NDK SO 库开发与使用中的 ABI 构架选择
studio android.useDeprecatedNdk=true解决ndk提示版本低不能自动编译jni