• (转载)Android多渠道打包飞一般的感觉


    上一篇《Android多渠道打包没你想的那么复杂》中说了用gradle方法进行多渠道打包,这个方法简单也好理解,但是速度不敢恭维。今天跟大家说说用Python的方法来打包,那感觉...

     
    1437707079_452x562.png

    1.添加渠道

    info目录下的channel.txt中添加要上传的渠道名。一定以回车分隔,就是每个名字占一行。

     
     

    2.Python脚本

    其实方法来自于美团。就是将apk解压,在META-INF目录下添加一个以渠道名channel_渠道名为前缀的空文件。如图:

     
     

    创建一个名为empty.txt的空文件
    # 空文件 便于写入此空文件到apk包中作为channel文件
    src_empty_file = 'info/empty.txt'
    # 创建一个空文件(不存在则创建)
    f = open(src_empty_file, 'w')
    f.close()
    

    获取目录下所有的apk(所以,可以同时多个apk打包哦~)

    src_apks = []
    # python3 : os.listdir()即可,这里使用兼容Python2的os.listdir('.')
    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)
    

    获取渠道列表

    channel_file = 'info/channel.txt'
    f = open(channel_file)
    lines = f.readlines()
    f.close()
    

    解压,读写等操作

    for src_apk in src_apks:
        # file name (with extension)
        src_apk_file_name = os.path.basename(src_apk)
        # 分割文件名与后缀
        temp_list = os.path.splitext(src_apk_file_name)
        # name without extension
        src_apk_name = temp_list[0]
        # 后缀名,包含.   例如: ".apk "
        src_apk_extension = temp_list[1]
    
        # 创建生成目录,与文件名相关
        output_dir = 'output_' + src_apk_name + '/'
        # 目录不存在则创建
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)
    
        # 创建临时目录,与文件名相关
        temp_dir = 'temp' + src_apk_name + '/'
        # 目录不存在则创建
        if not os.path.exists(temp_dir):
            os.mkdir(temp_dir)
    
    
        out_temp_apk = temp_dir + src_apk_name+'temp'+src_apk_extension;
        #copy一份没有渠道信息的apk
        zin = zipfile.ZipFile (src_apk, 'a', zipfile.ZIP_DEFLATED)
        zout = zipfile.ZipFile (out_temp_apk, 'w')
        for item in zin.infolist():
            buffer = zin.read(item.filename)
            if (item.filename[0:16:] != 'META-INF/channel'):
                zout.writestr(item, buffer)
        zout.close()
        zin.close()
    
    
        # 遍历渠道号并创建对应渠道号的apk文件
        for line in lines:
            # 获取当前渠道号,因为从渠道文件中获得带有
    ,所有strip一下
            target_channel = line.strip()
            # 拼接对应渠道号的apk
            target_apk = output_dir + src_apk_name + "_" + target_channel + src_apk_extension
            # 拷贝建立新apk
            shutil.copy(out_temp_apk, target_apk)
            # zip获取新建立的apk文件
            zipped = zipfile.ZipFile(target_apk, 'a', zipfile.ZIP_DEFLATED)
            # 初始化渠道信息
            empty_channel_file = "META-INF/channel_{channel}".format(channel=target_channel)
    
    
            for item in zipped.infolist():
                if (item.filename[0:16:] == 'META-INF/channel'):
                    print (item.filename)
            # 写入渠道信息
    
            zipped.write(src_empty_file, empty_channel_file)
            # 关闭zip流
            zipped.close()
    

    3.第三方统计平台设置对应渠道名

    美团有说过友盟的设置方法,由于我用的是腾讯分析,我在这里就说下腾讯的,在MainActivityonCreate方法里添加:

     StatConfig.setInstallChannel(ChannelUtils.getChannel(this));
    

    ChannelUtils.java文件:

    import android.app.Activity;
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.pm.ApplicationInfo;
    import android.util.Log;
    
    import java.io.IOException;
    import java.util.Enumeration;
    import java.util.zip.ZipEntry;
    import java.util.zip.ZipFile;
    
    /**
     * 渠道工具类
     * Created by shd on 2016/6/28.
     */
    public class ChannelUtils {
        public static final String Version = "version";
    
        public static final String Channel = "channel";
    
        public static final String DEFAULT_CHANNEL = "yunxiao";
    
        public static final String Channel_File = "channel";
    
        public static String getChannelFromMeta(Context context) {
            ApplicationInfo appinfo = context.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") && entryName.contains("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) {
                return ret.substring(split[0].length() + 1);
            } else {
                return DEFAULT_CHANNEL;
            }
        }
    
        /**
         * 得到渠道名
         *
         * @param mContext
         * @return
         */
        public static String getChannel(Context mContext) {
            String channel = "";
            if (isNewVersion(mContext)) {//是新版本
                Log.e("isNewVersion  %s", "isNewVersion");
                saveChannel(mContext);//保存当前版本
                channel = getChannelFromMeta(mContext);
            } else {
                channel = getCachChannel(mContext);
            }
            return channel;
        }
    
        /**
         * 保存当前的版本号和渠道名
         *
         * @param mContext
         */
        public static void saveChannel(Context mContext) {
            SharedPreferences mSettinsSP = mContext.getSharedPreferences(Channel_File, Activity.MODE_PRIVATE);
            SharedPreferences.Editor mSettinsEd = mSettinsSP.edit();
            mSettinsEd.putString(Version, PhoneInformationUtils.getAppVersionName(mContext));
            mSettinsEd.putString(Channel, getChannelFromMeta(mContext));
            //提交保存
            mSettinsEd.commit();
        }
    
        private static boolean isNewVersion(Context mContext) {
            SharedPreferences mSettinsSP = mContext.getSharedPreferences(Channel_File, Activity.MODE_PRIVATE);
            String version = PhoneInformationUtils.getAppVersionName(mContext);
            Log.e("version%s", version);
            return !mSettinsSP.getString(Version, "").equals(version);
        }
    
        private static String getCachChannel(Context mContext) {
            SharedPreferences mSettinsSP = mContext.getSharedPreferences(Channel_File, Activity.MODE_PRIVATE);
            return mSettinsSP.getString(Channel, DEFAULT_CHANNEL);
        }
    }
    
    

    源代码在Github上,需要的可以拿走:https://github.com/shd188/MultiChannel


    在此感谢美团cyning

     


    作者:Aimerd
    链接:https://www.jianshu.com/p/e87b1d7bde39
    來源:简书
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
     
    原文地址:https://www.jianshu.com/p/e87b1d7bde39
  • 相关阅读:
    小小的学习FPGA建议
    不厌其烦的四大集成电路
    关于FPGA复位的认识
    FPGA与图像处理
    谈谈对zynq的浅显理解
    嵌入ARM硬核的FPGA
    FPGA时序约束一点总结
    FPGA时序优化简单窍门
    学习FPGA,踏上一步台阶
    使用poi读取word2007(.docx)中的复杂表格
  • 原文地址:https://www.cnblogs.com/wodehao0808/p/9070993.html
Copyright © 2020-2023  润新知