1剿干、為什么要進行多渠道打包蜂怎?
安卓應(yīng)用商店(一個商店也叫做一個渠道,如豌豆莢置尔,360手機助手杠步,應(yīng)用寶)眾多,大大小小幾百個榜轿,每當我們發(fā)新版本時幽歼,需要將Android客戶端分發(fā)到各個應(yīng)用市場,為了統(tǒng)計這些市場的效果(下載量差导、活躍數(shù)等),需要有一種方法來唯一標識它們猪勇,所以才有了多渠道打包设褐。
2、如何統(tǒng)計各個渠道的下載量、活躍數(shù)助析?
現(xiàn)在有比較成熟的第三方應(yīng)用幫我們實現(xiàn)統(tǒng)計功能(比如友盟)犀被,統(tǒng)計的本質(zhì)就是收集用戶信息傳輸?shù)胶笈_,后臺生成報表外冀,幫助我們跟蹤分析并完善app寡键。通過android系統(tǒng)的方法已經(jīng)可以獲取到引用版本號,版本名稱雪隧,系統(tǒng)版本西轩,機型等各種信息,唯獨應(yīng)用商店(渠道)的信息我們是沒有辦法從系統(tǒng)獲取到的脑沿,所以我們就人為的在apk里面添加渠道信息(其實就用一個字段進行標識藕畔,如wandoujia
,360
庄拇,yingyongbao
)注服,我們只要把這些信息打包到apk文件并將信息傳輸?shù)胶笈_,后臺根據(jù)這個標識措近,可以統(tǒng)計各個渠道的下載量了溶弟。
多渠道打包只需要關(guān)注兩件事情:
- 將渠道信息寫入apk文件
- 將apk中的渠道信息傳輸?shù)浇y(tǒng)計后臺
3、使用Gradle進行多渠道批量打包**
-
通常都是在在
AndroidManifest.xml
中加入渠道區(qū)分標識寫入一個meta標簽:<meta-data android:name="channel" android:value="${channel}" />
-
在app目錄下在build.gradle中配置productFlavors添加如下代碼:
productFlavors { qihu360 {} // 360手機助手 yingyongbao {} // 騰訊應(yīng)用寶 wandoujia {} // 豌豆莢 baidu {} // 百度手機助手 miui {} // 小米 flyme {} // 魅族 lenovo {} // 聯(lián)想-樂商店 oppo {} // Oppo-可可軟件商店 huawei {} // 華為 vivo {} // vivo hiapk {} // 安卓市場 sj91 {} // 91手機助手 sogou {} // 搜狗手機市場 sohu {} // 搜狐應(yīng)用中心 taobao {} // 淘寶手機助手 gfan {} // 機鋒 appchina {} // 應(yīng)用匯 mumayi {} // 木螞蟻 wangyi163 {} // 網(wǎng)易應(yīng)用 nduoa {} // N多市場 mm10086 {} // MM商城-中國移動 wostore {} // WO商店 youyi {} // 優(yōu)異 uc {} // UC+開發(fā)平臺 anzhi {} // 安智市場 google {} // google play amazon {} // 亞馬遜 } productFlavors.all { flavor -> flavor.manifestPlaceholders = [channel: name] }
AndroidStudio的
Build -> Generate signed apk
打簽名包時即可選擇設(shè)置渠道:
在代碼中獲取渠道信息:
public static String getFlavorChannel(Context context) {
try {
PackageManager pm = context.getPackageManager();
ApplicationInfo appInfo = pm.getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA);
return appInfo.metaData.getString("channel");
} catch (PackageManager.NameNotFoundException ignored) {
}
return "";
}
- 在android studio中測試不同渠道的apk瞭郑。
4.APP定制渠道包(馬甲包)
在App的開發(fā)過程中辜御,經(jīng)常會遇到產(chǎn)品或者運營的同事提出要制作馬甲包的需求;馬甲包簡單來說就是原APP的小號凰浮,與原APP包除了包名我抠,應(yīng)用名稱、圖標等給用戶加以區(qū)分的東西袜茧,其他功能基本不變亦或者只采用原App的部分功能的APP包菜拓。
-
ApplicationId,版本號
Android 應(yīng)用都有自己的包名笛厦。包名是設(shè)備上每個應(yīng)用程序的唯一標識纳鼎,同樣也是在各個下載平臺的唯一標識。就是說裳凸,假如你已經(jīng)使用某個包名來發(fā)布應(yīng)用贱鄙,就不能再去改變應(yīng)用的包名,因為這樣做會導(dǎo)致你的應(yīng)用被視為一個全新的應(yīng)用姨谷,你現(xiàn)有的用戶也不會收到應(yīng)用的更新通知逗宁。
隨著渠道越來越多,不同渠道對應(yīng)用的要求也不盡相同梦湘。有時候我們需要發(fā)布不同的版本瞎颗,例如 pro件甥,hd 版本,支持用戶可以下載安裝不同的版本哼拔。那么我們需要設(shè)置不同的ApplicationId和對應(yīng)的版本號引有, 同時要與 PackageName 解耦合。
- 代碼中引用的 R 類要保持不變倦逐;
- 在構(gòu)建不同版本的應(yīng)用時譬正,對應(yīng)的(引用了 R 的) .java 源文件也不能改動。
那么我們只需要在productFlavors
對應(yīng)的渠道中指定applicationId
和versionCode
檬姥,versionName
曾我,例我們指定GooglePlay的applicationId
:
productFlavors {
GooglePlay {
//指定這個渠道的版本號
versionCode 2
versionName "1.2"
//指定區(qū)別于其他渠道的 applicationId
applicationId "com.liujc.androidtools.hd"
}
yingyongbao {} // 騰訊應(yīng)用寶
wandoujia {} // 豌豆莢
baidu {} // 百度手機助手
miui {} // 小米
//其他...
}
-
BuildConfig
Gradle會在generateSources階段為flavor生成一個BuildConfig.java
文件。BuildConfig類默認提供了一些常量字段穿铆,比如應(yīng)用的版本名(VERSION_NAME
)您单,應(yīng)用的包名(PACKAGE_NAME
)等。更強大的是荞雏,開發(fā)者還可以添加自定義的一些字段虐秦。下面的示例假設(shè)debug
版開啟LOG功能,使用debug的api凤优,而release
版則使用不開啟LOG和使用release時的api:
那么代碼中就可以使用 BuildConfig.LOG_DEBUG 和 BuildConfig.API_HOST 了筑辨。buildTypes { debug { // debug模式下悦陋,顯示log buildConfigField("boolean", "LOG_DEBUG", "true") buildConfigField ("String", "API_HOST", "\"http://api.test.com\"")//debug API Host } release { // release模式下,不顯示log buildConfigField("boolean", "LOG_DEBUG", "false") buildConfigField("String", "API_HOST", "\"http://api.release.com\"")//release API Host } }
備注: 這里簡單介紹下buildConfigField
方法俺驶,可以發(fā)現(xiàn)其有三個參數(shù):/** * Adds a new field to the generated BuildConfig class. * * <p>The field is generated as: {@code <type> <name> = <value>;} * * <p>This means each of these must have valid Java content. If the type is a String, then the * value should include quotes. * * @param type the type of the field * @param name the name of the field * @param value the value of the field */ public void buildConfigField( @NonNull String type, @NonNull String name, @NonNull String value)
String type 要創(chuàng)建的字段類型 如上面的String與boolean String name 要創(chuàng)建的字段名 如上面的API_HOST與LOG_DEBUG String value 創(chuàng)建此字段的值 如上面的"\"http://api.release.com\""與"true" 轉(zhuǎn)義字符
楚昭。
-
控制是否自動更新
一般應(yīng)用在啟動時都會默認檢查客戶端是否有更新栖袋,如果有更新就會提示用戶下載。但是有些渠道和應(yīng)用市場不允許這種默認行為抚太,所以在適配這些渠道時需要禁止自動更新功能塘幅。
解決的思路是提供一個配置字段,應(yīng)用啟動的時候檢查該字段的值以決定是否開啟自動更新功能尿贫。使用flavor可以完美的解決這類問題电媳。甚至可以在productFlavors對應(yīng)的渠道號進行區(qū)別,例如豌豆莢版默認禁止版本自動更新:android { defaultConfig { buildConfigField "boolean", "AUTO_UPDATES", "true" } productFlavors { wandoujia { buildConfigField "boolean", "AUTO_UPDATES", "false" } } }
多渠道資源文件定制
客戶端經(jīng)常會和一些應(yīng)用分發(fā)市場合作庆亡,需要在應(yīng)用的啟動界面中加上第三方市場的Logo匾乓,類似這類適配形式還有很多。通常對于不同渠道又谋,我們會區(qū)別不同的資源拼缝。例如我們一款應(yīng)用需要在360發(fā)布括享,而應(yīng)用圖標和歡迎界面要一個360標志的圖或者應(yīng)用名稱和其他渠道不同,那么這個時候就需要按渠道打包對應(yīng)的應(yīng)用圖標和歡迎圖片以及應(yīng)用名稱了了珍促。
Gradle在構(gòu)建應(yīng)用時,會優(yōu)先使用flavor所屬dataSet中的同名資源剩愧。所以猪叙,在flavor的dataSet中添加同名的字符串資源,以覆蓋默認的資源仁卷。上面我們已經(jīng)有針對360的渠道了穴翩,就是qihu360,我們只需要在app/src/目錄下添加渠道對應(yīng)的文件夾qihu360锦积,然后覆蓋對應(yīng)要覆蓋的內(nèi)容芒帕。下面是定制應(yīng)用圖標的步驟:
- 添加qihu360文件夾,那么在
app/src/
目錄下面就有 main , androidTest , qihu360,test這四個文件夾了丰介。main 目錄是通用正常渠道包目錄背蟆,qihu360是我們需要定制資源的渠道包目錄。如下圖:
- 并添加如下應(yīng)用名字符串資源
src/qihu360/res/values/strings.xml
:
默認的應(yīng)用名字符串資源如下(<resources> <string name="app_name">360MultiChannelBuild</string> </resources>
src/main/res/values/strings.xml
):
最后運行360版本的app即應(yīng)用名稱顯示成360MultiChannelBuild哮幢。<resources> <string name="app_name">MultiChannelBuild</string> </resources>
通過以上例也可以定制其他資源带膀,包括drawable
,styles.xml
甚至AndroidManifest.xml
也都是可以的橙垢。即可實現(xiàn)不同渠道不同的應(yīng)用顯示垛叨。
-
使用第三方SDK
某些渠道會要求客戶端嵌入第三方SDK來滿足特定的適配需求。問題的難點在于如何只為特定的渠道添加SDK柜某,其他渠道不引入該SDK嗽元。使用flavor可以很好的解決這個問題,下面以為qihu360
flavor引入com.qihoo360.union.sdk:union:1.0
SDK為例進行說明:
android {
productFlavors {
qihu360 {
}
}
}
...
dependencies {
//參與編譯但不參與打包
provided 'com.qihoo360.union.sdk:union:1.0'
//指定qihu360這個渠道可以打包這個庫
qihu360Compile 'com.qihoo360.union.sdk:union:1.0'
}
上例添加了名為qihu360的flavor喂击,并且指定編譯和運行時都依賴com.qihoo360.union.sdk:union:1.0
剂癌。而其他渠道只是在構(gòu)建的時候依賴該SDK,打包的時候并不會添加它惭等。
接下來珍手,需要在代碼中使用反射技術(shù)判斷應(yīng)用程序是否添加了該SDK,從而決定是否要顯示360 SDK提供的精品應(yīng)用辞做。部分代碼如下:
class MyActivity extends Activity {
private boolean useQihuSdk;
@override
public void onCreate(Bundle savedInstanceState) {
try {
Class.forName("com.qihoo360.union.sdk.UnionManager");
useQihuSdk = true;
} catch (ClassNotFoundException ignored) {
}
}
}
最后打包運行即可生成包含360精品應(yīng)用模塊的渠道包了琳要。