如何给app打vendor标签

官方推荐的打包方法

配置productFlavors

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

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

        

在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标签)