1. 基本概念
- 项目级
build.gradle
主要用于配置整个项目的构建设置 - 模块级
build.gradle
配置各个module的构建设置,指定了项目编译版本、打包配置及依赖库等
2. 项目级 build.gradle
2.1 文件内容
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
mavenLocal()
google()
jcenter()
maven {
allowInsecureProtocol = true
url "http://mvnrepo.alibaba-inc.com/mvn/repository"
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
}
}
allprojects {
repositories {
mavenLocal()
google()
jcenter()
maven {
allowInsecureProtocol = true
url "http://mvnrepo.alibaba-inc.com/mvn/repository"
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
buildscript
- gradle脚本执行所需依赖。repositories
- 配置依赖库仓库dependencies
- 依赖插件
allprojects
- 各个module gradle脚本执行所需依赖。repositories
- 配置依赖库仓库
task clean
- 执行clean时,会删除build目录
3. 模块级 build.gradle
3.1 文件内容
apply plugin: 'com.android.application'
android {
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
applicationId 'com.xxx.xxx'
buildConfigField "boolean", "NeedLogger", 'true'
buildConfigField "String", "AUTH_SECRET", '"请填入您的密钥"'
}
sourceSets {
main {
java.srcDirs = ['src/main/java']
jniLibs.srcDirs = ['libs']
res.srcDirs = ['src/main/res']
}
}
signingConfigs {
debug {
keyAlias 'xx'
keyPassword 'xx'
storeFile file('xx/xx.keystore')
storePassword 'xx'
v1SigningEnabled true
v2SigningEnabled true
}
release {
keyAlias 'xx'
keyPassword 'xx'
storeFile file('xx/xx.keystore')
storePassword 'xx'
v1SigningEnabled true
v2SigningEnabled true
}
}
buildTypes {
release {
debuggable false
minifyEnabled true
proguardFile file('proguard-rules.pro')
zipAlignEnabled false
multiDexEnabled true
signingConfig signingConfigs.release
}
debug {
debuggable true
minifyEnabled false
zipAlignEnabled false
multiDexEnabled true
signingConfig signingConfigs.debug
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar','*.aar'])
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
}
apply plugin
- 应用插件android
- 配置项目构建的各种属性dependencies
- 依赖库
3.2 apply plugin
插件
apply plugin: 'com.android.application'
是项目级build.gradle
里面引入的插件classpath 'com.android.tools.build:gradle:3.5.1'
com.android.application
表示该module是一个APP项目,编译产物是apkcom.android.library
表示该module是一个库,编译产物是aar
引入其他插件
//项目级build.gradle
dependencies {
classpath 'com.android.tools.build:gradle:3.5.1'
// 引入kotlin插件依赖
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.20'
}
//模块级build.gradle
apply plugin: 'com.android.application'
// 引入kotlin插件
apply plugin:'kotlin-android'
3.3 android
项目配置
compileSdkVersion 30
- 编译版本,配置当前项目使用API 30的android.jar参与编译,可以在项目目录-External Libraries-<Android API 30> 找到 android.jarbuildToolsVersion '30.0.3'
defaultConfig
- 项目信息默认配置,优先级最低minSdkVersion 21
- 最低支持的版本设备targetSdkVersion 30
- 目标适配的版本,比如设置成23以下,就不需要动态申请权限versionCode 1
- 版本号,用于对比两个APP的版本大小,判断是否可以覆盖安装versionName "1.0"
- 显示版本号,作为展示使用applicationId 'com.xxx.xxx'
- 包名buildConfigField "boolean", "NeedLogger", 'true'
- 在BuildConfig.class内生成一个boolean NeedLogger = true的变量buildConfigField "String", "AUTH_SECRET", '"请填入您的密钥"'
- 在BuildConfig.java内生成一个String Auth_SECRET = "请填入您的密钥",注意要加引号,否则编译错误
sourceSets
- 指定代码,配置等的目录,可以配置不同的渠道的配置目录signingConfigs
- 配置签名相关dependencies
- 依赖库配置
3.3.1 多渠道打包
android {
// ...
// 定义构建变体的维度,例如这里定义了"market" 和 "tier" 两个维度
flavorDimensions "market", "tier"
// 根据 flavorDimensions 定义不同的产品风味,如 free 和 pro
productFlavors {
xiaomi {
dimension "market"
}
huawei {
dimension "market"
}
free {
dimension "tier"
applicationIdSuffix ".free"
versionNameSuffix "-free"
}
pro {
dimension "tier"
applicationIdSuffix ".pro"
versionNameSuffix "-pro"
}
}
}
此时会构建market(2) * tier(2) * buildTypes(2) = 8个渠道的包
看下编译生成的BuildConfig.java,可以通过匹配渠道做不同的操作,比如初始化不一样的推送(小米或华为),显示收费或者免费等等
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.xx";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "huaweiFree";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0-free";
public static final String FLAVOR_market = "huawei";
public static final String FLAVOR_tier = "free";
// Fields from default config.
public static final String AUTH_SECRET = "请填入您的密钥";
public static final boolean NeedLogger = true;
}
3.3.2 动态配置
- 动态配置BuildConfig代码
buildTypes {
release {
// ...
buildConfigField "boolean", "NeedLogger", 'false'
}
debug {
// ...
buildConfigField "boolean", "NeedLogger", 'true'
}
}
// code,测试包自动打开日志,正式包关闭日志输出
if (BuildConfig.NeedLogger) {
Log.i(TAG, "xxxx");
}
- 动态配置AndroidManifest.xml
// AndroidManifest.xml
<data android:scheme:"${xx_scheme}"/>
// build.gradle
buildTypes {
release {
// ...
manifestPlaceholders = [xx_scheme: "release_scheme"]
}
debug {
// ...
manifestPlaceholders = [xx_scheme: "debug_scheme"]
}
}
- 动态配置资源
渠道和buildType可以分别配置不同的资源,例如huaweiFreeDebug
按照默认约定,可以创建如下目录
// debug/strings.xml
<string name="test_value">debug</string>
// free/strings.xml
<string name="test_value">free</string>
// huawei/strings.xml
<string name="test_value">huawei</string>
// main/strings.xml
<string name="test_value">main</string>
huaweiFreeDebug
内部资源优先级debug
>huawei
>free
>main
一般正式url可以配置在main/strings.xml
,测试url可以配置在debug/strings.xml
,这样在打包的时候就可以自动选择不同环境url,不需要手动去修改代码或配置切换。
另外,也可以手动配置资源路径,例如在项目根目录创建common/main,sourceSets可以配置此目录
sourceSets {
main {
// ...
res.srcDirs += ["${rootProject.projectDir}/common/main/java"]
res.srcDirs += ["${rootProject.projectDir}/common/main/res"]
}
huawei {
}
xiaomi {
}
}
3.4 dependencies
项目依赖
指定当前项目依赖的第三方库,常用的方式有四种
implementation
- 该依赖方式的三方库,项目可以直接调用三方库里面的代码或其他资源。并且可以依赖传递,会将该三方库依赖的其他的库一起引入,默认使用版本最高的那个。api
- 当前module如果是library,该依赖方式引入的三方库,会将三方库的代码、配置等一起打入当前module中。如果当前module是application,和implementation无区别compileOnly
- 只在编译期使用,最终产物不会包含该依赖库的代码,一般搭配编译插件使用runtimeOnly
- 只在运行时使用,编码期间无法使用该依赖库内的代码或者其他资源,最终产物会包含该依赖库的所有代码和资源。
// 常用依赖
implementation 'androidx.appcompat:appcompat:1.2.0'
// 统一定义版本号
appcompatVersion = '1.2.0'
implementation "androidx.appcompat:appcompat:$appcompatVersion"
// 依赖module
implementation project(path: ':moduleA')
结合多渠道打包的变体
可以根据Debug或Release包引入不同依赖。比如工具库LeakCanary,用于检测内存泄漏,仅希望在测试包中使用,在正式包中剔除该功能。可以使用如下方式依赖
debugImplementation "com.xxx.xxx:LeakCanary:1.0.0"
releaseImplementation "com.xxx.xxx:LeakCanary-no-op:1.0.0"
还可以根据不同渠道引入不同依赖sdk。比如小米渠道引入小米推送sdk,华为推送引入华为sdk
xiaomiImplementation 'xiaomipushsdk'
huaweiImplementation 'huaweipushsdk'
AndroidStudio提示了很多种,可以自行选择
剔除冲突的依赖
有一种场景,maven依赖和aar依赖同时包含了同一个库,编译时就会冲突,处理方式有两种
- 通过exclude方式排除掉,优点是简单,缺点是每个冲突的依赖库都得加
implementation('com.xxx.xxx:xxx:1.0.0') {
exclude group:'com.xxx', module:'xx'
}
- 让aar提供方去掉冲突的库