Android Gradle 多版本多APK打包,圖標不同,包名不同, 修改apk名字

環境: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")
	}  
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章