Android 多渠道打包

我想叶堆,每當(dāng)發(fā)布新版本時,大家都會對那么多發(fā)布渠道感到頭疼不已驹吮,本文主要介紹三種Android的多渠道打包方式茸时。下面的例子我以 TalkingData 統(tǒng)計(jì)為例子贡定。

1. Gradle 配置 Flavor

1.1 在 AndroidManifest.xml 中配置 meta-data 標(biāo)簽:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="your.package.name">
 <application>
   <meta-data android:name="TD_CHANNEL_ID" android:value="${TD_CHANNEL_VALUE}"/>
  </application> 
</manifest>
1.2 在項(xiàng)目的 build.gradle 里配置 productFlavors,定義渠道號:
productFlavors {
  yyb {}  
  bdsjzs {}  
  wdj {}  
  xiaomi {}  
  sjzs360 {} 
  productFlavors.all {  
      flavor -> flavor.manifestPlaceholders = [TD_CHANNEL_VALUE: name] 
   }
}

上面定義了一些渠道(比如:豌豆莢可都,360缓待,小米等),TD_CHANNEL_VALUE 就是你在 meta-data 標(biāo)簽中配置的值渠牲。
同時旋炒,需要注意的是,你需要在 defaultConfig 中配置一個默認(rèn)的渠道名稱:
manifestPlaceholders = [TD_CHANNEL_VALUE: "default_channel_name"]

該原理就是在打包過程中更換 meta-data 標(biāo)簽中的內(nèi)容签杈。

優(yōu)勢:方便理貨瘫镇,可以根據(jù)自身的需求配置不同的渠道執(zhí)行不同的邏輯(比如:小米渠道有一個獨(dú)立的方法,其他渠道沒有)答姥;
劣勢:打包速度慢(打包時是對每個渠道都進(jìn)行一次完整的打包過程)铣除。

2.第三方打包工具

第三方的打包工具原理跟 Gradle 一樣,也是去修改 AndroidManifest.xml 中的 meta-data 標(biāo)簽的內(nèi)容鹦付,然后執(zhí)行N次打包簽名的操作實(shí)現(xiàn)多渠道打包的尚粘。

優(yōu)勢:簡單方便,幾乎不用自身做什么工作敲长;
劣勢:打包速度過慢郎嫁;

3.美團(tuán)的多渠道打包方案

多渠道打包原理可以參考美團(tuán)Android自動化之旅—生成渠道包這篇文章。Demo 可以查看 快速多渠道打包潘明。

3.1 實(shí)現(xiàn)原理

直接解壓apk行剂,解壓后的根目錄會有一個META-INF
目錄,如下圖所示:



如果在META-INF目錄內(nèi)添加空文件钳降,可以不用重新簽名應(yīng)用。因此腌巾,通過為不同渠道的應(yīng)用添加不同的空文件遂填,可以唯一標(biāo)識一個渠道。

這樣澈蝙,每打一個渠道包只需復(fù)制一個apk吓坚,在 META-INF 中添加一個使用渠道號命名的空文件即可。這種打包方式速度非车朴快礁击,900多個渠道不到一分鐘就能打完。

2.2 多渠道實(shí)現(xiàn)步驟

2.2.1 android 代碼中獲取渠道號
/**
 * 渠道號工具類:解析壓縮包,從中獲取渠道號
 */
public class ChannelUtil {
 private static final String CHANNEL_KEY = "uuchannel";
 private static final String DEFAULT_CHANNEL = "internal";
 private static String mChannel;

 public static String getChannel(Context context) {
     return getChannel(context, DEFAULT_CHANNEL);
 }

