完整配置的Guthub地址:https://github.com/WangFion/mvp-mode
一、什么是 Gradle
关于 Gradle 是什么,这里我就不做过多的赘述了,打开度娘一搜一大片,感兴趣的童鞋可以自行学习哈!这里我就简单描述一下:
Gradle 是一个基于 Apache Ant 和 Apache Maven 概念的项目自动化构建工具。它使用一种基于 Groovy 的特定领域语言来声明项目设置,而不是传统的 XML。Gradle 就是工程的管理,帮我们做了依赖、打包、部署、发布、各种渠道的差异管理等工作。
这里你只需要己住一点:Gradle 是一个自动化构建工具,这就ok了。
二、AS 中的 Gradle 版本
在 Android Studio 中使用 Gradle 有三个版本需要注意:AS 版本、Gradle 插件版本、Gradle 版本。
1、AS版本
2、Gradle 插件版本(项目根目录的 build.gradle)
classpath 'com.android.tools.build:gradle:3.6.3'
3、Gradle 版本(项目根目录的 /gradle/wrapper/gradle-wrapper.properties)
#Sat May 09 20:18:45 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
1、其中 AS 的版本和 Gradle 插件的版本是有对应关系的,Gradle 版本根据项目而定,建议都保持最新版本。
2、有新版本,如果更新之后编译不过并且很难解决,亦可保持原编译通过版本不变。
3、个人建议有新版本就及时更新,不要累积很多版本后一次更新;否则到必须更新的时候再去更新,相信我你会痛苦万分的。
三、Project 的 Gradle 通用配置
Project 的 Gradle 配置的是项目统一化、公用化的一些信息,目的是为了保证公共的信息在每个 Module 中都是一致的,而每个 Module 只需要去配置自己的一些差异化的信息。
Project 的 Gradle 的配置文件是根目录下面的 build.gradle,这里面主要配置远程仓库、插件、项目版本信息、公共 lib 等。
1、远程仓库配置
repositories {
// wf-update: 2020/5/9 16:57 添加aliyun镜像,优化jcenter和google访问
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://maven.aliyun.com/repository/jcenter' }
maven { url 'https://maven.aliyun.com/repository/google' }
google()
jcenter()
}
往往在我们项目开发的过程中都会集成很多 Google 和第三方的开源库,而受国内环境的影响使用 google() 和 jcenter() 下载这些库往往不尽人意,所以这里推荐配置国内的镜像地址(当然不止我上面列举的这些),会有意想不到的效果哦。注意这里需要同时配置 buildscript 和 allprojects 方法块。
2、插件配置
dependencies {
classpath 'com.android.tools.build:gradle:3.6.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
}
注意这里的 dependencies 配置的是项目编译所用到的插件,一定要区别于 Module 里面的 dependencies ,注意阅读 NOTE 的英文说明。上例中我们配置了一个 Gradle 插件和 Kotlin 插件。
3、项目版本信息
/**
* 应用版本相关配置信息
*/
ext {
applicationId = "com.wf.mvp.mode"
apkName = "MvpMode"
versionCode = 1
versionName = "v1.0"
compileSdkVersion = 29
buildToolsVersion = "29.0.2"
minSdkVersion = 19
targetSdkVersion = 29
}
这里配置的是我们项目的包名、版本号、sdk 版本、编译版本等信息,当然了这里我们只是定义,具体的使用是在每个 Module 里面通过 rootProject.applicationId 的形式来调用,项目的每个 Module 都通过这种形式来配置版本信息后,后续版本调整我们就只需要修改这里就 ok 了。
4、公共 lib 配置
/**
* Module通用lib
*/
ext {
lib_kotlin = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
lib_appcompat = 'androidx.appcompat:appcompat:1.1.0'
lib_core_ktx = 'androidx.core:core-ktx:1.2.0'
lib_constraintlayout = 'androidx.constraintlayout:constraintlayout:1.1.3'
lib_junit = 'junit:junit:4.13'
lib_ext_junit = 'androidx.test.ext:junit:1.1.1'
lib_espresso_core = 'androidx.test.espresso:espresso-core:3.2.0'
}
同上面的版本信息一样,公用的 lib 库我们也可以定义在这里,子 Module 亦是通过 rootProject.lib_appcompat 的形式来调用,当然了和上面的版本信息写在一个 ext 方法块里面也可以,为了区分我们这里是分开写的。
四、Module 的 Gradle 通用配置
这里 Module 的 Gradle 主要是用来配置各个 Module 的差异化信息,公共的信息均调用 Project 的 Gradle 里面定义好的。
Module 的 Gradle 的配置文件是相应的 Module 目录下面的 build.gradle,这里面主要配置插件引用、版本信息、签名信息、编译信息、渠道信息、APK格式化输出、第三方框架及 lib 引用 等。
1、插件引用
// path -> app/build.gradle
apply plugin: 'com.android.application'
// apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
第一行配置此 Module 为 Application 还是 Library,为 Application 时可以单独运行。这里在组件化开发中尤为重要,可以通过参数来配置此 Module 为 Application 还是 Library。
后面两行为配置的 Kotlin 支持插件,当然了这里还可以配置一些其他需要用到的插件。
2、版本信息
// path -> app/build.gradle
// --------------- wf-update: 2020/5/9 17:53 版本配置信息 ---------------
compileSdkVersion rootProject.compileSdkVersion
buildToolsVersion rootProject.buildToolsVersion
defaultConfig {
applicationId rootProject.applicationId
minSdkVersion rootProject.minSdkVersion
targetSdkVersion rootProject.targetSdkVersion
versionCode rootProject.versionCode
versionName rootProject.versionName
buildConfigField("String", "DEFAULT_CONFIG", "\"default\"")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
这里配置的是应用版本相关的信息,此信息均定义在 Project 的 Gradle 里面,故这里均引用的 Project 的 Gradle 里面定义的信息。所有的 Module 版本信息都应参照这里配置来保证整个工程的版本一致。
buildConfigField 定义的字段可以在代码中通过 BuildConfig.DEFAULT_CONFIG 的形式来调用,这在后面讲到的版本和渠道里面会非常有用。注意这里定义的字符串需要加上双引号。
3、签名信息
// path -> app/build.gradle
// --------------- wf-update: 2020/5/9 17:55 签名配置信息 ---------------
signingConfigs {
debug {
}
release {
keyAlias 'mvp'
keyPassword 'mvp123'
storeFile file('../sign/mvp.jks')
storePassword 'mvp123'
}
}
签名信息配置没什么特别的,签名文件可以使用 AS 或者其他签名文件生成工具均可。具体的步骤这里不再赘述,可以自行百度。
4、编译信息
// path -> app/build.gradle
// --------------- wf-update: 2020/5/20 19:04 版本编译信息 ---------------
buildTypes {
debug {
buildConfigField("String", "BUILD_TYPES", "\"build_debug\"")
}
release {
buildConfigField("String", "BUILD_TYPES", "\"build_release\"")
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
}
编译信息配置用来配置我们编译的版本是 debug 还是 release,不同的版本我们可以配置不同的信息以及变量等。这里我们在 release 版本中配置了上面定义的签名信息,而 dubug 没有。当我们使用 assemble 命令编译时会在 app/build/outputs/apk 目录下同时输出 debug 和 release 版本的apk,而单独使用 assembleDebug 或者 assembleRelease 只会输出对应的一个版本的apk。
5、渠道信息
// path -> app/src/main/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wf.mvp.mode"
android:sharedUserId="${SHARED_USER_ID}">
<application ......>
......
<meta-data
android:name="CHANNEL_INFO"
android:value="${CHANNEL_VALUE}" />
</application>
</manifest>
// path -> app/build.gradle
// --------------- wf-update: 2020/5/19 20:36 渠道配置信息 ---------------
flavorDimensions "company", "channel"
productFlavors {
huawei {
dimension "company"
buildConfigField("String", "FLAVOR_COMPANY", "\"huawei\"")
manifestPlaceholders = [
SHARED_USER_ID: "android.uid.huawei",
CHANNEL_VALUE : "huawei"
]
}
xiaomi {
dimension "company"
buildConfigField("String", "FLAVOR_COMPANY", "\"xiaomi\"")
manifestPlaceholders = [
SHARED_USER_ID: "android.uid.xiaomi",
CHANNEL_VALUE : "xiaomi"
]
}
phone {
dimension "channel"
buildConfigField("String", "FLAVOR_COMPANY", "\"phone\"")
buildConfigField("String", "FLAVOR_CHANNEL", "\"phone\"")
manifestPlaceholders = [
SHARED_USER_ID: "android.uid.phone",
CHANNEL_VALUE : "phone"
]
}
tv {
dimension "channel"
buildConfigField("String", "FLAVOR_COMPANY", "\"tv\"")
buildConfigField("String", "FLAVOR_CHANNEL", "\"tv\"")
manifestPlaceholders = [
SHARED_USER_ID: "android.uid.tv",
CHANNEL_VALUE : "tv"
]
}
}
渠道配置是针对不同的渠道而进行的差异化配置。这里有以下几点需要说明:
- 多渠道维度(flavorDimensions): AS 3.0之后出现的,至少需要定义一个维度。举个栗子:A 厂商生产了 C、D 两个产品,B 厂商也生产了 C、D 两个产品,这里就需要用到二维渠道了,就会有 AC、AD、BC、BD 四个产品。
- 渠道维度顺序:渠道维度的定义是有先后顺序的,如果渠道里面有相同的配置信息,先定义的维度会覆盖后定义的维度,如上例中的 FLAVOR_COMPANY、SHARED_USER_ID 和 CHANNEL_VALUE 的值始终都会是 company 维度下的 huawei 或者 xiaomi,不可能为 channel 维度下的 phone 或者 tv。可以去 app/build/generated/source/buildConfig 下的 BuildConfig.java 文件中验证。
6、APK格式化输出
// path -> app/build.gradle
// --------------- wf-update: 2020/5/9 17:58 APK格式化输出配置 ---------------
applicationVariants.all { variant ->
variant.outputs.all {
def fileName
def formattedDate = new Date().format("yyyy-MM-dd-HHmmss")
if (variant.buildType.name == 'release') {
fileName = "${rootProject.apkName}_${variant.mergedFlavor.versionName}_${formattedDate}_release.apk"
} else {
fileName = "${rootProject.apkName}_${variant.mergedFlavor.versionName}_${formattedDate}_debug.apk"
}
outputFileName = fileName
}
}
这里也没有什么好讲的,自行根据项目来定义 apk 的输出名称,默认的输出路径是 app/build/outputs/apk,也可以修改此输出路径,但是修改输出路径后,当我们在使用 AS run 来调试应用的时候可能会报找不到 xxx.apk 的错误,所以建议不要修改。
7、第三方框架及 lib 引用
// path -> app/build.gradle
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation rootProject.lib_kotlin
implementation rootProject.lib_appcompat
implementation rootProject.lib_core_ktx
implementation rootProject.lib_constraintlayout
testImplementation rootProject.lib_junit
androidTestImplementation rootProject.lib_ext_junit
androidTestImplementation rootProject.lib_espresso_core
//引用其他 Module
implementation project(path: ':mvp-kotlin')
implementation project(path: ':mvp-java')
//内存泄漏
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
}
这里主要用来引用需要的外部库文件和 Library Module,通用的库我们还是通过 rootProject.lib_appcompat 的形式来引用我们在 Project 里面定义好的,保证通用库版本统一。注意区别这里的 dependencies 和我们上面讲到的 Project 的 build.gradle 里面的 dependencies。
总结
到这里,我们基础的、也是大多数项目必须的通用配置就讲完了,任何一个新项目把这套配置拿过去基本上都能满足需求。当然了 Gradle 用法远不止这些,像是源文件路径配置、ndk 配置、编译检测等等,感兴趣的童鞋可以自己去研究。以上就是本篇文章的全部内容,如有错误的地方或者更好的建议欢迎在下方留言讨论,谢谢!
完整配置的Guthub地址:https://github.com/WangFion/mvp-mode