一:概述
由于安卓应用市场很多,为了兼容每个市场的数据统计,我们需要为不同的应用市场上的apk安装包设置不同的渠道包,每次发版本的时候,由于渠道包的数量较多,为了解决这种重复无效的工作,需要提供一个种简洁的打包方式。
二、方案说明
现在有比较成熟的第三方应用实现统计功能(比如友盟),统计的本质是收集用户信息到后台,后台生成报表,帮助我们跟踪分析并完善app。通过系统的方法已经能获取到版本号,版本名称,系统版本号,机型和地区等各种信息,唯独应用商店(渠道)的信息我们是没有办法从系统获取到的,所以我们可以在apk中添加渠道信息,即一个字段标识,如xiaomi,m360,baidu。为了高效,批量地完成打包工作,考虑不对每个渠道包单独进行签名,而是采用在apk的META-INF文件夹中添加一个唯一标识的空文件,使用代码获取当前的apk空文件名作为渠道号,从而将相应渠道的apk信息传输到后台,后台根据该标识就可以统计渠道中的下载量等信息。
三、打包步骤
1、下载并安装python。python2和python3都可以,建议版本python2.7,详细安装步骤可自行百度。
2、拷贝打包文件夹buildapk到本地,只包含supportChanel文件夹和 apk.py文件。
下载地址:
3、在supportChanel文件夹的channel.txt文件里手动添加需要生成的渠道名,多个渠道之间用换行隔开。
4、拷贝需要生成多渠道的源apk文件,放置apk.py同一目录下。
5、双击apk.py文件即可生成一个outputDir文件夹,存放目标渠道apk文件。
apk.py代码如下:
# coding=utf-8
import zipfile
import shutil
import os
# 创建一个空文件,此文件作为apk包中的空文件
src_empty_file = 'supportChanel/empty.txt'
f = open(src_empty_file,'w')
f.close()
# 在渠道号配置文件中,获取指定的渠道号
channelFile = open('./supportChanel/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('.'):
ifos.path.isfile(file):
extension= os.path.splitext(file)[1][1:]
ifextension in 'apk':
src_apks.append(file)
# 遍历所以的apk文件,向其压缩文件中添加渠道号文件
for src_apk in src_apks:
src_apk_file_name= os.path.basename(src_apk)
print('currentapk 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]
output_dir= 'outputDir'+'/'
ifnot os.path.exists(output_dir):
os.mkdir(output_dir)
# 遍历从文件中获得的所以渠道号,将其写入APK包中
forline in channels:
target_channel= line.strip()
target_apk= output_dir + 'mobile' + "-" + target_channel+"-release" +src_apk_extension
shutil.copy(src_apk, target_apk)
zipped= zipfile.ZipFile(target_apk, 'a', zipfile.ZIP_DEFLATED)
empty_channel_file= "META-INF/uuchannel_{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))
四、使用渠道号
生成渠道包之后需要在代码中引用相对应的渠道包,进行数据的标识。创建ChannelUtil.java 文件用来解析渠道号,在进入应用的方法中使用ChannelUtil中的getChannel方法进行渠道号的设置。
getChannel代码如下:
public static String getChannel(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("bbkchannel")) { 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 ""; } }
五、参考
http://tech.meituan.com/mt-apk-packaging.html
美团Android自动化之旅—生成渠道包
https://github.com/mcxiaoke/gradle-packer-plugin
1000个渠道包只需要5s的打包方式