如何给app打vendor标签

作者: 三十二蝉 | 来源:发表于2017-04-24 18:25 被阅读82次

    官方推荐的打包方法

    配置productFlavors

        productFlavors {
            index{}
            tencent{}
            m360{}
            baidu{}
            wandoujia{}
            xiaomi{}
            zhihuiyun{}
            oppo{}
            meizu{}
            anzhi{}
            lenovo{}
            pp{}
            jinli{}
            vivo{}
            other{}
            googleplay{}
            smartisan{}
            sogou{}
        }
    

    借鉴友盟的方法使用meta-data占位符分配vendor值:

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

    在Application标签下配置APP_CHANNEL;
    在gradle中android标签下添加如下代码:

      productFlavors.all { flavor ->
            manifestPlaceholders.put("APP_CHANNEL",name)
        }
    

    在build的时候会填充APP_CHANNEL字段。
    在app中获取vendor值:

    /**
         * 从apk中获取版本信息
         *
         * @param app Application
         * @return
         */
        private static String getChannelFromApk(Application app) {
            final String DEFAULT_CHANNEL = "default_vendor";
            String channel = DEFAULT_CHANNEL;
            try {
                ApplicationInfo appInfo = app.getPackageManager()
                        .getApplicationInfo(app.getPackageName(),
                                PackageManager.GET_META_DATA);
                channel = appInfo.metaData.getString("APP_CHANNEL");
    
    
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
            return channel;
        }
    

    使用BuildConfig.FLAVOR

    也可以不使用meta-data,直接取FLAVOR的名字做vendor值:

     if (TextUtils.isEmpty(vendor)) {
                vendor = BuildConfig.FLAVOR;
                PreferenceUtils.putString(PreferenceConsts.KEY_VONDER, vendor);
            }
    
            if (TextUtils.isEmpty(vendor)){
                vendor = "EMPTY_VENDOR";
            }
    

    美团的打包方法

    官方推荐的打包方法在多渠道打包的时候,一旦渠道包特别多,就会非常慢。美团的打包方法就会显得非常快,因为美团的打包方法只打一个包,其余的包都是根据这个现有的包做修改。

    gradle 配置

    在gradle文件中不需要配置productFlavors。打默认的release包就行。但是有一点需要注意,新版的android studio打包默认采用V2签名。美团的打包方法一旦采用了V2签名的方法,在android 7.0的手机上是装不上去的。所有需要在realse标签下申请不使用V2签名:

    release {
                storeFile file('.....')
                storePassword "....."
                keyAlias "......"
                keyPassword "....."
                v2SigningEnabled false
            }
    

    同时注意,不能用android studio导航栏Build->generate signed APK,打包,因为上述步骤会要求你重写填写签名文件,密码等,也就是说gradle里面的release配置不会生效。
    至此,我们应该会得到一个release.apk。之后的步骤与android无关,写一个脚本修改META-INF目录,在这个目录下新建一个空的文件。(这种方法不需要重签名,根据空文件的文件名区分vendor)。
    脚本如下:

    # 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
    
    # 创建一个空文件,此文件作为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)
    
    # 获取当前目录下所有的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/appchannel_{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...')
    

    python相关目录

    -- release.apk
    -- vendor-rename.py
    -- info
       -- empty.txt
       -- channel.txt
    -- output
    

    info中channel.txt包含渠道列表:

    apk.hiapk.com
    pp.vmall.com
    AppWall_YoudaoCidianAndroid
    hanyu.youdao.com
    faxian
    anzhi
    baidu
    ext.se.360.cn
    lenovo
    meizu
    oppo
    sj.qq.com
    wandoujia
    weibo
    xiaomi
    yingyongbao
    zhihuiyun
    

    empty.txt是一个空文件,脚本会将这个问题放在META-INFO目录下,并重命名为渠道名。

    最后在App中获取渠道名字:

        /**
         * 从apk中获取版本信息
         *
         * @param context
         * @param channelKey
         * @return
         */
        private static String getChannelFromApk(Context context, String channelKey) {
            final String DEFAULT_CHANNEL = "default_vendor";
            long startTime = System.currentTimeMillis();
            //从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 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("未解析到相应的渠道号,使用默认内部渠道号");
                channel = DEFAULT_CHANNEL;
            }
            return channel;
        }
    

    相关文章

      网友评论

        本文标题:如何给app打vendor标签

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