Android Studio Gradle进阶配置

设置 Java 版本

在根目录下的build.gradle文件下添加 ext{ …. } 中的内容:

ext{
kotlin_version = ‘1.1.51’
rxandroid = ‘2.0.1’
anko_version = ‘0.8.2’
support_version = ‘26.1.0’
target_sdk_version = 26
compile_sdk_version = 26
min_sdk_version = 15
}

使用规则,字符串需使用“$rootProject.”,整形直接用rootProject.。ext可加可不加

android {
compileSdkVersion rootProject.compile_sdk_version
defaultConfig {
applicationId “com.xxx.xxxx”
minSdkVersion rootProject.ext.min_sdk_version
targetSdkVersion rootProject.ext.target_sdk_version
versionCode 1
versionName “1.0”
testInstrumentationRunner “android.support.test.runner.AndroidJUnitRunner”
}
}
dependencies {
implementation fileTree(dir: ‘libs’, include: [‘*.jar’])
implementation”org.jetbrains.kotlin:kotlin-stdlib-jre7:$rootProject.ext.kotlin_version”
implementation “com.android.support:appcompat-v7:$rootProject.support_version”
implementation “io.reactivex.rxjava2:rxandroid:$rootProject.rxandroid”
compile “org.jetbrains.anko:anko-common:$rootProject.anko_version”
compile “com.android.support:recyclerview-v7:$rootProject.support_version”
}

参考:https://www.jianshu.com/p/abb5bbb99142

全局设定编码

allprojects {
repositories {
jcenter()
}
tasks.withType(JavaCompile) {
options.encoding = “UTF-8”
}
}

定义全局变量

先在 project 根目录下的 build.gradle 定义全局变量:

ext {
minSdkVersion = 16
targetSdkVersion = 24
}

然后在各 module 的 build.gradle 中可以通过rootProject.ext来引用:

android {
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}

定义局部变量

有时候一个库会被引用多次,或者一个库有多个依赖,但这些依赖的版本都是统一的。我们通过ext来定义一些变量,这样在用到的时候就可以统一使用了。

ext {
leakcanaryVersion = ‘1.3.1’
scalpelVersion = “1.1.2” // other param
}

debugCompile “com.squareup.leakcanary:leakcanary-android:$leakcanaryVersion”
releaseCompile “com.squareup.leakcanary:leakcanary-android-no-op:$leakcanaryVersion”

exlude关键字

我们经常会遇到库冲突的问题,这个在多个部门协作的大公司会更常见到。将冲突的库通过exclude来做剔除是一个好方法。
1.剔除整个组织的库

compile (‘com.facebook.fresco:animated-webp:0.13.0’) {
exclude group: ‘com.android.support’ // 仅仅写组织名称
}

2.剔除某个库

compile(‘com.android.support:appcompat-v7:23.2.0’) {
exclude group: ‘com.android.support’, module: ‘support-annotations’ // 写全称
exclude group: ‘com.android.support’, module: ‘support-compat’
exclude group: ‘com.android.support’, module: ‘support-v4’
exclude group: ‘com.android.support’, module: ‘support-vector-drawable’
}

引用本地aar

1.把aar文件放在某目录内,比如就放在某个 module 的 libs 目录内
2.在这个 module 的 build.gradle 文件中添加:

repositories {
flatDir {
dirs ‘libs’ //this way we can find the .aar file in libs folder
}
}

3.之后在其他项目中添加下面的代码后就引用了该 aar

dependencies {
compile(name:’aar的名字(不用加后缀)’, ext:’aar’)
}

如果你希望把 aar 放在项目的根目录中,也可以参考上面的配置方案。在根目录的build.gradle中写上:

allprojects {
repositories {
jcenter()
flatDir {
dirs ‘libs’
}
}
}

依赖项目中的 module 和 jar

依赖项目中的 module 和 jar

dependencies {
compile project(‘:mylibraryModule’)
compile files(‘libs/sdk-1.1.jar’)
}

配置独立的签名信息

通常我们可以直接把签名的明文信息写在 gradle 配置文件中,但是在开源代码的时候不是很方便,前者可能存放签名文件的位置需要修改,后者则希望隐藏签名信息,在看不少开源项目的时候,发现很多是这样做的 signingConfigs 位置, android 的下一级

signingConfigs {
release_key{
storeFile file(RELEASE_STORE_FILE)
storePassword RELEASE_STORE_PASSWORD
keyAlias RELEASE_KEY_ALIAS
keyPassword RELEASE_KEY_PASSWORD
}
}

buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
signingConfig signingConfigs.release_key
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
signingConfig signingConfigs.release_key
}
}

在对应位置引用常量,在 properties 中再进行具体赋值,这样不会直接暴露签名信息,也方便配置
在 gradle.properties 中

RELEASE_KEY_PASSWORD=xxxx
RELEASE_KEY_ALIAS=xxx
RELEASE_STORE_PASSWORD=xxx
RELEASE_STORE_FILE=../.keystore/xxx.jks

多渠道打包

在 product flavor 下定义不同类型, 把 AndroiManifest 中的 channel 替换
ductFlavors 位置: android 的下一级

android {
productFlavors {
fir {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: “fir”]
}
GooglePlay {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: “GooglePlay”]
}
Umeng {
manifestPlaceholders = [UMENG_CHANNEL_VALUE: “Umeng”]
}
}
}

