美文网首页Android知识Android技术知识
android多渠道打包最快方案

android多渠道打包最快方案

作者: 轻云时解被占用了 | 来源:发表于2016-12-12 15:34 被阅读163次

    目前Android多渠道打包主要两种方式:

    Gradle方式。

    在build.gradle配置:

     productFlavors {
            huawei {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "huawei"]
            }
            xiaomi {
                manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"]
            }
            ...
        }
    

    渠道多的时候会导致gradle文件很长,如果想简化书写可以这样做:
    在build.gradle中配置如下:

    Properties properties = new Properties()
    properties.load(project.rootProject.file('local.properties').newDataInputStream())
    ...
    android{
        ...
        productFlavors {
                def channelArray = properties.getProperty("channel").split(";");
                for (int i = 0; i < channelArray.size(); i++) {
                    def channel = channelArray[i]
                    "${channel}" {
                        manifestPlaceholders = [CHANNEL_VALUE: channel]
                    }
                }
            }
            ...
    }        
    

    local.properties中添加所有渠道号:channel=wandoujia;_360;yingyongbao;xiaomi;baidu;huawei;...

    当渠道很多的时候,每次打包的时间要几十分钟到几个小时,那么有没有更快速的方式呢,请看第二种方式。

    META-INF方式。

    使用此种方式可以动态获取当前渠道号,极大节省了打包时间。

        /**
         * 友盟配置
         在application onCreate方法调用
         */
        private void umengConfig() {
            String channel = getChannelFromApk(application, "channel-");
            if (TextUtils.isEmpty(channel)) {
                channel = "default";
            }
            if (BuildConfig.IS_DEBUG) {
                Toast.makeText(application, "当前渠道:" + channel, Toast.LENGTH_SHORT).show();
            }
            AnalyticsConfig.setChannel(channel);
        }
        
         /**
         * 从apk中获取版本信息
         * @param context
         * @param channelPrefix 渠道前缀
         * @return
         */
        public static String getChannelFromApk(Context context, String channelPrefix) {
            //从apk包中获取
            ApplicationInfo appinfo = context.getApplicationInfo();
            String sourceDir = appinfo.sourceDir;
            //默认放在meta-inf/里, 所以需要再拼接一下
            String key = "META-INF/" + channelPrefix;
            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(channelPrefix);
            String channel = "";
            if (split != null && split.length >= 2) {
                channel = ret.substring(key.length());
            }
            return channel;
        }
    

    每次动态获取应用包下meta-inf文件夹中的渠道文件取得渠道号,那么meta-inf下的渠道文件如何添加呢?我们可以使用python脚本来做这件事。

    #!/usr/bin/python
    # coding=utf-8
    import zipfile
    import shutil
    import os
    import ConfigParser
    
    #读取配置文件
    config = ConfigParser.ConfigParser()
    config.read("channels-config.ini")
    #apk路径
    apk_path = config.get("Build-Config", "apk.path")
    print "src apk path=" + apk_path
    #渠道识别前缀
    channel_prefix = config.get("Build-Config", "channel.prefix")
    print "channel prefix=" + channel_prefix
    #渠道列表
    channel_list = config.get("Build-Config", "channel.list")
    print "channel list=" + channel_list
    #解析渠道,生成渠道数组
    channel_array = channel_list.split(',')
    
    # 空文件 便于写入此空文件到apk包中作为channel文件
    src_temp_file = 'temp_.txt'
    # 创建一个空文件(不存在则创建)
    f = open(src_temp_file, 'w')
    f.close()
    
    
    src_apk = apk_path
    # 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 = 'apks_' + src_apk_name + '/'
    # 目录不存在则创建
    if not os.path.exists(output_dir):
        os.mkdir(output_dir)
    
    # 遍历渠道号并创建对应渠道号的apk文件
    for line in channel_array:
        # 获取当前渠道号,因为从渠道文件中获得带有\n,所有strip一下
        target_channel = line.strip()
        # 拼接对应渠道号的apk
        target_apk = output_dir + src_apk_name + "-" + target_channel + src_apk_extension
        # 拷贝建立新apk
        shutil.copy(src_apk,  target_apk)
        # zip获取新建立的apk文件
        zipped = zipfile.ZipFile(target_apk, 'a', zipfile.ZIP_DEFLATED)
    
        # 初始化渠道信息
        target_channel_file = "META-INF/" + channel_prefix + "{channel}".format(channel = target_channel)
        # 写入渠道信息
        zipped.write(src_temp_file, target_channel_file)
        # 关闭zip流
        zipped.close()
    
    #删除临时文件
    os.remove(src_temp_file)
    

    channels-config.ini文件如下:

    [Build-Config]
    apk.path = your apk path
    channel.prefix = channel-
    channel.list = baidu,xiaomi
    

    相关文章

      网友评论

        本文标题:android多渠道打包最快方案

        本文链接:https://www.haomeiwen.com/subject/yjbmmttx.html