http://www.reibang.com/p/533240d222d3
Logo寫文章 注冊登錄
首頁
下載App
×
Gradle多渠道打包(動態(tài)設定App名稱,應用圖標阎姥,替換常量直秆,更改包名唆香,變更渠道)
96 Wing_Li 關注
2016.08.16 10:51* 字數 1606 閱讀 10163評論 68喜歡 131贊賞 2
如果本文幫助到你齐帚,本人不勝榮幸叠赐,如果浪費了你的時間偿洁,本人深感抱歉涯肩。
希望用最簡單的大白話來幫助那些像我一樣的人轿钠。如果有什么錯誤,請一定指出病苗,以免誤導大家疗垛、也誤導我。
本文來自:http://www.reibang.com/users/320f9e8f7fc9/latest_articles
感謝您的關注硫朦。
最近有個需求一次要打包9個類型的App贷腕,而且常量和String.xml都有變量。雖然之前也是一直存在變量,但是每次也僅僅只打包一個泽裳。這讓我每次改變量瞒斩,打包9個。要是以后每次都打包9次涮总,我得瘋了胸囱。
根據之前的了解,gradle 應該是可以解決這個問題的妹卿。所以就仔細研究了一番旺矾。
先放一個完整的 多渠道/多環(huán)境 打包的配置,然后再來講解夺克。
實現了:
不同環(huán)境箕宙,不同包名;
不同環(huán)境铺纽,修改不同的 string.xml 資源文件柬帕;
不同環(huán)境,修改指定的常量狡门;
不同環(huán)境陷寝,修改 AndroidManifest.xml 里渠道變量;
不同環(huán)境其馏,引用不同的 module凤跑。
先放一個完整的配置,可以參考:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion '22.0.1'
// 簽名文件
signingConfigs {
config {
keyAlias 'lyl'
keyPassword '123456'
storeFile file('../lyl.jks')
storePassword '123456'
}
}
// 默認配置
defaultConfig {
//applicationId "com.lyl.app"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0.0"
signingConfig signingConfigs.config
multiDexEnabled true
}
// 多渠道/多環(huán)境 的不同配置
productFlavors {
dev {
// 每個環(huán)境包名不同
applicationId "com.lyl.dev"
// 動態(tài)添加 string.xml 字段叛复;
// 注意仔引,這里是添加,在 string.xml 不能有這個字段褐奥,會重名?г拧!撬码!
resValue "string", "app_name", "dev_myapp"
resValue "bool", "isrRank", 'false'
// 動態(tài)修改 常量 字段
buildConfigField "String", "ENVIRONMENT", '"dev"'
// 修改 AndroidManifest.xml 里渠道變量
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "dev"]
}
stage {
applicationId "com.lyl.stage"
resValue "string", "app_name", "stage_myapp"
resValue "bool", "isrRank", 'true'
buildConfigField "String", "ENVIRONMENT", '"stage"'
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "stage"]
}
prod {
applicationId "com.lyl.prod"
resValue "string", "app_name", "myapp"
resValue "bool", "isrRank", 'true'
buildConfigField "String", "ENVIRONMENT", '"prod"'
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "prod"]
}
}
dexOptions {
incremental true
// javaMaxHeapSize "4g"
}
//移除lint檢測的error
lintOptions {
abortOnError false
}
def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
buildTypes {
debug {
signingConfig signingConfigs.config
}
release {
buildConfigField("boolean", "LOG_DEBUG", "false")
minifyEnabled false
zipAlignEnabled true
//移除無用的resource文件
shrinkResources true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.config
// 批量打包
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
//輸出apk名稱為:渠道名版本名時間.apk
def fileName = "${variant.productFlavors[0].name}v${defaultConfig.versionName}${releaseTime()}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
}
}
}
repositories {
mavenCentral()
}
dependencies {
compile 'com.facebook.android:facebook-android-sdk:4.0.0'
compile project(':qrscan')
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'com.google.code.gson:gson:2.3'
compile files('libs/android-async-http-1.4.6.jar')
compile 'com.google.android.gms:play-services:7.5.0'
compile 'com.android.support:support-annotations:22.1.1'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'de.hdodenhof:circleimageview:2.1.0'
}
接下來我們來詳細看看修改特定的字段儿倒。
不同環(huán)境的設置基本都是在 productFlavors 里設置的,
而且在里面你想添加多少個環(huán)境都可以呜笑。
1. 不同環(huán)境夫否,不同包名;
productFlavors {
dev {
applicationId "com.lyl.dev"
}
stage {
applicationId "com.lyl.stage"
}
prod {
applicationId "com.lyl.prod"
}
}
這里注意叫胁,在 defaultConfig 中凰慈,大家應該都是寫了個默認的 applicationId 的。
經測試曹抬,productFlavors 設置的不同環(huán)境包名會覆蓋 defaultConfig 里面的設置溉瓶,
所以我們可以推測急鳄,它執(zhí)行的順序應該是先執(zhí)行默認的,然后在執(zhí)行分渠道的堰酿,如果沖突疾宏,會覆蓋處理,這也很符合邏輯触创。
<br />
2. 不同環(huán)境坎藐,添加 string.xml 資源文件;
利用 resValue 來定義資源的值哼绑,顧名思義 res 底下的內容應該都可以創(chuàng)建岩馍,最后用 R.xxx.xxx 來引用。
如下就根據不同的類型抖韩,添加了不同的 app_name 字段蛀恩,以及定義了 布爾值,可以通過 R.string.app_name 來引用茂浮。
注意双谆,這里是添加,是在 string.xml 里面添加了一個字段app_name席揽,所以在現有的 string.xml 中不能有這個字段顽馋,否則會報錯!;闲摺寸谜!
productFlavors {
dev {
resValue "string", "app_name", "dev_myapp"
resValue "bool", "isrRank", 'false'
}
stage {
resValue "string", "app_name", "stage_myapp"
resValue "bool", "isrRank", 'true'
}
prod {
resValue "string", "app_name", "myapp"
resValue "bool", "isrRank", 'true'
}
}
通過以上我們大概可以推測出 color、dimen 也可以通過類似的方法添加属桦。
<br />
3. 不同環(huán)境熊痴,動態(tài)修改指定的常量;
使用 BuildConfig 的變量地啰。
①定義字段
當我們定義如下字段之后愁拭,編譯后自動生成文件讲逛,在 app/build/source/BuildConfig/dev/com.lyl.dev/BuildConfig 目錄亏吝,
打開這個文件,我們就能看到我們所定義的字段了盏混。
productFlavors {
dev {
buildConfigField "String", "ENVIRONMENT", '"dev"'
}
stage {
buildConfigField "String", "ENVIRONMENT", '"stage"'
}
prod {
buildConfigField "String", "ENVIRONMENT", '"prod"'
}
}
②引用字段
在我們自己的任意的類中蔚鸥,來直接通過 BuildConfig 就可以調用我們定義的字段。
public class Constants {
public static final String ENVIRONMENT = BuildConfig.ENVIRONMENT;
}
注意:這里有個小細節(jié)许赃,看其中第三個參數止喷,是先用了“'”,然后在用了“"”混聊,這種語法在 Java 里可能比較陌生弹谁,但是在很多其他語言中,這種用法是很常見的。
它的意思是 "dev" 這個整體是屬于一個字符串预愤,至于為什么要這么寫沟于,你把單引號去掉,然后去 app/build/source/BuildConfig/dev/com.lyl.dev/BuildConfig 這個文件看一看就知道了植康。
<br />
4. 不同環(huán)境旷太,修改 AndroidManifest.xml 里渠道變量
①在 AndroidManifest.xml 里添加渠道變量
<application
android:icon="${app_icon}"
android:label="@string/app_name"
android:theme="@style/AppTheme">
...
<meta-dataa
android:name="UMENG_CHANNEL"
android:value="${ENVIRONMENT}" />
...
</application>
②在 build.gradle 設置 productFlavors
productFlavors {
dev {
manifestPlaceholders = [ENVIRONMENT: "dev",
app_icon : "@drawable/icon_dev"]
}
stage {
manifestPlaceholders = [ENVIRONMENT: "stage",
app_icon : "@drawable/icon_stage"]
}
prod {
manifestPlaceholders = [ENVIRONMENT: "prod",
app_icon : "@drawable/icon_prod"]
}
}
這樣我們可以在不同環(huán)境使用不同的 key 值。
<br />
5. 不同環(huán)境销睁,引用不同的 module
這個就很強大了供璧,根據不同的環(huán)境,引用對應的 module冻记。
你可以替換大量的圖片睡毒,string,color冗栗,vaule等等吕嘀。
首先,要建立跟渠道對應的 module贞瞒,然后再引用偶房。
引用方式如下:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
// 引用本的項目
devCompile project(':devModule')
stageCompile project(':stageModule')
prodCompile project(':prodModule')
// 也可以分渠道引用網絡的。因為這里都相同军浆,所以地址也就都一樣了
devCompile 'com.roughike:bottom-bar:2.0.2'
stageCompile 'com.roughike:bottom-bar:2.0.2'
prodCompile 'com.roughike:bottom-bar:2.0.2'
}
xxxCompile 代表 各個渠道的名稱棕洋。
然后把需要分渠道的文件,放到不同的 module 里面乒融,把主項目的文件刪掉掰盘。
千萬注意:如果這樣做了,每次需要引用的時候赞季,在各個渠道的 module 里面都必須要放置文件哦愧捕,不然會找不到資源。
通過這種方式可以替換整套素材資源申钩,具體如何使用還得看項目需求次绘。
<br />
<br />
通過以上方式,我們基本可以 通過 gradle 動態(tài)設定應用標題撒遣,應用圖標邮偎,替換常量,設置不同包名义黎,更改渠道等等禾进。
打包編譯
最后,做完所有的配置之后廉涕,然后就是打包操作了泻云。
打包某一個(日常編譯)
因為 buildTypes 里面有兩種艇拍,所以每個渠道都會有兩種模式。
打包所有的宠纯,就是正常打包流程
如圖所示:
圖片來源網絡
圖片來源網絡
圖片來源網絡
圖片來源網絡
<br />
打包完成之后淑倾,然后就可以在我們指定的目錄下,看到我們所生成的apk包征椒。
使用 local.properties 存放私密配置
以上就可以基本實現 gradle 的設置娇哆,但是如果我們要將我們的項目上傳到 Github ,或者要將項目發(fā)送給別人勃救。上面有些私密的東西就會被別人看到碍讨。比如:.jks 文件的密碼。
在項目跟目錄下蒙秒,有個 local.properties 文件勃黍,我們可以使用它來存放一些私密的屬性,然后在 gradle 中讀取晕讲,而 local.properties 文件不需要上傳覆获。
local.properties 文件里設置如下:
sdk.dir=D:\Android\android-sdk
gaodeKey=e348025dd034d1c347dd0345e34802
keyPassword=123456
在 build.gradle 讀取 local.properties 字段信息
// 加載 local.properties 資源
Properties properties = new Properties()
InputStream inputStream = project.rootProject.file('local.properties').newDataInputStream() ;
properties.load( inputStream )
android {
...
// 簽名文件
signingConfigs {
config {
keyAlias 'lyl'
// 獲取 local.properties 字段信息
keyPassword properties.getProperty( 'keyPassword' )
storeFile file('../lyl.jks')
storePassword properties.getProperty( 'keyPassword' )
}
}
...
}
這樣就可以將自己想要隱藏的一些數據隱藏起來。