替换 AndroiManifest 中的字段

<meta-data
android:name=”UMENG_CHANNEL”
android:value=”${UMENG_CHANNEL_VALUE}”/>

减少编译错误和忽略 lint 检查

packagingOptions {
exclude ‘META-INF/DEPENDENCIES.txt’
exclude ‘META-INF/LICENSE.txt’
exclude ‘META-INF/NOTICE.txt’
exclude ‘META-INF/NOTICE’
exclude ‘META-INF/LICENSE’
exclude ‘META-INF/DEPENDENCIES’
exclude ‘META-INF/notice.txt’
exclude ‘META-INF/license.txt’
exclude ‘META-INF/dependencies.txt’
exclude ‘META-INF/LGPL2.1’
}
lintOptions {
abortOnError false
}

生成自定义 App 名称,在Android标签添加如下代码

applicationVariants.all { variant ->
variant.outputs.all { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith(‘.apk’)) {
// 输出apk名称为ForWatch_v1.1(2)2016-09-28_15-54-35.apk
def version = “v${versionName}-${versionCode}”
def endIndex = outputFile.name.indexOf(‘.apk’)
def apkName = outputFile.name.substring(0, endIndex);
def fileName = “${apkName}
${version}${buildTime()}${revision()}.apk”
//output.outputFile = new File(outputFile.parent, fileName)
outputFileName = fileName
}
}
}

自定义apk的生成目录(含有自定义app名称的代码)

android {
……//省略部分代码
applicationVariants.all {
//判断是release还是debug版本
def buildType = it.buildType.name
def fileName
//下面的channel是获取渠道号,你获取渠道号不一定会和我的代码一样,因为有可能你的渠道名称的规则和我的不一样,我的规则是${渠道名}-${applicationId},所以我是这样取的。
def channel = it.productFlavors[0].name.split(“-“)[0]
//获取当前时间的”YYYY-MM-dd”格式。
def createTime = new Date().format(“YYYY-MM-dd”, TimeZone.getTimeZone(“GMT+08:00”))
//只对Release包起作用,如果不是Release包则不变更输出路径,否则可能导致AS无法自动安装debug包。
if (buildType == “release”) {
it.getPackageApplication().outputDirectory = new File(project.rootDir.absolutePath + “/apks/${it.productFlavors[0].applicationId}/${createTime}”)
}
it.outputs.each {
//只对Release包起作用,如果不是Release包则不变更名称。
if (buildType == “release”) {
//我此处的命名规则是:渠道名项目名版本名创建时间构建类型.apk
fileName = “${channel}_项目名称v${defaultConfig.versionName}${createTime}-${buildType}.apk”
//将名字打印出来,以便及时查看是否满意。
println “文件名:—————–${fileName}”
//重新对apk命名。(适用于Gradle4.0以下版本)
//it.outputFile = new File(it.outputFile.parent, fileName)
//重新对apk命名。(适用于Gradle4.0(含)以上版本)如果你Gradle版本是4.0以下版本则将上面的一行代码放开并注释下面的这一行。
it.outputFileName = fileName
}
}
}
……//省略部分代码
}

参考:https://blog.csdn.net/kelin410/article/details/75500821

指定资源目录

自定义 java 代码和 res 资源的目录,更加灵活

android {
sourceSets {
main {
manifest.srcFile ‘AndroidManifest.xml’
java.srcDirs = [‘src’]
resources.srcDirs = [‘src’]
aidl.srcDirs = [‘src’]
renderscript.srcDirs = [‘src’]
assets.srcDirs = [‘assets’]
if (!IS_USE_DATABINDING) { // 如果用了databinding
jniLibs.srcDirs = [‘libs’]
res.srcDirs = [‘res’, ‘res-vm’] // 多加了databinding的资源目录
} else {
res.srcDirs = [‘res’]
}
}
test {
java.srcDirs = [‘test’]
}
androidTest {
java.srcDirs = [‘androidTest’]
}
}
}

在 BuildConfig.class 中增加静态变量

有时候我们想根据不同的版本,设置相同变量不同的值,最常见的使用场景就是 Log 工具类,通过设置 isDubug 不同值,只有 debug 版本的 app 会产生 log 日志,设置过程如下:

buildTypes {
release {
buildConfigField(“boolean”, “isDebug”, “false”) // 定义 isdubug 的值
minifyEnabled false
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
}
debug{
buildConfigField(“boolean”, “isDebug”, “true”)
proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’
}
}

在 sync 后BuildConfig中就有你定义的这个变量(isDebug)。

public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean(“true”);
public static final String APPLICATION_ID = “com.hiwhitley.himei”;
public static final String BUILD_TYPE = “debug”;
public static final String FLAVOR = “”;
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = “1.0”;
// Fields from build type: debug
public static final boolean isDebug = true;
}

如果有带引号的 string,要记得转义:

buildConfigField “String”, “URL_ENDPOINT”, “”http://your.development.endpoint.com/“”

参考:

Gradle配置最佳实践
Android Studio 中 gradle 的一些玩法
Gradle 语法

    原文作者:xiechengfa
    原文地址: https://www.jianshu.com/p/fbde621bbb46
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