 public static String getChannel(Context context, String defaultChannel) {
     if (!TextUtils.isEmpty(mChannel)) {
         return mChannel;
     }
     //從apk中獲取
     mChannel = getChannelFromApk(context, CHANNEL_KEY);
     if (!TextUtils.isEmpty(mChannel)) {
        return mChannel;
     } //全部獲取失敗
   return defaultChannel;
 }
/**
 * 從apk中獲取版本信息
 *
 * @param context
 * @param channelKey
 * @return
 */
 private static String getChannelFromApk(Context context, String channelKey) {
 long startTime = System.currentTimeMillis();
 //從apk包中獲取
 ApplicationInfo appinfo = context.getApplicationInfo();
 String sourceDir = appinfo.sourceDir;
 //默認(rèn)放在meta-inf/里哆窿, 所以需要再拼接一下
 String key = "META-INF/" + channelKey;
 String ret = "";
 ZipFile zipfile = null;
 try {
     zipfile = new ZipFile(sourceDir);
     Enumeration<?> entries = zipfile.entries();
     while (entries.hasMoreElements()) {
         ZipEntry entry = ((ZipEntry) entries.nextElement());
         String entryName = entry.getName();
         if (entryName.startsWith(key)) {
             ret = entryName; break;
         }
      }
 } catch (IOException e) {
       e.printStackTrace();
 } finally {
       if (zipfile != null) {
           try {
                 zipfile.close();
           } catch (IOException e) {
                 e.printStackTrace();
           }
       }
}
String channel = ""; 
if (!TextUtils.isEmpty(ret)) {
     String[] split = ret.split("_");
     if (split != null && split.length >= 2) {
         channel = ret.substring(split[0].length() + 1);
      }
    System.out.println("-----------------------------");
    System.out.println("渠道號:" + channel + "链烈,解壓獲取渠道號耗時:" + (System.currentTimeMillis() - startTime) + "ms"); 
    System.out.println("-----------------------------");
 } else { 
    System.out.println("未解析到相應(yīng)的渠道號,使用默認(rèn)內(nèi)部渠道號");
    channel = DEFAULT_CHANNEL;
 } 
return channel;
}

然后在代碼中初始化調(diào)用TalkingData設(shè)置渠道號:

String channelName = ChannelUtil.getChannel(mContext);
TCAgent.init(mContext,Constants.APP_KEY_TD,channelName );
2.2.2 編寫渠道號文件

修改 info/channel.txt(一行代表一個渠道):

yyb
bdsjzs
wdj
xiaomi
...
2.2.3 編寫 python 腳本

實(shí)現(xiàn)解壓 apk 文件挚躯,遍歷渠道文件 為 META-INF 目錄添加新文件强衡,重新壓縮 apk 文件等邏輯:

# coding=utf-8
import zipfile
import shutil
import os

def delete_file_folder(src):
 '''delete files and folders'''
 if os.path.isfile(src):
   try:
     os.remove(src)
   except:
     pass 
elif os.path.isdir(src):
   for item in os.listdir(src):
     itemsrc=os.path.join(src,item)
     delete_file_folder(itemsrc)
   try:
     os.rmdir(src)
   except: 
      pass

# 創(chuàng)建一個空文件,此文件作為apk包中的空文件 
 src_empty_file = 'info/empty.txt'
 f = open(src_empty_file,'w')
 f.close()

# 在渠道號配置文件中码荔,獲取指定的渠道號
 channelFile = open('./info/channel.txt','r')
 channels = channelFile.readlines()
 channelFile.close()
 print('-'*20,'all channels','-'*20)
 print(channels)print('-'*50)

# 獲取當(dāng)前目錄下所有的apk文件
 src_apks = [];
 for file in os.listdir('.'):
   if os.path.isfile(file):
     extension = os.path.splitext(file)[1][1:]
       if extension in 'apk': 
          src_apks.append(file)

# 遍歷所以的apk文件漩勤,向其壓縮文件中添加渠道號文件
for src_apk in src_apks:
 src_apk_file_name = os.path.basename(src_apk)
 print('current apk name:',src_apk_file_name)
 temp_list = os.path.splitext(src_apk_file_name)
 src_apk_name = temp_list[0]
 src_apk_extension = temp_list[1]
 apk_names = src_apk_name.split('-');
 output_dir = 'outputDir'+'/'
 if os.path.exists(output_dir):
   delete_file_folder(output_dir)
 if not os.path.exists(output_dir):
   os.mkdir(output_dir)

