環境:Android Studio3.2.1 gradle 3.1.3 gradle-4.4-all.zip
在app的build.gradle中加入(初版)
//配置多版本的apk
productFlavors{
Offline{
applicationId "com.xxxx.xxxx.beta"
manifestPlaceholders = [app_name:"xxxx" ,icon: "@mipmap/ic_launcher_xxxx"]
resValue("string" , "baseUrl","xxxxxxx")
versionCode 2
versionName "1.0.2"
}
Online{
applicationId "com.xxxx.xxxx.online"
manifestPlaceholders = [app_name:"xxxx" ,icon: "@mipmap/ic_launcher_xxxx"]
resValue("string" , "baseUrl","xxxxxxx")
versionCode 1
versionName "1.0.3"
}
注意:
1. 這裏分了Offline和Online兩個版本,applicationId分別配置的是兩個版本的包名,如果沒有配置的話,則默認使用defaultConfig下的包名。
2.manifestPlaceholders裏配置應用名稱或圖標,需要在AndroidManifest.xml的application標籤下配置android:label="${app_name}" android:icon="${icon}"
3.resValue
可以配置一些我們需要的不同的值,第一個參數是變量的類型,第二個參數key,第三個參數是變量的value。具體的使用value=context.getResources().getString(R.string.key)
sync一下,在側邊欄的gradle中就會出現assembleOnline和assembleOffline兩個task,運行這兩個task就能生成相應的包。
每個apk配置不同的名字:
applicationVariants.all {
variant ->
variant.outputs.all {
outputFileName = productFlavors[0].manifestPlaceholders.get("app_name")+".apk"
}
}
或者(productFlavors[0].name開頭不能以數字開頭,所以以數字開頭的apk名稱還是得用上一種方法)
applicationVariants.all {
variant ->
variant.outputs.all {
outputFileName = productFlavors[0].name+".apk"
}
}
出現的問題:
1. 在build.gradle中加入了productFlavors後,報錯Error: All flavors must now belong to a named flavor dimension.
這個錯誤是說:必須保證所有的flavor都屬於同一個維度。
解決辦法:
在defaultConfig{}中添加 flavorDimensions "default"
2. 程序中有百度語音的內容,打包時報錯:Error:Duplicate registration for activity com.baidu.voicerecognition.android.ui.BaiduASRDigitalDialog
Explanation for issues of type "DuplicateAcitivity":
解決辦法:
在build.gradle的 android{}下加入
lintOptions {
checkReleaseBuilds false
abortOnError false
}
打包成功。
3. 打包成功後,安裝apk,報錯:Failure 【INSTALL_PARSE_FAILED_NO_CERTIFICATES: Package /data/app/vmd1519554990.tmp/base.apk has no certificates at entry AndroidManifest.xml】
原因:Android 7.0 引入一項新的應用簽名方案 APK Signature Scheme v2,它能提供更快的應用安裝時間和更多針對未授權 APK 文件更改的保護。在默認情況下,Android Studio 2.2 和 Android Plugin for Gradle 2.2 會使用 APK Signature Scheme v2 和傳統簽名方案來簽署您的應用。
解決辦法:
在build.gradle的release簽名設置下加入v2SigningEnabled false,在工具欄的Build>Generate Signed Bundle or APK中只選中V1然後打包,可以安裝成功。如果在側邊欄的Gradle中使用assembleRelease打包,還是安裝不成功。
(補充:用側邊欄的assembleRelease打包不成功,是因爲在沒有簽名,這樣編譯出來的apk名字爲app-Offline-release-unsigned.apk,需要在productFlavors的Offline或Online中加入signingConfig signingConfigs.release才能打出帶簽名的包app-Offline-release.apk,這樣就可以安裝成功了。)
4. 在AndroidManifest.xml的<application>中修改android:label="${app_name}" android:icon="${icon}",編譯時出錯:Manifest merger failed with multiple errors
(項目中有多個module,每個module中都有AndroidManifest)
解決辦法:
在<application>中加入tools:replace="android:label,android:icon"即可。
productFlavors修改後的完整版:
//配置多版本的apk
productFlavors{
Offline{
applicationId "com.xxxx.xxxx.beta"
manifestPlaceholders = [app_name:"fileOffline" ,icon: "@drawable/ic_launcher"]
resValue("string" , "baseUrl","xxxxxxx")
versionCode 2
versionName "1.0.2"
signingConfig signingConfigs.release
}
Online{
applicationId "com.xxxx.xxxx.online"
manifestPlaceholders = [app_name:"fileOnline" ,icon: "@drawable/ic_launcher_canada"]
resValue("string" , "baseUrl","xxxxxxx")
versionCode 1
versionName "1.0.3"
signingConfig signingConfigs.Onlinerelease//單獨配置簽名
}
使用buildConfigField控制Log開關,替換不同apk 中的圖標:
//設置apk的名字
android.applicationVariants.all { variant ->
variant.outputs.all {
outputFileName = productFlavors[0].manifestPlaceholders.get("apk_name")+".apk"
}
}
//配置多版本的apk
productFlavors{
Offline{
applicationId "com.xxxx.xxxx.beta"
manifestPlaceholders = [app_name:"@string/app_name_on" ,icon: "@drawable/ic_launcher",apk_name:"fileOffline"]
resValue("string" , "baseUrl","xxxxxxx")
versionCode 2
versionName "1.0.2"
signingConfig signingConfigs.release
buildConfigField("int","logo","R.drawable.logo")
buildConfigField("boolean","ENABLE_DEBUG","true")
}
Online{
applicationId "com.xxxx.xxxx.online"
manifestPlaceholders = [app_name:"@string/app_name_on" ,icon: "@drawable/ic_launcher_canada",apk_name:"fileOnline"]
resValue("string" , "baseUrl","xxxxxxx")
versionCode 1
versionName "1.0.3"
signingConfig signingConfigs.Onlinerelease//單獨配置簽名
buildConfigField("int","logo","R.drawable.ic_logo")
buildConfigField("boolean","ENABLE_DEBUG","false")
}
java代碼中調用:
ivLogo.setImageResource(BuildConfig.logo);
注意:
1. apk的名字設定專門在productFlavors的manifestPlaceholders中設置了apk_name的字段,原本用的是app_name的值,但考慮到多語言的狀態,app_name不能設爲固定值,只能設爲@string/app_name,如果apk的名字繼續用app_name的話,編譯出來的apk會生成一個@string的目錄,目錄裏面纔是apk,但apk的名字不是想要的名字而是app_name.apk
2. 要在有多個library的項目中,使用buildConfig,需要在使用到的library以及它上層的library的build.gradle中都配置productFlavors。裏面不一定要有內容,但一定要配置。否則報錯。
比如app裏配置了多版本編譯,app裏包含fileinput這個library,fileinput下又包含了common的library,需要在common裏設置某個需要替換的屬性,那就需要在fileinput裏設置一個空的productFlavors.
fileinput的build.gradle設置:
productFlavors{
Offline{
}
Online{
}
}
common的build.gradle設置:
productFlavors{
Offline{
buildConfigField("int","logo","R.drawable.logo")
buildConfigField("boolean","ENABLE_DEBUG","true")
}
Online{
buildConfigField("int","logo","R.drawable.ic_logo")
buildConfigField("boolean","ENABLE_DEBUG","false")
}
}