強(qiáng)大的Gadle
自?Android Studio發(fā)布以來(lái),Gradle作為構(gòu)建工具,??有著強(qiáng)大的?功能。我們可以通過(guò)簡(jiǎn)單的?配置來(lái)實(shí)現(xiàn)一些復(fù)雜的構(gòu)建過(guò)程。???????????????包括自動(dòng)區(qū)分版本打包,多渠道打包等。引用一張官方的構(gòu)建流程圖:

主要文件
咱們最常用到的是build.gradle文件,通常的項(xiàng)目中會(huì)有?兩個(gè):
- Project根目錄下,Project級(jí)別的build.gradle文件
- 各個(gè)Module目錄下,Module級(jí)別的build.gradle文?件
Project級(jí)別的build.gradle
?這個(gè)是頂級(jí)的構(gòu)建文件,位于項(xiàng)目根目錄
/**
* 定義項(xiàng)目中所有模塊共用的 Gradle 存儲(chǔ)區(qū)和依賴項(xiàng)
*/
buildscript {
/**
* 代碼遠(yuǎn)程倉(cāng)庫(kù),可以定義搜索并下載的遠(yuǎn)程倉(cāng)庫(kù),也能定義自己的遠(yuǎn)程倉(cāng)庫(kù)。
* 支持本地和遠(yuǎn)程倉(cāng)庫(kù),如下是引用了JCenter?作為遠(yuǎn)程依賴倉(cāng)庫(kù)。
*/
repositories {
jcenter()
}
/**
* 一些頂級(jí)的依賴,用于整個(gè)項(xiàng)目?,如下是使用的gradl插件2.3.3
*/
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
}
}
/**
* 給所有的Module配置公用依賴,包括一些第三方的插件?和庫(kù)。單獨(dú)的需要進(jìn)入Module級(jí)別的build.gradle文件進(jìn)行?配置
* Android新項(xiàng)目會(huì)默認(rèn)使用JCenter,但不會(huì)添加任何依賴。
*/
allprojects {
repositories {
jcenter()
}
}
/**
* 經(jīng)常會(huì)有些項(xiàng)目有這樣的寫(xiě)法,位于頂層的配置?可以被其他的gradle文件調(diào)用,所以有些項(xiàng)目會(huì)把版本號(hào),SDK的版本配置在這里,方便所有的gradle文件統(tǒng)一
*/
ext {
//版本號(hào)版本名稱(chēng)等
versionCode = 1
versionName = '1.0.0'
}
Module級(jí)別的build.gradle
?通常我們?新建項(xiàng)目的時(shí)候?,這個(gè)目錄是app/build.gradle。這個(gè)文件中就有很多可以給我們??進(jìn)行自定義了。?包括 android{} repositories{} dependencies{} 等?;
- android{}
這邊挑幾個(gè)主要的介紹
?android {
//...
//默認(rèn)配置
defaultConfig{
}
//編譯類(lèi)型配置
buildTypes {
//可以根據(jù)實(shí)際情況來(lái)定義各種構(gòu)建類(lèi)型
debug{
?//對(duì)于debug版本的單獨(dú)配置,包括debug開(kāi)關(guān),和一些參數(shù)的配置
}
release{}
//...
}
//?渠道打包??梢葬槍?duì)不同渠道生成不同的包名。也可以用來(lái)區(qū)分免費(fèi)版和付費(fèi)版
productFlavors {
free {
applicationId 'com.example.myapp.free'
}
paid {
applicationId 'com.example.myapp.paid'
}
}
//...
}
- repositories{}
repositories {
//主要是一些?倉(cāng)庫(kù)的設(shè)置,支持本地代碼庫(kù)
mavenCentral()
flatDir {
dirs 'aars'
}
}
- dependencies{}
比較常用的是這個(gè)?配置,用來(lái)依賴各種第三方代碼
//代碼依賴
?dependencies {
//本地的依賴
compile fileTree(include: ['*.jar'], dir: 'libs')
//通常的依賴
compile 'io.reactivex:rxjava:1.1.6'
//?測(cè)試依賴
testCompile 'junit:junit:4.12'
//正式發(fā)布的時(shí)候依賴
releaseCompile 'com.android.support:appcompat-v7:25.3.1'
//只在調(diào)試的時(shí)候依賴
debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1'
}
一些實(shí)用的配置和技巧
關(guān)于簽名的一些配置
在實(shí)際?開(kāi)發(fā)中,大部分情況下,我們會(huì)將代碼通過(guò)Git上傳至代碼倉(cāng)庫(kù),?這樣的話,簽名配置等一些敏感信息,例如密碼等都不適合上傳。?那么這個(gè)時(shí)候,我們可以使用本地的一個(gè)「local.properties」文件來(lái)進(jìn)行本地的?簽名信息配置(該?文件不被上傳至代碼庫(kù),??庫(kù)將其添加至.ignore文件中)。Android Studio會(huì)?默認(rèn)為我們生成這么一個(gè)文件的,它本來(lái)是用來(lái)配置SDK在本地的路徑等信息的?,F(xiàn)在我們也能利用這個(gè)文件進(jìn)行簽名文件的配置。
- 首先我們將我們的簽名信息配置到local?.properties文件中
# 本地簽名文件部署,主要修改storeFile的路徑值
keyAlias=example
keyPassword=123456
# 簽名文件的路徑
storeFile=/Users/keys/example.jks
storePassword=123456
- 在build.gradle開(kāi)頭加載這個(gè)文件(在 android{} 代碼之前添加)
//加載本地簽名配置
def keystorePropertiesFile = rootProject.file("local.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
- 在 signingConfigs{} 中配置
signingConfigs {
ExampleSign {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}
經(jīng)過(guò)以上3步的配置,?就不用擔(dān)心密碼泄露的一些問(wèn)題了。
動(dòng)態(tài)配置AndroidManifest.xml中的一些值
?在?對(duì)接一些第三方的?API時(shí),?往往需要在「AndroidManifest.xml」文件中進(jìn)行「app_key」「app_secret」等參數(shù)的配置。
?一般按照?第三方API文檔的做法,比如我接入一個(gè)阿里的推送服務(wù),那我需要如下配置:
<meta-data
android:name="com.alibaba.app.appkey"
android:value="exampleappkey"/>
<meta-data
android:name="com.alibaba.app.appsecret"
android:value="exampleappsecret"/>
可是在實(shí)際生產(chǎn)中,我們往往會(huì)發(fā)布一個(gè)beta版用于??發(fā)release版之前的測(cè)試,但是beta版和release版用的不是同一套「app_key」「app_secret」。這個(gè)時(shí)候比較笨的?辦法是,寫(xiě)兩套,然后每次發(fā)布版本的時(shí)候,將其中一套注釋掉。這樣做當(dāng)然是可行的,但是?根據(jù)版本的?不斷迭代,?往往會(huì)忘記對(duì)這一部分進(jìn)行修改或者修改混亂,導(dǎo)致發(fā)布的版本產(chǎn)生混亂。
這個(gè)時(shí)候可以利用gradle結(jié)合AndroidManifest.xml進(jìn)行動(dòng)態(tài)的配置:
<meta-data
android:name="com.alibaba.app.appkey"
android:value="${ali_push_appkey}"/>
<meta-data
android:name="com.alibaba.app.appsecret"
android:value="${ali_push_appsecret}"/>
這里的 ${value} 的寫(xiě)法相當(dāng)于定義了?value這么一個(gè)變量,然后再在build.gradle文件中,找到不同的buildType
buildTypes {
debug {
//開(kāi)啟調(diào)試
debuggable = true
//編譯時(shí)給包名
applicationIdSuffix '.dev'
//給AndroidManifest.xml中對(duì)應(yīng)的變量設(shè)置?值
manifestPlaceholders = [ ali_push_appkey : "2******6"
, ali_push_appsecret: "c1********************31"]
}
//...
}
可以看到manifestPlaceholders可以有很?多對(duì)這樣的值進(jìn)行設(shè)定。經(jīng)過(guò)這樣的設(shè)置,每次?對(duì)不同版本打包時(shí),都會(huì)自動(dòng)找到相應(yīng)的配置,這樣就不需要每次打包都要進(jìn)行修改了。
使用Android Studio切換運(yùn)行不同的版本
通常?使用Android Studio?項(xiàng)目運(yùn)行時(shí),默認(rèn)是使用的debug的配置。根據(jù)上面動(dòng)態(tài)配置來(lái)看,我們是存在beta版或者release版的,有時(shí)候,我們會(huì)面對(duì)需要調(diào)試特定版本來(lái)判定服務(wù)器(服務(wù)器一般會(huì)有測(cè)試環(huán)境和生產(chǎn)環(huán)境的區(qū)分)或者?第三方API在該版本下的配置是否正常運(yùn)行的情形。
可是,我們總不能每次需要測(cè)試生產(chǎn)環(huán)境時(shí),就打一個(gè)包,然后push到設(shè)備上進(jìn)行安裝吧。Android Studio為我們提供了一個(gè)運(yùn)行切換的?方法--?Build Variant。通常,這個(gè)選項(xiàng)會(huì)在?整個(gè)IDE的左下角,也可以通過(guò)「View」-->「Tool Windows」-->「Build Variant」找到。打開(kāi)這個(gè)選項(xiàng)?視圖,可以看到?各個(gè)?Module及當(dāng)前的Build Variant。這個(gè)Build Variant,指的是???gradle中?buildTypes和productFlavors?排列組合所有的版本,比如,配置了2個(gè)?buildTypes和2個(gè)productFlavors,那么會(huì)有2*2=4種組合。切換的方法也很簡(jiǎn)單,只需要點(diǎn)擊選擇你想切換的版本就好:

在選擇版本之后,你?運(yùn)行的版本就是你選擇的這個(gè)版本了。
打包自動(dòng)生成包名
?在辛苦的完成編碼之后,我們打出了一個(gè)APP的安裝包。這個(gè)安裝包的名稱(chēng)為「app-release」你習(xí)慣性的給它重新命名了一番。只發(fā)這么一次版本打一次包的話這么做還好。如果要打很多個(gè)包,你總不能一個(gè)個(gè)命名過(guò)去吧。使用?gradle進(jìn)行配置的話會(huì)很方便,只需要在 android{} 中加入一段代碼就可實(shí)現(xiàn):
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = new File(output.outputFile.parent,
defaultConfig.applicationId
+ (buildType.properties.containsKey("applicationIdSuffix") ? buildType.properties.get("applicationIdSuffix") : "")
+ "_" + defaultConfig.versionName + ".apk");
}
}
在new File()的第二個(gè)參數(shù)中,你可以傳入想要的生成文件名的規(guī)則。上面?這段代碼生成的格式是「包名+build后綴_版本名.apk」其中 applicationIdSuffix 的值會(huì)根據(jù)不同bulidTypes生成后綴。
提供一份較完整的?app/build.gradle文件供參考build.gradle