 # 遍歷從文件中獲得的所以渠道號,將其寫入APK包中
 for line in channels:
   target_channel = line.strip()
   target_apk = output_dir + apk_names[0] + "-" + target_channel+"-"+apk_names[2] + src_apk_extension
   shutil.copy(src_apk, target_apk)
   zipped = zipfile.ZipFile(target_apk, 'a', zipfile.ZIP_DEFLATED)
   empty_channel_file = "META-INF/uuchannel_{channel}".format(channel = target_channel)
   zipped.write(src_empty_file, empty_channel_file)
   zipped.close()

print('-'*50)
print('repackaging is over ,total package: ',len(channels))
input('\npackage over...')
2.2.4 打包一個簽名 APK 包

將APK 包放在 python 腳本的同級目錄

2.2.5 執(zhí)行python 腳步缩搅,多渠道打包
python Android.py

最后就會在 同級目錄下生成 outputDir 目錄越败,里面就是各個渠道的 APK 。

優(yōu)勢:打包速度很快硼瓣,很方便究飞;
劣勢:不夠靈活,不能靈活的配置不同的渠道不同的業(yè)務(wù)邏輯巨双;

總結(jié)
三種打包方式中噪猾,各有各的優(yōu)勢,大家在選擇多渠道打包方式的時候可以根據(jù)自身的需求來選擇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末筑累,一起剝皮案震驚了整個濱河市袱蜡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慢宗,老刑警劉巖坪蚁,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異镜沽,居然都是意外死亡敏晤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門缅茉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘴脾,“玉大人,你說我怎么就攤上這事蔬墩∫氪颍” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵拇颅,是天一觀的道長奏司。 經(jīng)常有香客問我,道長樟插,這世上最難降的妖魔是什么韵洋? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任竿刁,我火速辦了婚禮,結(jié)果婚禮上搪缨,老公的妹妹穿的比我還像新娘食拜。我一直安慰自己,他們只是感情好勉吻,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布监婶。 她就那樣靜靜地躺著,像睡著了一般齿桃。 火紅的嫁衣襯著肌膚如雪惑惶。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天短纵,我揣著相機(jī)與錄音带污,去河邊找鬼。 笑死香到,一個胖子當(dāng)著我的面吹牛鱼冀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悠就,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼千绪,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了梗脾?” 一聲冷哼從身側(cè)響起荸型,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炸茧,沒想到半個月后瑞妇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梭冠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年辕狰,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片控漠。...
    茶點(diǎn)故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡蔓倍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出盐捷,到底是詐尸還是另有隱情柬脸,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布毙驯,位于F島的核電站,受9級特大地震影響灾测,放射性物質(zhì)發(fā)生泄漏爆价。R本人自食惡果不足惜垦巴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望铭段。 院中可真熱鬧骤宣,春花似錦、人聲如沸序愚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爸吮。三九已至芬膝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間形娇,已是汗流浹背锰霜。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留桐早,地道東北人癣缅。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像哄酝,于是被迫代替她去往敵國和親友存。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Android多渠道打包 概述 每當(dāng)發(fā)新版本時陶衅,Android客戶端會被分發(fā)到各個應(yīng)用市場屡立,比如豌豆莢,360手機(jī)...
    礪雪凝霜閱讀 2,137評論 2 11
  • 目錄一万哪、Python打包及優(yōu)化(美團(tuán)多渠道打包)二侠驯、Gradle打包三、其他打包方案:修改Zip文件的commen...
    守望君閱讀 5,695評論 4 17
  • 我們做Android用戶級應(yīng)用開發(fā)的時候都要考慮這樣的問題奕巍,目前的應(yīng)用市場有很多吟策,我們的安裝包是通過哪個渠道進(jìn)入用...
    尹star閱讀 8,767評論 11 26
  • 這里主要說一下同時使用 微信資源混淆以及同時使用 walle 打多渠道包 遇到的坑,以及如何解決這個問題的的止。如果只...
    Coralline_xss閱讀 1,208評論 0 1
  • android多渠道打包 1.如何查看apk的簽名信息 1將apk解壓檩坚; 2.找到META-INF 下的.RSA文...
    ping0505閱讀 1,045評論 0 1