今天運(yùn)營(yíng)同事給我發(fā)了15個(gè)應(yīng)用平臺(tái)對(duì)應(yīng)的apk名。我第一反應(yīng)就是給你個(gè)apk自己改名不就完了...于是心中一萬個(gè)草泥馬奔騰而過。

轉(zhuǎn)念一想,這事兒可能不是那么簡(jiǎn)單,只怪我圖樣圖森破。于是想到了之前看到過多渠道打包,那么就引出了第一個(gè)問題:
一、什么是多渠道
我理解的是:APP發(fā)布到不同的應(yīng)用平臺(tái),監(jiān)測(cè)用戶是從哪個(gè)平臺(tái)安裝的。
二、為什么要多渠道打包
1. 統(tǒng)計(jì)用戶安裝APP來源
知道多渠道的意義就不難理解多渠道打包主要是為了我們統(tǒng)計(jì)分析用的。所以,這樣就很清楚了我最初的想法不是不行,而是不好,對(duì)今后的產(chǎn)品分析沒有任何幫助。
2.批量修改生成的apk文件名
根據(jù)運(yùn)營(yíng)給的命名規(guī)則,如果是一個(gè)個(gè)的右鍵-重命名,那15個(gè)還好,要真是有1000個(gè),運(yùn)營(yíng)同事一定會(huì)拿刀找我的...而多渠道打包所有的都自動(dòng)生成。
3.可更改包名
如果有生成不同包名的需求,通過gradle就可以解決。
4.生成不同應(yīng)用名稱或圖標(biāo)
有的時(shí)候你會(huì)在不同平臺(tái)看到XX-小米版,XX-魅族版等等,或者beta版的圖標(biāo)和正式的不一樣,其實(shí)代碼還是那個(gè)代碼,無非做點(diǎn)小小的改動(dòng),具體實(shí)現(xiàn)我們后面會(huì)說。
這是我所了解到的,可能還有很多我不知道的用途,歡迎大家在下面留言。
三、如何多渠道打包
多渠道打包網(wǎng)上大概有兩種,一個(gè)是通過gradle,另一個(gè)是美團(tuán)介紹的只打一個(gè)包,然后解壓替換文件,兩者比較美團(tuán)的方法要更快,但是今天我們先不做介紹,如果想了解請(qǐng)看《Android多渠道打包飛一般的感覺》。。
1. 在AndroidManifest.xml中添加占位符
一般都是像友盟,騰訊統(tǒng)計(jì)分析SDK中使用的方案,網(wǎng)上友盟的較多,我實(shí)際用的是騰訊分析所以就拿騰訊的來說(其實(shí)都一樣)。
首先,在AndroidManifest.xml的application標(biāo)簽里添加一個(gè)meta-data標(biāo)簽定義MTA_CHANNEL占位符,騰訊分析SDK會(huì)讀取里面的value值傳到后臺(tái),便于我們?nèi)蘸蠓治觥?/p>
<meta-data
android:name="MTA_CHANNEL"
android:value="${MTA_CHANNEL_VALUE}" />
2. 修改app下的build.gradle文件,在android閉包中添加productFlavors屬性配置占位符
apply plugin: 'com.android.application'
android {
compileSdkVersion 21
buildToolsVersion "21.1.2"
defaultConfig {
applicationId "com.aimerd.channel"
minSdkVersion 11
targetSdkVersion 21
versionCode 1
versionName "1.0.0"
multiDexEnabled true
}
buildTypes {
release {
// 不顯示Log
buildConfigField "boolean", "LOG_DEBUG", "false"
//啟用混淆代碼的功能
minifyEnabled true
//壓縮對(duì)齊生成的apk包
zipAlignEnabled true
//指定混淆規(guī)則,需要壓縮優(yōu)化的混淆要把proguard-android.txt換成proguard-android.txt
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
//移除無用的資源文件
shrinkResources true
//啟用multidex的支持
multiDexEnabled true
}
}
productFlavors
baidu {
manifestPlaceholders = [MTA_CHANNEL_VALUE: "baidu"]
}
_91 {
manifestPlaceholders = [MTA_CHANNEL_VALUE: "91"]
}
wandoujia {
manifestPlaceholders = [MTA_CHANNEL_VALUE: "wandoujia"]
}
xiaomi {
manifestPlaceholders = [MTA_CHANNEL_VALUE: "xiaomi"]
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def outputFile = output.outputFile
if (variant.buildType.name.equals('release')) {
//生成apk名字的格式:Channel1.0.0_2016-06-22_baidu.apk
//可自定義自己想要生成的格式
def fileName = "Channel${defaultConfig.versionName}_${releaseTime()}_${variant.productFlavors[0].name}.apk"
output.outputFile = new File(outputFile.parent, fileName)
}
}
}
def releaseTime() {
return new Date().format("yyyy-MM-dd", TimeZone.getTimeZone("UTC"))
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:multidex:1.0.1'
}
如果覺得productFlavors重復(fù)代碼太多,還可以這樣寫:
productFlavors {
baidu {}
_91 {}
wandoujia {}
xiaomi {}
}
//批量處理
productFlavors.all {
flavor -> flavor.manifestPlaceholders = [MTA_CHANNEL_VALUE: name]
}
注意:像91和360這種數(shù)字的是不可以的,我試過"91"雖然可以編譯通過,但打包的時(shí)候會(huì)報(bào)錯(cuò)
Error:Execution failed for task ':app:transformClassesWithRetrolambdaFor91Release'.
> java.lang.NullPointerException (no error message)
具體原因我不清楚,還請(qǐng)知道原因或者知道解決方法的告訴我一下,謝謝!
3. 打包
-
build->Generate Signed APK...
這個(gè)沒什么好說的,很簡(jiǎn)單 -
AS的Terminal輸入:
gradle build
可一次性打包所有渠道,如果想打某個(gè)渠道的包,先輸入:gradle tasks

找到想要打包的渠道,例如紅框標(biāo)出的豌豆莢,在終端輸入:gradle assembleWandoujia,就會(huì)單獨(dú)打包豌豆莢的包了。
注意:有的輸入命令會(huì)提示'gradle'不是內(nèi)部或外部命令,也不是可運(yùn)行的程序或批處理文件。說明沒有配置gradle的環(huán)境變量,配置成功重啟即可。
4.如何更改包名
剛才提到可以根據(jù)不同業(yè)務(wù)需求,需要更改包名,在productFlavors中指定不同的applicationId即可
productFlavors {
baidu {
applicationId="com.aimerd.channel"
manifestPlaceholders = [MTA_CHANNEL_VALUE:"baidu"]
}
}
5.如何生成不同應(yīng)用名稱或圖標(biāo)
我們以baidu為例,在app模塊,src目錄下,新建一個(gè)與main目錄同級(jí)的baidu目錄(這里的名字跟productFlavors中定義的渠道名要一致):

把
values下strings.xml中的"app_name"改成自己想要的應(yīng)用名稱。
<resources>
<string name="app_name">哈哈哈-小米版</string>
</resources>
如果需要換圖標(biāo),只需更換ic_launcher.png文件即可。