2017年08月15日更新浅妆,不知道簡書出什么BUG了凌外,重新發(fā)布更新一下,原來的目錄標(biāo)簽全部失效變成文字了摄欲,無奈之下只有刪掉胸墙,簡直坑爹迟隅,待過幾日再看能否重新啟用目錄。
前言
本文記錄了一些常用的gradle配置奔缠,基本上都是平時(shí)開發(fā)中可能會(huì)使用到的校哎,如果有新內(nèi)容會(huì)不定時(shí)更新箫锤,附官網(wǎng)
1.依賴庫版本寫法
- 不推薦寫法:
dependencies {
compile 'com.example.code.abc:def:2.+' // 不推薦的寫法
}
這樣寫雖然可能保證每次都保持庫是最新的谚攒,但同時(shí)會(huì)有以下更嚴(yán)重的問題:
1)多人開發(fā)時(shí)馏臭,每個(gè)人可能會(huì)得到不同的最新版本括儒,帶來潛在的隱患锐想;
2)庫更新后赠摇,可能會(huì)由于庫的內(nèi)部代碼的修改而引起不易發(fā)現(xiàn)的BUG藕帜;
3)每次build時(shí)會(huì)聯(lián)網(wǎng)檢查洽故,增加build時(shí)間。
- 推薦寫法(固定版本):
dependencies {
compile 'com.example.code.abc:def:2.0.1' // 固定版本隘弊,有需要時(shí)再進(jìn)行修改
}
2.全局設(shè)置編碼
在最頂層的build.gradle
中添加:
allprojects {
repositories {
jcenter()
}
tasks.withType(JavaCompile){
options.encoding = "UTF-8"
}
}
3.設(shè)置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版本的密碼配置
密碼嚣鄙、簽名等敏感信息可以統(tǒng)一進(jìn)行存放串结,不進(jìn)行硬編碼肌割。寫在gradle.properies
中把敞,可以隨意的定義key-value
形式奋早,此文件是gradle
自動(dòng)引入的。
例: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.設(shè)置第三方maven倉庫
在頂層的build.gradle
中:
allprojects {
repositories {
maven {
url 'http://repo.xxxx.net/nexus/'
name 'maven name'
credentials {
username = 'username'
password = 'password'
}
}
}
}
其中name和credentials是可選項(xiàng),視具體情況而定规个。如使用阿里云倉庫如下:
allprojects {
repositories {
maven {
url "http://maven.aliyun.com/nexus/content/groups/public/"
}
}
}
6.自動(dòng)刪除unaligned apk
每次打包后都會(huì)有一個(gè)unaligned的apk文件生成诞仓,這個(gè)文件對(duì)于開發(fā)來說無意義速兔,可以配置一個(gè)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選項(xiàng)開關(guān)
lint默認(rèn)會(huì)做嚴(yán)格檢查屑柔,遇到包錯(cuò)誤會(huì)終止構(gòu)建過程掸宛。可以用如下開關(guān)關(guān)掉這個(gè)選項(xiàng)别凤,非特殊情況不最好不配置领虹。
寫在module
的build.gradle
中:
android {
lintOptions {
disable 'InvalidPackage'
checkReleaseBuilds false
abortOnError false
}
}
8.依賴項(xiàng)目中的module和jar
工程可以依賴自身的module和jar文件塌衰,如下:
dependencies {
compile project(':myExamplelibraryModule')
compile files('libs/sdk-1.1.jar')
}
9.根據(jù)buildType設(shè)置包名
寫在module
的build.gradle
中:
android {
defaultConfig {
applicationId "example" // 這里設(shè)置了example作為默認(rèn)包名
}
buildTypes {
release {
applicationIdSuffix '.abc.gradle' // 設(shè)置release時(shí)的包名為example.abc.gradle
}
debug{
applicationIdSuffix '.abc.debug' // 設(shè)置debug時(shí)的包名為example.abc.debug
}
}
10.替換AndroidManifest中的占位符
在manifest中可以有類似{appName}這樣的占位符杯巨,在module
的build.gradle
中可以將其進(jìn)行賦值努酸。
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
}
}
如果是在當(dāng)前文件中定義的获诈,就不用添加rootProject.ext
舔涎。
12.定義局部變量
有時(shí)候一個(gè)庫會(huì)被引用多次终抽,或者一個(gè)庫有多個(gè)依賴昼伴,但這些依賴的版本都是統(tǒng)一的镣屹。通過ext
來定義一些變量女蜈,這樣在用到的時(shí)候就可以統(tǒng)一使用了:
ext {
rxandroidVersion = '2.0.1'
rxjavaVersion = "2.1.0"
}
dependencies {
...
compile "io.reactivex.rxjava2:rxandroid:$rxandroidVersion"
compile "io.reactivex.rxjava2:rxjava:$rxjavaVersion"
}
13.動(dòng)態(tài)設(shè)置額外信息
假如想把當(dāng)前的編譯時(shí)間伪窖、編譯的機(jī)器覆山、最新的commit版本添加到apk中,動(dòng)態(tài)設(shè)置如下:
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()
}
上述代碼實(shí)現(xiàn)了動(dòng)態(tài)添加了3個(gè)字符串資源: 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
中增加自己的靜態(tài)變量:
defaultConfig {
applicationId "zyr.gradle.demo"
minSdkVersion 19
targetSdkVersion 24
buildConfigField("boolean", "IS_TEST", "true") // 定義一個(gè)bool變量
resValue "string", "build_time", "2017.06.12" // 上面講到的植入資源文件
}
在sync
后BuildConfig
中就有定義的這個(gè)變量了:
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;
}
如果有帶引號(hào)的string
牲尺,需要轉(zhuǎn)義:
buildConfigField "String", "URL_ENDPOINT", "\"http://your.development.example.com/\""
14.使用init.with繼承配置
如果想新增一個(gè)buildType
谤碳,又想新的buildType
繼承之前配置好的參數(shù)蜒简,使用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關(guān)鍵字
遇到庫沖突的問題時(shí)卷仑,將沖突的庫通過exclude來剔除:
- 剔除整個(gè)組織的庫:
compile ('com.facebook.fresco:animated-webp:0.13.0') {
exclude group: 'com.android.support' // 僅僅寫組織名稱
}
- 剔除某個(gè)庫:
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.聚合依賴多個(gè)庫
有時(shí)候一些庫是一并依賴的锡凝,剔除也是要一并剔除的窜锯,此時(shí)進(jìn)行統(tǒng)一引入:
compile(['io.reactivex.rxjava2:rxandroid:2.0.1',
'io.reactivex.rxjava2:rxjava:2.1.0'])
這樣別的開發(fā)者就知道哪些庫是有相關(guān)性的锚扎,在刪除庫的時(shí)候也更方便馁启。
17.跳過task
Gradle
每次構(gòu)建時(shí)都執(zhí)行了許多task
,其中有一些task
是不需要的浪听,可以把它們都屏蔽掉迹栓,如下:
tasks.whenTaskAdded { task ->
if (task.name.contains('AndroidTest') || task.name.contains('Test')) {
task.enabled = false
}
}
這樣在build時(shí)就會(huì)跳過包含AndroidTest和Test關(guān)鍵字的task了克伊。
NOTE:有時(shí)候自己也會(huì)寫一些task或者引入一些gradle插件和task愿吹,通過這種方式可以簡單的進(jìn)行選擇性的執(zhí)行犁跪。
18.通過邏輯判斷來跳過task
上面有提到過動(dòng)態(tài)獲得字段歹袁,但有些東西是在打包發(fā)布的時(shí)候用条舔,有些則是在調(diào)試時(shí)用孟抗,需要區(qū)分不同的場景凄硼,定義不同的task帆喇。下面以通過“以git
的commit
號(hào)當(dāng)做版本號(hào)”這個(gè)需求做例子:
def cmd = 'git rev-list HEAD --first-parent --count'
def gitVersion = cmd.execute().text.trim().toInteger()
android {
defaultConfig {
versionCode gitVersion
}
}
因?yàn)樯厦娴牟僮骺赡鼙容^慢坯钦,或者在debug時(shí)沒必要侈玄,所以就做了如下判斷:
def gitVersion() {
if (!System.getenv('CI_BUILD')) { // 不通過CI進(jìn)行build的時(shí)候返回1
return 1 //1無實(shí)際意義,return用于中斷后續(xù)操作
}
def cmd = 'git rev-list HEAD --first-parent --count'
cmd.execute().text.trim().toInteger()
}
android {
defaultConfig {
versionCode gitVersion()
}
}
這里用到了System.getenv()
方法序仙,可以參考Java
中System
下的getenv()
突颊,就是得到當(dāng)前的環(huán)境。
19.引用全局的配置文件
在根目錄中建立一個(gè)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.區(qū)分不同環(huán)境下的不同依賴
除了通過buildtype來定義不同的依賴外律秃,還可以通過寫邏輯判斷來做:
先在gradle.properties
中寫上:
needExample = true
然后在module
的build.gradle
中使用:
dependencies {
//根據(jù)是不同情形進(jìn)行判斷
if (!needExample) {
provided fileTree(dir: 'libs', include: ['*.jar'])
} else {
compile 'com.android.support:example:1.0.0'
}
// ...
}
21.動(dòng)態(tài)改變module種類
插件化有可能會(huì)要根據(jù)環(huán)境更改當(dāng)前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.定義庫的私有混淆(針對(duì)庫的開發(fā))
有很多庫是需要進(jìn)行混淆配置的爬橡,但讓庫的使用者配置混淆文件的方式總是不太友好,consumerProguardFiles
可以讓庫的作者在庫中定義混淆參數(shù)棒动,讓使用者無需了解其混淆:
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
文件位置如下圖:
打包工具會(huì)將*.pro
文件打包進(jìn)入aar
中,庫混淆的時(shí)候會(huì)自動(dòng)使用此混淆配置文件船惨。
以consumerProguardFiles
方式加入的混淆具有以下特性:
-
*.pro
文件會(huì)包含在aar
文件中 - 這些
pro
配置會(huì)在混淆的時(shí)候被使用 - 此配置針對(duì)此
aar
進(jìn)行混淆配置 - 此配置只對(duì)庫文件(
apply plugin: 'com.android.library
)有效柜裸,對(duì)應(yīng)用程序(apply plugin: 'com.android.application'
)無效
23.指定資源目錄
在module
的build.gradle
中通過下面的配置,可以自定義java代碼和res資源的目錄粱锐,一個(gè)和多個(gè)都可以疙挺,更加靈活:
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.定義多個(gè)Manifest
在module
的build.gradle
中:
sourceSets {
main {
if (isDebug.toBoolean()) {
manifest.srcFile 'src/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/release/AndroidManifest.xml'
}
}
}
根據(jù)flavor
也可以進(jìn)行定義:
productFlavors {
abc {
manifest.srcFile 'abc/AndroidManifest.xml'
}
main {
manifest.srcFile '/AndroidManifest.xml'
}
}
最后
gradle
可以做很多事,也非常靈活怜浅。希望上面提到的一些配置對(duì)大家有所幫助铐然。有空去官網(wǎng)了解最好。
吐糟一句恶座,簡書的markdown真?難用=蹙簟!
原文作者/ZYRzyr
原文鏈接:http://www.reibang.com/p/7ca459085b96
請(qǐng)進(jìn)入這里獲取授權(quán):https://101709080007647.bqy.mobi