最近遇到這樣一個需求:一套代碼需要給不同的公司打包,需要修改App icon,ic_launcher,歡迎頁背景圖,登錄按鈕顏色,第三方的不同的key,包名,applicationId等
作為一個懶得不想動的程序員,是不可能去給每個公司打一個包的,所以把精力放到了多渠道打包的想法上。
經過研究最終實現思路是這樣的。
在app的model下創建了幾個不同的文件夾。層級如下:

flavor_xxx為新建的目錄,每個目錄下包括一些資源,資源的相同點(不同apk下不同的東西:比如App icon,背景圖等),它們必須是與app的model下資源的名字是相同的,如下圖:(res->mipmap-hdpi->ic_launcher.phg與app model下的資源路徑是相同的)

values下的strings.xml里的內容是不同的App名稱,公司名稱,電話號碼等

第一步完成,接下來需要在app.build 中配置一下。
android {
compileSdkVersion 25
buildToolsVersion '25.0.0'
signingConfigs {
def alias = 'keystory alias'
def password = 'keystory possword'
def filePath = 'keystore/xxx.jks'
debug {
keyAlias alias
keyPassword password
storeFile file(filePath)
storePassword(password)
}
1{
storeFile file(filePath)
keyAlias alias
keyPassword password
storePassword(password)
}
2{
keyAlias alias
keyPassword password
storeFile file('keystore/xxx.jks')
storePassword(password)
}
3{
keyAlias alias
keyPassword password
storeFile file('keystore/xxx.jks')
storePassword(password)
}
4{
keyAlias alias
keyPassword password
storeFile file('keystore/xxx.jks')
storePassword(password)
}
5{
keyAlias alias
keyPassword password
storeFile file('keystore/xxx.jks')
storePassword(password)
}
}
defaultConfig {
applicationId "com.lesoft.wuye"
minSdkVersion 15
targetSdkVersion 23
versionCode 255
versionName "2.5.5"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
multiDexEnabled true
ndk {
abiFilters "armeabi-v7a"
}
}
productFlavors {
flavor_1 {
applicationId = "com.xxx"
// manifestPlaceholders中寫到的『BAIDU_KEY』
// 這里所設置的變量可以直接使用在『AndroidManifest.xml』中,使用方式為:${package_name}
// android:name="${HOST}.permission.JPUSH_MESSAGE"
// <meta-data
// android:name="com.baidu.lbsapi.API_KEY"
// android:value="${BAIDU_KEY}"/>
manifestPlaceholders = [BAIDU_KEY : "",
JPUSH_APPKEY: "",
UMENG_APPKEY: "", HOST: applicationId]
}
// flavor_2 {
// applicationId = "com.xxx"
// manifestPlaceholders = [BAIDU_KEY : "百度key",
// JPUSH_APPKEY: "極光推送key",
// UMENG_APPKEY: "友盟", HOST: applicationId]
// }
// flavor_3 {
// applicationId = "com.xxx"
// manifestPlaceholders = [BAIDU_KEY : "",
// JPUSH_APPKEY: "",
// UMENG_APPKEY: "", HOST: applicationId]
//
// }
//
// flavor_4 {
// applicationId = "com.xxx"
// manifestPlaceholders = [BAIDU_KEY : "",
// JPUSH_APPKEY: "",
// UMENG_APPKEY: "", HOST: applicationId]
// }
//
// flavor_5 {
// applicationId = "com.xxx"
// manifestPlaceholders = [BAIDU_KEY : "",
// JPUSH_APPKEY: "",
// UMENG_APPKEY: "", HOST: applicationId]
// }
}
buildTypes {
debug {
// 如果 debug 包需要測試諸如微信、地圖等第三方 sdk ,則可以指定 debug 包使用 release 包的簽名
//debug 並不能設置多個簽名
debuggable true
minifyEnabled false
productFlavors.flavor_1.signingConfig signingConfigs.1
// //為已經存在的applicationId添加后綴
// applicationIdSuffix ".debug"
// // 為版本名添加后綴
// versionNameSuffix "-debug"
}
release {
minifyEnabled false
// shrinkResouse ture 移除無用資源
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// productFlavors.flavor_1.signingConfig signingConfigs.1
// productFlavors.flavor_2.signingConfig signingConfigs.2
// productFlavors.flavor_3.signingConfig signingConfigs.3
// productFlavors.flavor_4.signingConfig signingConfigs.4
// productFlavors.flavor_5.signingConfig signingConfigs.5
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)
}
}
}
}
}
}
最后在AndroidManifest.xml 中加入 <application
android:replace="icon,lable,theme">
如果沒有會在編譯中報錯,錯誤如下:


到現在多渠道打包就已經配置完成,使用方法:點assembleRelease即可打包,運行速度有點慢。

踩過的坑:在rearelease{
shrinkResources true //移除無用資源
}
如果存在這個配置,會導致把我們的無用資源給移除,會導致編譯不通過。
在java代碼中需要改的內容是不能在我們flaflavor_xxx的文件下修改的,需要我們在代碼中根據App name或者package name來自動判斷。如修改一個登陸按鈕的顏色:
/**
* 根據App的名字,如果是xxx公司:登錄按鈕顏色要變
*/
private void setLoginBtnColor(){
String app_name = getResources().getString(R.string.app_name);
if (app_name.equals("app name")) {
mLoginBtn.setBackgroundColor(getResources().getColor(R.color.gaodi_login_btn));
ivPhoto.setImageResource(R.mipmap.ic_launcher_trans);
}
}
