本文做爲實戰系列,主要講解gradle在實際項目中的使用,原理部分不會講解太多。本文會用到一些Groovy的知識,若是不瞭解Groovy基礎語法的話能夠參考一下主席的文章Groovy基礎,Gradle執行時序。固然我也會對使用到的地方作註解說明,就算你不看的話,也行。java
這裏主要是說項目的編譯版本、依賴庫的版本等,這裏參考Google官方的項目,在項目的根目錄單獨建一個version.gradle文件統一管理版本,這樣作的好處明顯,特別是多module的項目,很方便的作統一版本管理,避免衝突。可是這樣作也會帶來一個壞處,就是你inspection檢查新版本的時候,當有了新版本的話,你是檢查不到的。不過整體來講,利大於弊吧。android
來看一看version.gradle文件裏都有些什麼吧git
// version.gradle文件
ext{
android = [
compileSdkVersion: 27,
minSdkVersion : 21,
targetSdkVersion : 27,
versionName: "1.0.0"
]
dependencies = [
appcompatV7 : 'com.android.support:appcompat-v7:27.1.1',
design : 'com.android.support:design:27.1.1',
constrant :'com.android.support.constraint:constraint-layout:1.0.2'
]
}
複製代碼
這裏做爲說明,只寫了幾個最基本的依賴,接下來就是要使用這些配置了。首先在project的build.gradle文件裏引入github
buildscript {
apply from: 'version.gradle'
repositories {
google()
jcenter()
}
…………
}
複製代碼
而後,在module的gradle裏就能夠愉快的使用了。緩存
compileSdkVersion rootProject.ext.android.compileSdkVersion
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode getCode()
versionName rootProject.ext.android.versionName
…………
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation rootProject.ext.dependencies.appcompatV7
implementation rootProject.ext.dependencies.constrant
implementation rootProject.ext.dependencies.design
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.1'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
複製代碼
細心的小夥伴可能發現了,上面的versionCode並無使用version.gradle裏配置的versionCode,事實上version.gradle裏也並無配置versionCode,這裏我是根據產品需求使用versionName自動生成的versionCode。服務器
// 讀取version.gradle裏的versionName 生成versionCode
def getCode() {
String name = rootProject.ext.android.versionName
List arr = name.tokenize('.')
int code1
int code2
int code3
code1 = arr.get(0).toInteger() * 10000
code2 = arr.get(1).toInteger() * 100
code3 = arr.get(2).toInteger()
int code = code1 + code2 + code3
}
複製代碼
上面就是獲取版本號的方法,採用三段式,每段兩位,能夠根據實際需求本身改。另外說明一下,Groovy語法裏,若是本身不寫return語句,會把最後一行計算的code自動return。這樣的話,就不用每次版本升級要修改versionName還要修改versionCode了。注意上面的代碼是在android的同級領域。微信
簽名文件怎麼生成這裏就不說了,須要說明的是爲了方便引用,jks簽名文件我放在了app目錄下,一樣在這個目錄下,建立了一個signing.properties的文件,文件內容以下:app
// signing.properties 文件
storePass=123456
alias=key
keyPass=123456
v2SigningEnabled=false
signingFile=key.jks
複製代碼
就是基本的簽名信息了,看一下module的gradle裏的使用:maven
signingConfigs {
// 定義signConfig並賦值
signConfig
File propFile = file('signing.properties')
if (propFile.exists()) {
Properties props = new Properties()
props.load(new FileInputStream(propFile))
if (props.containsKey('signingFile') && props.containsKey('storePass') &&
props.containsKey('alias') && props.containsKey('keyPass') && props.containsKey("v2SigningEnabled")) {
signConfig.storeFile = file(props['signingFile'])
signConfig.storePassword = props['storePass']
signConfig.keyAlias = props['alias']
signConfig.keyPassword = props['keyPass']
android.signingConfigs.signConfig.v2SigningEnabled = props['v2SigningEnabled']
} else {
android.buildTypes.release.signingConfig = null
android.buildTypes.flavor.signingConfig = null
}
} else {
android.buildTypes.release.signingConfig = null
android.buildTypes.flavor.signingConfig = null
}
print("signingConfigs===========${signConfig}")
}
複製代碼
就是定義一個signConfig 並給賦值了,很簡單。可是這樣寫就避免了直接在gradle裏暴露簽名信息了。固然你能夠在terminal裏運行一下gradle guild指令來驗證,看一下打印結果是否正確。性能
配置完之後,直接在buildTypes裏引用就好了。
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.signConfig
…………
}
複製代碼
實際開發中服務器通常有正式環境和生成環境,有時候還會有個後臺開發人員本身本地的服務器環境,這時候經過自定義buildConfigField來區分配置不一樣的環境
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.signConfig
buildConfigField "boolean","isRelease","true"
…………
}
複製代碼
咱們在release的type裏把值設置爲true,其餘的type設置爲fasle,這樣,同步完之後,在BuildConfig類裏會多出一個靜態變量isRelease,這樣在java代碼裏,就能夠根據這個變量來判斷是測試環境仍是生產環境了,還能夠根據這個變量來控制是否須要日誌輸出等。甚至你均可以直接把測試服務器地址和生產服務器地址配置到裏面都行。
buildConfigField 'String','API_SERVER_URL','"http://lxy.v1/"'
複製代碼
實際開發中,爲了區分測試版和正式版,有時候須要把測試版的包名和app名字設置爲不一樣。其實這樣的需求用gradle分分鐘就能夠實現
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.signConfig
buildConfigField "boolean","isFlavor","false"
manifestPlaceholders = [
APP_NAME : "release"
]
}
debug {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.signConfig
buildConfigField "boolean","isFlavor","false"
applicationIdSuffix 'debug'
manifestPlaceholders = [
APP_NAME : "debug"
]
}
複製代碼
如上,在debug版裏,配置了applicationIdSuffix 'debug',這樣打包的話,會在原來的包名後面加上debug,這樣安裝到手機上就是兩個不一樣的app了,由於包名不一樣。這樣一個測試機就能夠同時測試測試包和正式包了。並且,還設置了manifestPlaceholders佔位符,這樣在menifests文件裏直接引用就行,就實現了不一樣的包名和app名字。
// 清單文件裏引用
android:label="${APP_NAME}"
複製代碼
這裏有個坑,若是這樣配置事後,若是你項目裏使用有微信支付、分享等的sdk,注意支付、分享後的回調的類所在的包和正式版分開,不然是收不到回調的(微信的sdk有時候很蛋疼)。
在android的領域裏添加以下代碼
applicationVariants.all { variant ->
variant.outputs.all { output ->
def newApkName
newApkName = getTime() + defaultConfig.versionName + "-" + defaultConfig.versionCode + ".apk"
outputFileName = newApkName
}
}
複製代碼
getTime()方法在android領域的同級
def getTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
複製代碼
java8的lambda仍是很簡潔的,一樣,dataBinding用起來同樣爽飛
// 固然在android領域裏設置了
dataBinding {
enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
複製代碼
如今新建as項目會自動在app目錄下生成一個libs目錄,能夠在gradle裏設置jar、so庫等的文件目錄
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
複製代碼
混淆配置的話配置在release版本里,注意別忘了添加混淆文件
minifyEnabled true
zipAlignEnabled true
shrinkResources true
複製代碼
用gradle打包多渠道的話比較慢,這裏就不講了,我的感受360多渠道打包挺好用的,推薦一下。
以上是實際項目裏經常使用的配置,固然還有不少不太經常使用的配置,如可能須要打包aar到maven,gradle編譯、gradle性能檢測、gradle加速、使用gradle緩存,自定義gradle插件等等,篇幅問題,你們本身學習了……
附上完整的demo地址,若是對你有幫助,麻煩start鼓勵一下!