當咱們的工程中有許多module的時候,分開管理編譯版本,minsdk將會是一件很麻煩的事,由於一個library的改動,可能會影響到其餘module。這時咱們就須要對全部的版本進行統一的管理,管理的方式有兩種:javascript
咱們能夠把一些須要用的字段都放在project的build.gradle(注意是project的不是module的)中:java
ext {
compileSdk = 21
minSdk = 11
targetSdk = 23
support = "23.1.1"
buildTools = "21.0.1"
buildstyle ="debug"
}複製代碼
這樣,在module的build.gradle中能夠進行讀取:android
defaultConfig {
applicationId "android.com.testgradle"
minSdkVersion rootProject.ext.minSdk
targetSdkVersion rootProject.ext.targetSdk
versionCode 1
versionName "1.0"
}複製代碼
找到工程目錄下的gradle.properties文件,若是沒有也能夠本身建立:git
ANDROID_COMPLILE_SDK_VERSION=21
ANDROID_BUILD_SDK_VERSION=21.0.1
ANDROID_TEXT=test複製代碼
而後在各個module的build.gradle中能夠引用:github
compileSdkVersion ANDROID_COMPLILE_SDK_VERSION as int
buildToolsVersion ANDROID_BUILD_SDK_VERSION複製代碼
須要注意的是在gradle.properties中聲明的格式都是string類型,若是如要轉化成int類型,能夠用as int 進行強制轉化。app
#程序中對buildTypes的區分gradle
##buildTypes是對不一樣build類型的處理
當你點擊運行按鈕的時候會根據build Variant進行對應的方式編譯。
build Variant能夠在這裏進行選擇:ui
默認狀況下被依賴工程會使用release模式,與上層依賴的app工程選擇的模式無關
須要在build.gradle中進行設置:spa
defaultPublishConfig "debug"複製代碼
你能夠在buildTypes,根據須要新增一個類型,以下代碼所示:插件
buildTypes {
debug {
buildConfigField("String","TEXT","\"這個字符串來自debug模式\"")
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
stag {
buildConfigField("String","TEXT","\"這個字符串來自test模式\"")
minifyEnabled false
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
buildConfigField("String","TEXT","\"這個字符串來自release模式\"")
minifyEnabled false
signingConfig signingConfigs.debug
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}複製代碼
根據上面的代碼,在不一樣的buildTypes中,TEXT這個變量是不同的,並且根據代碼能夠看出,這個變量是一個String類型,那麼咱們在程序文件中能夠這樣經過BuildConfig引用:
t2.setText(BuildConfig.TEXT);複製代碼
gradle插件容許最終生成的包以多個維度進行組合
例如咱們能夠設定一下幾個維度:
productFlavors {
red {
applicationId 'android.com.red'
versionCode 1
minSdkVersion 21
targetSdkVersion 22
}
blue {
applicationId 'android.com.blue'
}
yellow {
applicationId 'android.com.yellow'
}
}複製代碼
每一個維度中能夠設置這個版本的最小sdk限制,以及targetsdkversion
假設咱們設置的維度有red blue yellow可是結合以前講過的buildType(假設只有debug和release)
那麼將會出現如下構建:
blueDebug和blueRelease
yellowDebug和yellowRelease
redDebug和redRelease
Gradle會爲每個Variant建立一個任務
對應以下:
gradle assembleBlue 會生成debug和release兩個版本
gradle assembleDebug 會生成blue yellow red三個版本
gradle assembleBlueDebug 會生成bluedebug一個版本
這裏還有一個用處須要提一下:
Gradle在打包android應用以前會將全部的代碼,資源文件,包括manifest進行結合,固然library也會提供額外的資源,這些也會進行合併。
若是咱們在建立一些設置時,須要動態的去更改內容,能夠設置一個變量,而後從本地文件或者打包的命令行讀取,咱們這裏就拿上面提到過的BuildConfig作例子,但願程序中引用的字符串是從本地讀取的或從命令行讀取的
首先須要在最開始的地方設置一個變量aaa:
而後在buildTypes的debug模式中修改對應的代碼:
debug {
buildConfigField("String","TEXT","\""+aaa+"\"")
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}複製代碼
而後在工程目錄下建立一個本地文件test.properties,並添加內容:
而後回到你剛纔定義字符串的build.gradle中,添加:
if(rootProject.file('test.properties').exists()){
java.util.Properties properties = new Properties()
properties.load(rootProject.file('test.properties').newDataInputStream())
aaa = properties.getProperty('debug.text')
println("!!!!!"+aaa)
}else {
aaa = "文件沒找到"
}複製代碼
便可讀取到你本地文件的字符串
若是是從命令行讀入就更加簡單,只須要將上面讀取文件的代碼改成:
aaa = new String(System.console().readLine("請輸入字符串:"))複製代碼
首先想看一個工程包含了多少task,須要切到這個工程目錄下:
gradle tasks複製代碼
會列出全部的tasks:
assembleDebug複製代碼
其它同理便可。
若是使用build則回編譯出全部的版本
如今調整一下結構:
把jar以module的形式提供就不會出現衝突。
例如咱們新建一個任務:
task umengtest{
println("aaaaaaaaa")
println("bbbbbb")
}複製代碼
他的執行以下:
task umengtestaa<<{
println("ccc")
println("dddd")
}複製代碼
此次執行這個任務:
task umengtest{
doLast{
println("aaaaaaaaa")
println("bbbbbb")
}
}複製代碼
有了上面的基礎,下面就能夠說一下打包的任務了,根據咱們以前的工程,咱們有一個app的module和四個library module,我須要打印出一個apk和四個jar,明確了任務,如今能夠開始實施了。
打開工程的build.gradle
def sdk = [
root : 'build/sdk/',
]task dabao( type:Zip) {
dependsOn('cp_main')
def name = 'umeng_test' ;
destinationDir = file('build')
archiveName = name + '.zip'
from('build/sdk') {
into( name )
}
}
task cp_main(type: Copy, dependsOn: ['app:assembleRelease'] ) {
destinationDir = file( sdk.root )
from('app/build/outputs/apk') {
include('app-release.apk')
rename ('app-release.apk','test.apk' )
into('.')
}
from('mylibrary1/build/intermediates/bundles/release') {
include('classes.jar')
rename ('classes.jar','library1.jar' )
into('.')
}
from('mylibrary2/build/intermediates/bundles/release') {
include('classes.jar')
rename ('classes.jar','library2.jar' )
into('.')
}
from('mylibrary3/build/intermediates/bundles/release') {
include('classes.jar')
rename ('classes.jar','library3.jar' )
into('.')
}
from('mylibrary4/build/intermediates/bundles/release') {
include('classes.jar')
rename ('classes.jar','library4.jar' )
into('.') }
}複製代碼
這時,咱們再去找一下工程的build文件夾下能夠發現:
打包不一樣內容的module能夠利用以前講過的variant或這個buildtypes來控制,這裏就不說了,不明白的,能夠回頭再去看一下結合上面的打包腳本沒有什麼難度,然而還有一種需求,不是某個變量或者包名的更改,而是兩個版本中兩個文件的不一樣,咱們能夠試一下修改variant的方式來實現,在app的build.gradle中:
productFlavors {
pay {
}
free {
}
}複製代碼
修改結構目錄:
在這裏已經說完了全部與打包相關的東西了,在最後仍然加這一個標題是交給你們如何防止項目開發者打包出錯,或者上傳包出錯後定位問題。
方法就是在打包的時候,生成一個記錄文件,在這個包中記錄打包時間,和當前git的版本號:
def releaseTime() {
return new Date().format("yyyyMMddHHmmss", TimeZone.getTimeZone("GMT+8"))
}
def getGitVersion() {
return 'git rev-parse --short HEAD'.execute().text.trim()
}
task writefile( ){
File configFile = new File('config.xml');
if (!configFile.exists()){
configFile.createNewFile()
}
FileOutputStream out =new FileOutputStream(configFile)
def result ="編譯時間:"+"${releaseTime()}\n"+"commitid:"+"${getGitVersion()}\n" out.write(result.getBytes())
out.close();
}
task cp_config(type: Copy, dependsOn: ['writefile'] ) {
destinationDir = file( sdk.root )
duplicatesStrategy = 'exclude'
includeEmptyDirs = false
from('.') {
include('config.xml')
into('.')
}
}複製代碼
以上工程中所用到的全部代碼,已經上傳github
地址以下:
github.com/mymdeep/And…
若有對groovy語法不清楚的看官,請看一下個人上一篇文章,groovy基礎知識:
www.jianshu.com/p/b58b254d8…
*更多的開發知識,能夠關注個人公衆號: