1. 程式人生 > >多渠道打包方法簡介

多渠道打包方法簡介

渠道包就是要在安裝包中新增渠道資訊,也就是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中就能看到自動打好的渠道包了。