多渠道打包方法簡介
渠道包就是要在安裝包中新增渠道資訊,也就是channel,對應不同的渠道,例如:小米市場、360市場、應用寶市場等
我們要在安裝包中新增不同的標識,應用在請求網路的時候攜帶渠道資訊,方便後臺做運營統計(這就是新增渠道資訊的用處)。
實現多渠道打包的原理:
一般來講,這個渠道的標識會放在AndroidManifest.xml的Application的一個Metadata中。然後就可以在java中通過API獲取對應的資料了。
目前常用的多渠道打包工具有三種:1、友盟 2、美團 3、360
一、友盟的多渠道實現步驟
1.按照umeng的要求,manifest檔案中需要有
<meta-data
android:name="UMENG_CHANNEL"
android:value="${UMENG_CHANNEL_VALUE}" />
這段配置,value那裡就是wandoujia,360之類的渠道名稱,但是我們在這裡不會去寫渠道名,寫的是一個佔位符,後面gradle編譯的時候會動態的替換掉它。
2,在module(一般也就是app)的build.gradle的android{}中新增如下內容:
productFlavors{
wandoujia{
manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia" ]
}
xiaomi{
manifestPlaceholders=[UMENG_CHANNEL_VALUE: "xiaomi"]
}
}
productFlavors是android節點的一個自節點。你需要打什麼渠道的包,就在這裡按umeng的要求用渠道名給UMENG_CHANNEL_VALUE賦值。
3.優化1:上面只是兩個渠道,如果有幾十個渠道,都這樣寫,重複的東西太多,觀察到每個渠道就是flavor的名稱,所以修改如下:
productFlavors{
wandoujia{
//manifest Placeholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
xiaomi{
//manifestPlaceholders=[UMENG_CHANNEL_VALUE: "xiaomi"]
}
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
3.優化2:上面經過簽名打包後生成的apk的名稱是有預設命名規則的,如:xxx-xiaomi-release.apk 但是我們想包含版本資訊如:xxx-xiaomi-release-1.0.apk,所以最終打包指令碼如下:
productFlavors{
wandoujia{
//manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"]
}
xiaomi{
//manifestPlaceholders=[UMENG_CHANNEL_VALUE: "xiaomi"]
}
}
productFlavors.all { flavor ->
flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
//3.0以下可以這樣配置,3.0的AS版本會報錯
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (outputFile != null && outputFile.name.endsWith('.apk')) {
def fileName = outputFile.name.replace(".apk", "-${defaultConfig.versionName}.apk")
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
如果是這樣配置的話,在3.0會報錯。
升級了AS3.0以後,在專案編譯的時候發現Gradle中報錯了,錯誤如下:
Error:(60, 0) Cannot set the value of read-only property 'outputFile' for ApkVariantOutputImpl_Decorated{apkData=Main{type=MAIN, fullName=xiaomiRelease, filters=[]}} of type com.android.build.gradle.internal.api.ApkVariantOutputImpl.
<a href="openFile:E:\Studio\MyApplication\CodeBook\build.gradle">Open File</a>
解決方法可以用如下配置:
applicationVariants.all { variant -> //批量修改Apk名字
variant.outputs.all { output ->
if (!variant.buildType.isDebuggable()) {
//獲取簽名的名字 variant.signingConfig.name
//要被替換的源字串
// def sourceFile = "-${variant.flavorName}-${variant.buildType.name}"
def sourceFile = ".apk"
//替換的字串 //輸出apk名稱為:渠道名_版本名_時間.apk
// def replaceFile = "${variant.productFlavors[0].name}_V${variant.versionName}_${variant.flavorName}_${variant.buildType.name}"
def replaceFile = "-${variant.versionName}_${releaseTime()}.apk"
outputFileName = output.outputFile.name.replace(sourceFile, replaceFile)
}
}
}
//獲取日期
def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
如果報錯誤如下:
解決方法是:在主app的build.gradle裡面的
defaultConfig {
targetSdkVersion:*
minSdkVersion :*
versionCode:*
versionName :*
//版本名後面新增一句話,意思就是flavor dimension 它的維度就是該版本號,這樣維度就是都是統一的了
flavorDimensions “versionCode”
}
4.獲取渠道
在程式碼中我們可以通過讀取mate-data資訊來獲取渠道,然後新增到請求引數中,獲取方法如下:
private String getChannel() {
try {
PackageManager pm = getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo(getPackageName(), PackageManager.GET_META_DATA);
return appInfo.metaData.getString("UMENG_CHANNEL");
} catch (PackageManager.NameNotFoundException ignored) {
}
return "";
}
5.執行簽名打包:
這時候你去app/build/outputs/apk中就能看到自動打好的渠道包了。