零、一些概念:
1.Gradle是什么?
解释一:Gradle其实就是一个构建项目的工具,即把一堆堆的目录、文件按照一定的规则关联起来,形成一个项目的自动化构建工具。
解释二:Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具
。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,抛弃了基于XML的各种繁琐配置。
gradle版本,如gradle-5.4.1-all.zip
位置:项目主目录: gradle 文件夹->wrapper->gradle-wrapper.properties
#Mon Feb 17 09:51:13 GMT+08:00 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
2、Gradle插件又是什么?
解释:其实应该是AndroidStudio Gradle Plugin,也就是AndroidStudio用于开发Android项目的gradle插件
。
Gradle插件是针对Gradle发行版和Android SDK Build Tools封装的一个工具,主要有两大功能:
- 调用Gradle本身的代码和批处理工具来构建项目
- 调用Android SDK的编译、打包功能
位置:项目下的 build.gradle 中
buildscript {
ext.kotlin_version = '1.3.50'
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
3.Android SDK Build Tools Version:Android SDK 构建工具版本
位置:在模块下的build.gradle->android{...}中
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
}
4.依赖关系
明确概念:
-
Gradle Plugin Version: Gradle 插件版本
-
Gradle Version: Gradle发行版本
-
Android SDK Build Tools Version:Android SDK 构建工具版本
三者依赖关系
- Gradle Plugin 有不同的版本号。 即我们常见的:classpath 'com.android.tools.build:gradle:3.0.1'】,
每个插件版本号又对应一个或一些 Gradle 发行版本【即我们常见的:gradle-4.1-all.zip】如果这两个版本对应不上了,那么构建项目的时候就会报错。 - Gradle Plugin 还和 Android SDK BuildTool 有关联,因为它还负责和编译相关的功能,这也是为何我们要在 build.gradle 里注明 buildToolsVersion 的原因。这也是我们要在项目的 local.properties 文件里写明Android SDK路径、在build.gradle 里注明 buildToolsVersion 的原因。Android Gradle Plugin 本质上就是 一个AS的插件,它一边调用 Gradle本身的代码和批处理工具来构建项目,一边调用Android SDK的编译、打包功能,从而让我们能够顺畅地在AS上进行开发。
更多详情以及Android Gradle 插件版本所需的 Gradle 版本对应关系看官方文档:
下表列出了各个 Android Gradle 插件版本所需的 Gradle 版本。为了获得最佳性能,应使用 Gradle 和插件这两者的最新版本。
插件版本 | 所需的 Gradle 版本 |
---|---|
1.0.0 - 1.1.3 | 2.2.1 - 2.3 |
1.2.0 - 1.3.1 | 2.2.1 - 2.9 |
1.5.0 | 2.2.1 - 2.13 |
2.0.0 - 2.1.2 | 2.10 - 2.13 |
2.1.3 - 2.2.3 | 2.14.1+ |
2.3.0+ | 3.3+ |
3.0.0+ | 4.1+ |
3.1.0+ | 4.4+ |
3.2.0 - 3.2.1 | 4.6+ |
3.3.0 - 3.3.3 | 4.10.1+ |
3.4.0 - 3.4.3 | 5.1.1+ |
3.5.0 - 3.5.4 | 5.4.1+ |
3.6.0 - 3.6.4 | 5.6.4+ |
4.0.0+ | 6.1.1+ |
4.1.0+ | 6.5+ |
一、已经约定好的一些关键字配置:
1.
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin:用来指定应用的是哪个插件/脚本。.
- com.android.application:Android APP
- com.android.library:仅Android模块引用的,需要设置成这个。
2.
android {...}
用来指定Android打包插件的相关属性。
3.
compileSdkVersion 28
//或者将 数字 配置到别的地方然后进行调用,详情看另一篇博文
compileSdkVersion var.compileSdkVersion
compileSdkVersion rootProject.ext.android.compileSdkVersion
compileSdkVersion ${System.env.xx}
compileSdkVersion:设置编译时用的Android版本
4.
buildToolsVersion 29.0.3
buildToolsVersion:设置编译时使用的构建工具的版本(默认可以不设置)
5.defaultConfig
defaultConfig:设置一些默认属性,其可用属性是buildTypes和ProductFlavors之和,具体直接看着两个属性内的属性。
6.sourceSets
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
配置相关源文件的位置,当你的项目的目录结构跟默认的有区别但又不想改的时候sourceSets就派上用场了.
- aidl 设置aidi的目录
- assets 设置assets资源目录
- compileConfigurationName The name of the compile configuration for this source set.
- java Java源代码目录
- jni JNI代码目录
- jniLibs 已编译好的JNI库目录
- manifest 指定清单文件
- name The name of this source set.
- packageConfigurationName The name of the runtime configuration for this source set.
- providedConfigurationName The name of the compiled-only configuration for this source set.
- renderscript Renderscript源代码目录
- res 资源目录
- setRoot(path) 根目录
7.signingConfigs:配置签名信息
另外,如何签名请看另一篇博文:AS 项目 签名
- keyAlias 签名的别名
- keyPassword 密码
- storeFile 签名文件的路径
- storePassword 签名密码
- storeType 类型
signingConfigs {
release {
storeFile file(props['KEYSTORE_FILE'])
keyAlias props['KEY_ALIAS']
storePassword props['KEYSTORE_PWD']
keyPassword props['KEY_PWD']
}
debug {
storeFile file("KeyStore/eim-android.keystore")
storePassword "545468222"
keyAlias "eim-android"
keyPassword "545468222"
}
deba{
setSigningProperties()
}
}
def setSigningProperties() {
def currentFlavor = getCurrentFlavor()
def flavorBuildPro = "app/src/${currentFlavor}/buildConfigs/build.properties"
def defaultBuildPro = "app/src/main/buildConfigs/build.properties"
def props = new Properties()
if(project.rootProject.file(flavorBuildPro).exists()) {
props.load(project.rootProject.file(flavorBuildPro).newDataInputStream())
} else {
props.load(project.rootProject.file(defaultBuildPro).newDataInputStream())
}
android.signingConfigs.release.storeFile = file(props['STORE_FILE'])
android.signingConfigs.release.storePassword = props['STORE_PASSWORD']
android.signingConfigs.release.keyAlias = props['KEY_ALIAS']
android.signingConfigs.release.keyPassword = props['KEY_PASSWORD']
}
def getCurrentFlavor() {
Gradle gradle = getGradle()
String tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
Pattern pattern
if( tskReqStr.contains( "assemble" ) )
pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
else
pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
Matcher matcher = pattern.matcher( tskReqStr )
if( matcher.find() ) {
println ("getCurrentFlavor()-> " + matcher.group(1).toLowerCase())
return matcher.group(1).toLowerCase()
}
else
{
println "getCurrentFlavor()-> NO MATCH FOUND"
return ""
}
}
区别各版本。其中:props['KEY_ALIAS']等常量就到对应的build.properties下找,eg:
STORE_PASSWORD=564781561
KEY_ALIAS=eim-android
KEY_PASSWORD=564781561
STORE_FILE=src/main/buildConfigs/eim-android.keystore
8.buildTypes:配置构建类型,可打出不同类型的包,默认有debug,可以自行增加release{..}等。
以下的属性,在defaultConfig 和 ProductFlavors 中基本同样适用
- applicationIdSuffix 修改applicationId,在默认applicationId的基础上加后缀。在buildType中修改applicationId时只能加后缀,不能完全修改
- debuggable 设置是否生成debug版的APK
- jniDebuggable 设置生成的APK是否支持调试本地代码
- minifyEnabled 设置是否执行代码混淆
- multiDexEnabled Whether Multi-Dex is enabled for this variant.
- renderscriptDebuggable 设置生成的APK是否支持调试RenderScript代码
- renderscriptOptimLevel 设置RenderScript优化级别
- signingConfig 设置签名信息
- versionNameSuffix 修改版本名称,在默认版本名称的基础上加后缀。在buildType中修改版本名称时只能加后缀,不能完全修改
- zipAlignEnabled 设置是否对APK包执行ZIP对齐优化,减小zip体积,增加运行效率(类比于ssd的4k对齐)
- proguardFile(proguardFile) 添加一个混淆文件
- proguardFiles(proguardFileArray) 添加多个混淆文件
- setProguardFiles(proguardFileIterable) 设置多个混淆文件
release{
applicationIdSuffix ".beta"
debuggable false
signingConfig signingConfigs.release
multiDexEnabled false
minifyEnabled false
zipAlignEnabled false
shrinkResources false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
再详细说一下multiDexEnabled这个属性:
64K 引用限制问题官方文档 传送门
- 类型:Boolean
- 描述:是否开启分包。因为安卓中方法索引值为两个字节,四位十六进制的一个数值,即[0, 0xffff],所以最大方法数为65536个。一旦超出了,就需要进行分包,所以我们就需要开启这个参数。
- 使用方法:
android{ buildTypes { debug { multiDexEnabled true ... } } } // 添加依赖 dependencies { // 如果使用的为 AndroidX,则使用下面这个导入 // implementation 'androidx.multidex:multidex:2.0.1' // 如果不使用 AndroidX,则使用下面这段 compile 'com.android.support:multidex:1.0.3' }
有两种开启 MultiDex 方法:
// 第一种:让你应用的 Application 继承 MultiDexApplication。
public class MyApplication extends MultiDexApplication {
}
// 第二种:重写应用的 Application 方法 attachBaseContext
public class MyApplication extends Application {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
最后别忘了在 AndroidManifest.xml
中使用我们在上面的 Application。
9.productFlavors:配置不同风格的APP,在buildTypes的基础上还可以让每一个类型的APP拥有不同的风格,所以最终打出的APK的数量就是buildTypes乘以productFlavors。常说的马甲包就是通过这两种方式结合生成的。
以下的属性,在defaultConfig 和 ProductFlavors 中基本同样适用
- applicationId 设置应用ID
- testApplicationId 设置测试时的应用ID
- testFunctionalTest See instrumentation.
- testHandleProfiling See instrumentation.
- testInstrumentationRunner Test instrumentation runner class name.
- versionCode 设置版本号
- versionName 设置版本名称
- minSdkVersion(int minSdkVersion) 设置兼容的最小SDK版本
- minSdkVersion(String minSdkVersion) 设置兼容的最小版本
- targetSdkVersion(int targetSdkVersion) 设置目标SDK版本
- targetSdkVersion(String targetSdkVersion) 设置目标SDK版本
normal {
applicationId "com.example.android.test"
versionCode 282
versionName "3.10.0"
applicationIdSuffix ".beta"
signingConfig signingConfigs.release
buildConfigField "boolean", "IS_BETA", "false"
manifestPlaceholders = [app_icon : "@mipmap/ic_launcher",
app_icon_round: "@mipmap/ic_launcher_round"]
buildConfigField "int", "CHANNELID", "100"
buildConfigField "boolean", "ENABLE_QA", "true"
}
上升涉及到的 buildConfigField 可以查看一下这篇文章 Android使用buildConfigField写入编译时常量
10.testOptions:设置测试相关属性
- reportDir 设置测试报告的目录
- resultsDir 设置测试结果的目录
11.aaptOptions:设置AAPT的属性
- failOnMissingConfigEntry Forces aapt to return an error if it fails to find an entry for a configuration.
- ignoreAssets Pattern describing assets to be ignore.
- noCompress Extensions of files that will not be stored compressed in the APK.
- useNewCruncher Whether to use the new cruncher.
12.intOptions:设置Lint的属性
(挺多的,不罗列,可以直接去看官网)
lintOptions {
disable 'GoogleAppIndexingWarning', 'HardcodedText', 'InvalidPackage'
textReport true
textOutput "stdout"
abortOnError false //设置是否在lint发生错误时终止构建
// if true, only report errors
ignoreWarnings true
}
13.flavorDimensions
这个涉及到的是:Android App编译风味设置。如果不做这个设置的话,可以不搞。
14.dexOptions
- incremental Whether to enable the incremental mode for dx. This has many limitations and may not work. Use carefully.
- javaMaxHeapSize Sets the -JXmx* value when calling dx. Format should follow the 1024M pattern.
- jumboMode Enable jumbo mode in dx (--force-jumbo).
- preDexLibraries Whether to pre-dex libraries. This can improve incremental builds, but clean builds may be slower.
dexOptions {
javaMaxHeapSize "2g"
jumboMode = true
}
15.compileOptions:设置编译的相关属性
- sourceCompatibility Language level of the source code.
- targetCompatibility Version of the generated Java bytecode.
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
16.packagingOptions:设置APK包的相关属性
- excludes The list of excluded paths.
- pickFirsts The list of paths where the first occurrence is packaged in the APK.
- exclude(path) Adds an excluded paths.
- pickFirst(path) Adds a firstPick path. First pick paths do get packaged in the APK, but only the first occurrence gets packaged.
exclude,过滤掉某些文件或者目录不添加到APK中,作用于APK,不能过滤aar和jar中的内容。
比如:
packagingOptions {
exclude 'META-INF/**'
exclude 'lib/arm64-v8a/libmediaplayer.so'
}
pickFirst,匹配到多个相同文件,只提取第一个。只作用于APK,不能过滤aar和jar中的文件。
比如:
packagingOptions {
pickFirst "lib/armeabi-v7a/libaaa.so"
pickFirst "lib/armeabi-v7a/libbbb.so"
}
doNotStrip,可以设置某些动态库不被优化压缩。
比如:
packagingOptions{
doNotStrip "*/armeabi/*.so"
doNotStrip "*/armeabi-v7a/*.so"
}
merge,将匹配的文件都添加到APK中,和pickFirst有些相反,会合并所有文件。
比如:
packagingOptions {
merge '**/LICENSE.txt'
merge '**/NOTICE.txt'
}
17.dependencies:配置依赖
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation fileTree(include: ['*.aar'], dir: 'libs')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.core:core-ktx:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
}
ref:
2.AndroidStudio与Gradle插件和Gradle