productFlavors的用處
1.增加包環(huán)境種類
項(xiàng)目里面常常會(huì)用到很多環(huán)境,拿打包來(lái)說(shuō),一個(gè)項(xiàng)目,從開發(fā)到正式上線,可能要經(jīng)過(guò)很多階段.那么,在這些不同的階段內(nèi),要驗(yàn)證Android應(yīng)用,不可避免的需要打出很多不同環(huán)境的包,例如開發(fā)環(huán)境(dev),測(cè)試環(huán)境(tes),正式環(huán)境(pro).
在這么多的環(huán)境中,假如需要配合測(cè)試API接口,那么不同環(huán)境項(xiàng)目中的API地址會(huì)一樣嗎,肯定不會(huì)吧,如果在需要有其他的一些配置信息,每個(gè)環(huán)境不一樣,那每次打包要去手動(dòng)修改會(huì)很麻煩.這時(shí)候可以用到productFlavors來(lái)試試:
廢話不多說(shuō),先看看項(xiàng)目建成后,在打包時(shí),你會(huì)有多少的選擇:

都是這樣的,應(yīng)該沒(méi)有異議吧....
那么開始慢慢的增加:
1.在app下的build.gradle里面增加這些代碼:
flavorDimensions "mode"http://這里起什么名字都可以,姑且叫 mode吧
productFlavors{
dev{
dimension "mode"
}
tes{
dimension "mode"
}
pro{
dimension "mode"
}
}
看看發(fā)生了什么:

當(dāng)然,相應(yīng)的打包時(shí)的項(xiàng)目選擇也多了起來(lái):

2.添加一些項(xiàng)目常用配置
現(xiàn)在有那么多環(huán)境的包,有啥用?在每個(gè)不同環(huán)境的包里面配置自己需要的東西啊,比如咱們剛才說(shuō)的,每個(gè)環(huán)境的API地址不一樣,怎么;再比如說(shuō),我開發(fā)環(huán)境需要支持自動(dòng)升級(jí),可我正式環(huán)境不想支持了,需要一個(gè)常量做一個(gè)標(biāo)示,怎么辦?盤他就得了!
flavorDimensions "mode"
productFlavors{
dev{
dimension "mode"
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/dev/"')
buildConfigField("boolean", "UPDATE", "true")//那里需要用了,直接BuildConfig.UPDATE就取出來(lái)了,就這么簡(jiǎn)單
}
tes{
dimension "mode"
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/tes/"')
buildConfigField("boolean", "UPDATE", "false")
}
pro{
dimension "mode"
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/pro/"')
buildConfigField("boolean", "UPDATE", "false")
}
}
把格式說(shuō)一下 buildConfigField("常量類型","常量名稱","常量值")
這樣會(huì)在項(xiàng)目構(gòu)建的是后,在項(xiàng)目的Build.config中生成項(xiàng)目的配置文件,類似這樣:

你選擇的是開發(fā)環(huán)境,那么這里面的配置就是dev環(huán)境下的地址,同理tes,pro環(huán)境一樣.
3.可以用來(lái)配置清單文件里面的值
這個(gè)最常用的就是在清單文件里面需要配置app_key,app_id的時(shí)候了,很多的三方SDK是需要配置這個(gè)東西的,比如某盟,某語(yǔ)音等等一大堆,這個(gè)時(shí)候,開發(fā)是用的key和id肯定不能正是環(huán)境也用,或者給不同的客戶打不同的包,用的也不能一樣,這是后,需要進(jìn)行一些配置:
在清單文件(AndroidManifest)里面,application節(jié)點(diǎn)下這樣配置:
<meta-data
android:name="app_id"
android:value="${app_id_value}" />//占位符
<meta-data
android:name="app_key"
android:value="${app_key_value}" />
在剛剛的productFlavors下面這樣配置:
productFlavors{
dev{
dimension "mode"
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/dev/"')
manifestPlaceholders = [app_id_value : "123456"
,app_key_value : "654321"]
}
tes{
dimension "mode"
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/tes/"')
manifestPlaceholders = [app_id_value : "111111"
,app_key_value : "222222"] //替換兩個(gè)以上的用逗號(hào)隔開
}
pro{
dimension "mode"
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/pro/"')
manifestPlaceholders = [app_id_value : "223344"
,app_key_value : "556677"]
}
}
除了設(shè)置這些之外,還可以給不同環(huán)境配置不同的包名,版本號(hào),版本名稱,并且在選擇不同環(huán)境運(yùn)行或者打包的時(shí)候,顯示的包名是不一樣的,這個(gè)我驗(yàn)證過(guò)了,上個(gè)全的:
flavorDimensions "mode"
productFlavors{
dev{
dimension "mode"
applicationId "com.liucl.dev.app"
versionName "1.0.0"
versionCode 10
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/dev/"')
buildConfigField("boolean", "UPDATE", "true")
manifestPlaceholders = [app_id_value : "123456"
,app_key_value : "654321"]
}
tes{
dimension "mode"
applicationId "com.liucl.tes.app"
versionName "2.0.0"
versionCode 20
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/tes/"')
buildConfigField("boolean", "UPDATE", "true")
manifestPlaceholders = [app_id_value : "111111"
,app_key_value : "222222"]
}
pro{
dimension "mode"
versionName "3.0.0"
versionCode 30
applicationId "com.liucl.pro.app"
buildConfigField("String", "HTTP_BASE", '"https://www.xxx.com/pro/"')
buildConfigField("boolean", "UPDATE", "false")
manifestPlaceholders = [app_id_value : "223344"
,app_key_value : "556677"]
}
}
4.根據(jù)不同的productFlavors,引入不同的依賴包:
舉個(gè)例子:我dev環(huán)境想用劉氏財(cái)團(tuán)的 發(fā)財(cái)_aar 包 ; tes環(huán)境用 長(zhǎng)壽_aar 包 ; 正式環(huán)境用 喜慶_aar包,改咋辦?
1.新加節(jié)點(diǎn)configurations,
2.在dependencies中添加以下配置
configurations {
dev
tes
pro
}
def date = "20201222"http://aar的日期
def ver = "v1.0.2_" //aar的版本
dependencies {
.....
devImplementation(name: '發(fā)財(cái)_' + ver + date, ext: 'aar')
tesImplementation(name: '長(zhǎng)壽_' + ver + date, ext: 'aar')
proImplementation(name: '喜慶_' + ver + date, ext: 'aar')
.......
}
5.再說(shuō)說(shuō)打包吧
在build.gradle里面增加一些配置,可以使打出來(lái)的包有自己的命名規(guī)則,比如什么名稱,版本是多少,打包時(shí)間是什么時(shí)候,這樣的配置可以避免很多時(shí)候,打包多了,不知道那個(gè)包是什么時(shí)候打的,這很讓人頭大,上代碼配置:
buildTypes {//在android節(jié)點(diǎn)下
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
android.applicationVariants.all {
variant ->
if (variant.buildType.name == 'release') {
variant.outputs.all {
outputFileName = "LCL_v${defaultConfig.versionName}_${variant.productFlavors[0].name}_${variant.buildType.name}_${releaseTime()}.apk"
}
}
}
signingConfig signingConfigs.release
}
}
另外需要配置這些:
signingConfigs { //在Android節(jié)點(diǎn)下
release {
keyAlias 'liucl'
keyPassword 'liucl3889@.'
storeFile file('./liucl.jks')
storePassword 'liucl3889@.'
}
}
再加這個(gè):
static def releaseTime() { //獲取時(shí)間的方法,在Android節(jié)點(diǎn)外,另外的節(jié)點(diǎn)
return new Date().format("yyyyMMddHHmm", TimeZone.getDefault())
}
ok就這些了,如有錯(cuò)誤,歡迎指出,反正我也不會(huì)改,你能拿我怎么樣.....
