1. 程式人生 > >Android多渠道打包方案的實踐與優化

Android多渠道打包方案的實踐與優化

目前使用過的多渠道打包方式有兩種 ,一種是通過gradle打包,還有一種是美團的多渠道打包方案具體詳情見這裡

1、Gradle打包

1.1、在Androidmanifest.xml中新增

        <meta-data
            android:name="UMENG_CHANNEL"
            android:value="${UMENG_CHANNEL_VALUE}" />

1.2、在build.gradle中新增

     productFlavors {
         // 百度
         baidu {
             manifestPlaceholders = [UMENG_CHANNEL_VALUE: "baidu"
] } //魅族 meizu { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "meizu"] } //搜狗 sougou { manifestPlaceholders = [UMENG_CHANNEL_VALUE: "sougou"] }

這時候在Android Studio右側的Gradle project工作區中就可以看到在這裡配置的多個渠道了,雙擊相應的選項就能build出相應的渠道包了,assembleRelease是build出所有渠道的Release包,這裡只使用了少量的渠道作為示例。這裡的UMENG_CHANNEL_VALUE需要和meta-data中的value一致才能替換。
這裡寫圖片描述

1.3、獲取渠道號

    public static String getApplicationMetadata(Context context,
                                                String metaDataKey) {
        ApplicationInfo info = null;
        try {
            PackageManager pm = context.getPackageManager();

            info = pm.getApplicationInfo(context.getPackageName(),
                    PackageManager.GET_META_DATA);

            return
String.valueOf(info.metaData.get(metaDataKey)); } catch (Exception e) { e.printStackTrace(); } return null; }

這裡的metaDataKey自然就是UMENG_CHANNEL了

2、美團多渠道打包方案

2.1、環境配置

由於美團的多渠道打包方案需要依靠指令碼來實現,這裡我用的是python,經試驗指令碼檔案在windows 下用3.6版本和mac下用2.7版本都能完美執行。並且需要安裝openpyxl模組。

2.2、檔案說明

打包的檔案有channels.xlsx 和 package.py
channels.xlsx是一個excel表格裡面第一列是渠道號的id,第二列是渠道號的名稱,第三列是渠道名稱的備註(非必須)

這裡寫圖片描述

package.py 是一個python指令碼檔案

import datetime
import zipfile
import shutil
import sys
import os
from openpyxl import load_workbook

starttime = datetime.datetime.now()
apk_path = sys.argv[1]
print(os.path.abspath(apk_path))
file_path=os.path.dirname(os.path.abspath(apk_path))+os.path.sep
out_path =file_path+'output'

if not os.path.exists(out_path):
    os.makedirs(out_path)
else:
    shutil.rmtree(out_path,True)
    os.makedirs(out_path)

name = os.path.basename(apk_path)
origin_apk_name = os.path.splitext(name)[0]
wb=load_workbook(filename=file_path+'channels.xlsx',read_only=True)
sheets = wb.get_sheet_names()
ws=wb[sheets[0]]

for row in ws.rows:
    idStr=str(row[0].value)
    channelStr=str(row[1].value)
    channel_apk_name='{}-{}-{}.apk'.format(idStr,channelStr,origin_apk_name)
    channel_apk_path=os.path.join(out_path,channel_apk_name)
    shutil.copy2(apk_path,channel_apk_path)
    zipped=zipfile.ZipFile(channel_apk_path,'a',zipfile.ZIP_DEFLATED)
    empty_channel_file="META-INF/channel_{}_{}".format(idStr,channelStr)
    zipped.writestr(empty_channel_file, '')
    zipped.close()
    print(idStr+":"+channelStr)

endtime=datetime.datetime.now()
between=(endtime-starttime).microseconds/1024
print('time:%d ms' % between)

2.3、執行指令碼

在命令列中輸入 python package.py xxxx.apk
如果Python命令是在package.py所在目錄下用上面的方式輸入,也可以將package.py和apk檔案直接拖入命令視窗中執行,然後就會在apk所在路徑下生成一個output資料夾裡面有所有生成的渠道包。

2.4、獲取渠道號

這時候用Android Studio 開啟新生成的渠道包,Build——>Analyze Apk選中剛才生成的apk開啟META-INF資料夾可以看到這樣的的一個檔案channel_{id}_{name}的檔案,由於它是一個空檔案,所以可以看到它的體積大小為0B。因此新的渠道包也不會需要重新簽名。

這裡寫圖片描述

程式碼中獲取渠道號

    public static String[] getChannel() {
        ApplicationInfo appinfo = App.getInstance().getContext().getApplicationInfo();
        String sourceDir = appinfo.sourceDir;
        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("META-INF/channel")) {
                    ret = entryName;
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (zipfile != null) {
                try {
                    zipfile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        String[] split = ret.split("_");
        if (split != null && split.length >= 2) {
            for (int i = 0; i < split.length; i++) {
                Logger.e(split[i]);
            }
            return split;

        } else {
            return null;
        }
    }

在這裡獲取到的split資訊應該是[“META-INF/channel”,”18”,”uc”],然後獲取自己需要的資訊就好了

3、兩種打包方式對比

打包方式 特點 優點 缺點 適用場景
gradle productFlavors下配置渠道號,assembleRelease一鍵執行打完所有包 配置簡單 每個包都需要重新build,耗時較長 渠道包較少時
美團多渠道打包方案 通過指令碼檔案在apk的META-INF目錄下生成包含渠道號的空檔案 打包速度快 需要依賴外部的指令碼檔案來實現,修改指令碼有學習成本 渠道包比較多時

4、遇到的其他問題

4.1、umeng的渠道號設定

這種方式不會替換meta-data中的資訊,好在umeng提供了在程式碼中設定channel的方法,詳情見這裡

4.2、注意事項

渠道包的位置一定要和channel的配置檔案在同一目錄下

4.3、打包方式優化

這種方式還是需要自己輸入命令列,稍後打算寫一份.bat檔案讓他雙擊執行。

打包指令碼下載

轉載請註明出處:http://blog.csdn.net/zhong1113/article/details/54094770