美團多渠道打包,美團打包
一.原理
把一個Android應用程式套件當作zip檔案包進行解壓,然後發現在簽名產生的目錄下(META-INF)添加一個空檔案不需要重新簽名。利用這個機制,該檔案的檔案名稱就是渠道名。這種方式不需要重新簽名等步驟,非常高效。
二.方法
已經將美團的打包工具放到了tools下的test01檔案中:
1、將要打包的apk放到PythonTool中
2、在PythonTool/info/channel.txt中寫入需要的渠道,一個渠道佔一行
3、雙擊執行PythonTool/MultiChannelBuildTool.py檔案(需要Python環境),就會產生渠道包
4、擷取渠道資訊:將JavaUtil檔案中的ChannelUtil.java拷貝到工程,調用ChannelUtil.getChannel即可擷取渠道
package com.czt.util;import java.io.IOException;import java.util.Enumeration;import java.util.zip.ZipEntry;import java.util.zip.ZipFile;import android.content.Context;import android.content.SharedPreferences;import android.content.SharedPreferences.Editor;import android.content.pm.ApplicationInfo;import android.content.pm.PackageManager.NameNotFoundException;import android.preference.PreferenceManager;import android.text.TextUtils;public class ChannelUtil {private static final String CHANNEL_KEY = "cztchannel";private static final String CHANNEL_VERSION_KEY = "cztchannel_version";private static String mChannel;/** * 返回市場。 如果擷取失敗返回"" * @param context * @return */public static String getChannel(Context context){return getChannel(context, "");}/** * 返回市場。 如果擷取失敗返回defaultChannel * @param context * @param defaultChannel * @return */public static String getChannel(Context context, String defaultChannel) {//記憶體中擷取if(!TextUtils.isEmpty(mChannel)){return mChannel;}//sp中擷取mChannel = getChannelBySharedPreferences(context);if(!TextUtils.isEmpty(mChannel)){return mChannel;}//從apk中擷取mChannel = getChannelFromApk(context, CHANNEL_KEY);if(!TextUtils.isEmpty(mChannel)){//儲存sp中備用saveChannelBySharedPreferences(context, mChannel);return mChannel;}//全部擷取失敗return defaultChannel; }/** * 從apk中擷取版本資訊 * @param context * @param channelKey * @return */private static String getChannelFromApk(Context context, String channelKey) {//從apk包中擷取 ApplicationInfo appinfo = context.getApplicationInfo(); String sourceDir = appinfo.sourceDir; //預設放在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[] split = ret.split("_"); String channel = ""; if (split != null && split.length >= 2) { channel = ret.substring(split[0].length() + 1); } return channel;}/** * 本地儲存channel & 對應版本號碼 * @param context * @param channel */private static void saveChannelBySharedPreferences(Context context, String channel){SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);Editor editor = sp.edit();editor.putString(CHANNEL_KEY, channel);editor.putInt(CHANNEL_VERSION_KEY, getVersionCode(context));editor.commit();}/** * 從sp中擷取channel * @param context * @return 為空白表示擷取異常、sp中的值已經失效、sp中沒有此值 */private static String getChannelBySharedPreferences(Context context){SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);int currentVersionCode = getVersionCode(context);if(currentVersionCode == -1){//擷取錯誤return "";}int versionCodeSaved = sp.getInt(CHANNEL_VERSION_KEY, -1);if(versionCodeSaved == -1){//本地沒有儲存的channel對應的版本號碼//第一次使用 或者 原先儲存版本號碼異常return "";}if(currentVersionCode != versionCodeSaved){return "";}return sp.getString(CHANNEL_KEY, "");}/** * 從包資訊中擷取版本號碼 * @param context * @return */private static int getVersionCode(Context context){try{return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode;}catch(NameNotFoundException e) {e.printStackTrace();}return -1;}}
工具:http://pan.baidu.com/share/link?shareid=1485267923&uk=4218015263#list/path=%2F
三.優缺點
優點:
這種打包方式速度非常快,900多個渠道不到一分鐘就能打完
缺點:
1、google如果哪天更改打包規則,使得在META-INF中建立空檔案還需要重新打包,這種方式將不可用
2、一些不法的渠道商很容易通過工具修改渠道,如果一個渠道商,通過網路劫持和篡改渠道的組合方式來擷取暴利,對於程式開發人員來說可能會存在著巨大的經濟損失