Android中Gradle常用配置
前言
本文记录了一些常用的gradle配置,基本上都是平时开发中可能会使用到的,如果有新内容会不定时更新,附官网
1.依赖库版本写法
不推荐写法:
dependencies {
compile 'com.example.code.abc:def:2.+' // 不推荐的写法
}
这样写虽然可能保证每次都保持库是最新的,但同时会有以下更严重的问题:
1)多人开发时,每个人可能会得到不同的最新版本,带来潜在的隐患;
2)库更新后,可能会由于库的内部代码的修改而引起不易发现的BUG;
3)每次build时会联网检查,增加build时间。
推荐写法(固定版本):
dependencies {
compile 'com.example.code.abc:def:2.0.1' // 固定版本,有需要时再进行修改
}
2.全局设置编码
在最顶层的build.gradle中添加:
allprojects {
repositories {
jcenter()
}
tasks.withType(JavaCompile){
options.encoding = "UTF-8"
}
}
3.设置Java编译版本
在module中的build.gradle中:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
}
全局配置则在最顶层的build.gradle中:
allprojects {
repositories {
jcenter()
}
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
}
4.Release版本的密码配置
密码、签名等敏感信息可以统一进行存放,不进行硬编码。写在gradle.properies中,可以随意的定义key-value形式,此文件是gradle自动引入的。
例:gradle.properies文件如下
STORE_FILE_PATH ../test_key.jks
KEYSTORE_PASSWORD 123456
KEY_ALIAS abc
KEY_PASSWORD 654321
PACKAGE_NAME_SUFFIX .test
TENCENT_AUTHID aaa0123
module的build.gradle文件:
signingConfigs {
release {
try {
storeFile file(STORE_FILE_PATH)
storePassword STORE_PASSWORD
keyAlias KEY_ALIAS
keyPassword KEY_PASSWORD
}
catch (ex) {
throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
}
}
}
5.设置第三方maven仓库
在顶层的build.gradle中:
allprojects {
repositories {
maven {
url 'http://repo.xxxx.net/nexus/'
name 'maven name'
credentials {
username = 'username'
password = 'password'
}
}
}
}
其中name和credentials是可选项,视具体情况而定。如使用阿里云仓库如下:
allprojects {
repositories {
maven {
url "http://maven.aliyun.com/nexus/content/groups/public/"
}
}
}
6.自动删除unaligned apk
每次打包后都会有一个unaligned的apk文件生成,这个文件对于开发来说无意义,可以配置一个task来删除它。
写在module的build.gradle中:
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
}
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
// 删除unaligned apk
if (output.zipAlign != null) {
output.zipAlign.doLast {
output.zipAlign.inputFile.delete()
}
}
}
}
7.lint选项开关
lint默认会做严格检查,遇到包错误会终止构建过程。可以用如下开关关掉这个选项,非特殊情况不最好不配置。
写在module的build.gradle中:
android {
lintOptions {
disable 'InvalidPackage'
checkReleaseBuilds false
abortOnError false
}
}
8.依赖项目中的module和jar
工程可以依赖自身的module和jar文件,如下:
dependencies {
compile project(':myExamplelibraryModule')
compile files('libs/sdk-1.1.jar')
}
9.根据buildType设置包名
写在module的build.gradle中:
android {
defaultConfig {
applicationId "example" // 这里设置了example作为默认包名
}
buildTypes {
release {
applicationIdSuffix '.abc.gradle' // 设置release时的包名为example.abc.gradle
}
debug{
applicationIdSuffix '.abc.debug' // 设置debug时的包名为example.abc.debug
}
}
10.替换AndroidManifest中的占位符
在manifest中可以有类似{appName}这样的占位符,在module的build.gradle中可以将其进行赋值。
android{
defaultConfig{
manifestPlaceholders = [appName:"@string/app_name"]
}
}
11.定义全局变量
先在顶层的build.gradle定义全局变量:
ext {
minSdkVersion = 19
targetSdkVersion = 24
}
然后在各module的build.gradle中可以通过rootProject.ext来引用:
android {
defaultConfig {
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
}
}
如果是在当前文件中定义的,就不用添加rootProject.ext。
12.定义局部变量
有时候一个库会被引用多次,或者一个库有多个依赖,但这些依赖的版本都是统一的。通过ext来定义一些变量,这样在用到的时候就可以统一使用了:
ext {
rxandroidVersion = '2.0.1'
rxjavaVersion = "2.1.0"
}
dependencies {
...
compile "io.reactivex.rxjava2:rxandroid:$rxandroidVersion"
compile "io.reactivex.rxjava2:rxjava:$rxjavaVersion"
}
13.动态设置额外信息
假如想把当前的编译时间、编译的机器、最新的commit版本添加到apk中,动态设置如下:
android {
defaultConfig {
resValue "string", "build_time", buildTime()
resValue "string", "build_host", hostName()
resValue "string", "build_revision", revision()
}
}
def buildTime() {
return new Date().format("yyyy-MM-dd HH:mm:ss")
}
def hostName() {
return System.getProperty("user.name") + "@" + InetAddress.localHost.hostName
}
def revision() {
def code = new ByteArrayOutputStream()
exec {
commandLine 'git', 'rev-parse', '--short', 'HEAD'
standardOutput = code
}
return code.toString()
}
上述代码实现了动态添加了3个字符串资源: build_time、build_host、build_revision, 在其他地方可像引用strings.xml中的字符串一样使用:
getString(R.string.build_time) // 输出2017-06-12 15:05:05
getString(R.string.build_host) // 输出zyr@example,这是我的电脑的用户名和PC名
getString(R.string.build_revision) // 输出5ff4x89, 这是最后一次commit的sha值
上面讲到的是植入资源文件,同样可以在BuildConfig.class中增加自己的静态变量:
defaultConfig {
applicationId "zyr.gradle.demo"
minSdkVersion 19
targetSdkVersion 24
buildConfigField("boolean", "IS_TEST", "true") // 定义一个bool变量
resValue "string", "build_time", "2017.06.12" // 上面讲到的植入资源文件
}
在sync后BuildConfig中就有定义的这个变量了:
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "zyr.gradle.test";
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.0";
// Fields from default config.
public static final boolean IS_TEST = true;
}
如果有带引号的string,需要转义:
buildConfigField "String", "URL_ENDPOINT", "\"http://your.development.example.com/\""
14.使用init.with继承配置
如果想新增一个buildType,又想新的buildType继承之前配置好的参数,使用init.with()。
buildTypes {
release {
zipAlignEnabled true
minifyEnabled true
shrinkResources true // 是否去除无效的资源文件
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
signingConfig signingConfigs.release
}
abcd.initWith(buildTypes.release) // 继承release的配置
abcd {
...
}
}
15.exlude关键字
遇到库冲突的问题时,将冲突的库通过exclude来剔除:
剔除整个组织的库:
compile ('com.facebook.fresco:animated-webp:0.13.0') {
exclude group: 'com.android.support' // 仅仅写组织名称
}
剔除某个库:
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'
}
16.聚合依赖多个库
有时候一些库是一并依赖的,剔除也是要一并剔除的,此时进行统一引入:
compile(['io.reactivex.rxjava2:rxandroid:2.0.1',
'io.reactivex.rxjava2:rxjava:2.1.0'])
这样别的开发者就知道哪些库是有相关性的,在删除库的时候也更方便。
17.跳过task
Gradle每次构建时都执行了许多task,其中有一些task是不需要的,可以把它们都屏蔽掉,如下:
tasks.whenTaskAdded { task ->
if (task.name.contains('AndroidTest') || task.name.contains('Test')) {
task.enabled = false
}
}
这样在build时就会跳过包含AndroidTest和Test关键字的task了。
NOTE:有时候自己也会写一些task或者引入一些gradle插件和task,通过这种方式可以简单的进行选择性的执行。
18.通过逻辑判断来跳过task
上面有提到过动态获得字段,但有些东西是在打包发布的时候用,有些则是在调试时用,需要区分不同的场景,定义不同的task。下面以通过“以git的commit号当做版本号”这个需求做例子:
def cmd = 'git rev-list HEAD --first-parent --count'
def gitVersion = cmd.execute().text.trim().toInteger()
android {
defaultConfig {
versionCode gitVersion
}
}
因为上面的操作可能比较慢,或者在debug时没必要,所以就做了如下判断:
def gitVersion() {
if (!System.getenv('CI_BUILD')) { // 不通过CI进行build的时候返回1
return 1 //1无实际意义,return用于中断后续操作
}
def cmd = 'git rev-list HEAD --first-parent --count'
cmd.execute().text.trim().toInteger()
}
android {
defaultConfig {
versionCode gitVersion()
}
}
这里用到了System.getenv()方法,可以参考Java中System下的getenv(),就是得到当前的环境。
19.引用全局的配置文件
在根目录中建立一个config.gradle文件:
ext {
android = [
compileSdkVersion: 23,
applicationId : "com.zyr.gradle",
]
dependencies = [
"support-v7": "com.android.support:appcompat-v7:24.2.1",
]
}
然后在顶层的build.gradle中引入apply from: “config.gradle”,即:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
apply from: "config.gradle" // 引入该文件
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
// ...
}
之后就可以在其余的build.gradle中读取变量了:
defaultConfig {
applicationId rootProject.ext.android.applicationId // 引用applicationId
minSdkVersion 14
targetSdkVersion 20
}
dependencies {
compile rootProject.ext.dependencide["support-v7"] // 引用dependencide
}
20.区分不同环境下的不同依赖
除了通过buildtype来定义不同的依赖外,还可以通过写逻辑判断来做:
先在gradle.properties中写上:
needExample = true
然后在module的build.gradle中使用:
dependencies {
//根据是不同情形进行判断
if (!needExample) {
provided fileTree(dir: 'libs', include: ['*.jar'])
} else {
compile 'com.android.support:example:1.0.0'
}
// ...
}
21.动态改变module种类
插件化有可能会要根据环境更改当前module是app还是lib:
先在gradle.properties中写上:
isDebug = false
然后在module的build.gradle中使用:
if (isDebug.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
22.定义库的私有混淆(针对库的开发)
有很多库是需要进行混淆配置的,但让库的使用者配置混淆文件的方式总是不太友好,consumerProguardFiles可以让库的作者在库中定义混淆参数,让使用者无需了解其混淆:
apply plugin: 'com.android.library'
android {
compileSdkVersion 24
buildToolsVersion '24.0.2'
defaultConfig {
minSdkVersion 9
targetSdkVersion 24
consumerProguardFiles 'consumer-proguard-rules.pro' // 自定义混淆配置
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
其中的consumer-proguard-rules.pro文件位置如下图:
consumerProguardFiles.jpg
打包工具会将*.pro文件打包进入aar中,库混淆的时候会自动使用此混淆配置文件。
以consumerProguardFiles方式加入的混淆具有以下特性:
*.pro文件会包含在aar文件中
这些pro配置会在混淆的时候被使用
此配置针对此aar进行混淆配置
此配置只对库文件(apply plugin: 'com.android.library)有效,对应用程序(apply plugin: ‘com.android.application’)无效
23.指定资源目录
在module的build.gradle中通过下面的配置,可以自定义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']
}
}
}
24.定义多个Manifest
在module的build.gradle中:
sourceSets {
main {
if (isDebug.toBoolean()) {
manifest.srcFile 'src/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/release/AndroidManifest.xml'
}
}
}
根据flavor也可以进行定义:
productFlavors {
abc {
manifest.srcFile 'abc/AndroidManifest.xml'
}
main {
manifest.srcFile '/AndroidManifest.xml'
}
}
原文地址:https://blog.csdn.net/NotesChapter/article/details/144371375
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!