安卓打渠道包是个比较头痛的问题,如在gradle里面配置manifestPlaceholders的方式,它虽然实现了打出多渠道包,代价也是相当大的。编译耗时长,同时计算机基本也干不了别的事了,不能忍受!
度娘一把,结果也是非常多的,我就是看了Android批量打包-如何一秒内打完几百个apk渠道包,前辈是通过给apk包写一个空白文件,把渠道信息写在文件名上,然后在java代码里面解析applicationInfo的sourceDir文件,遍历从而拿到渠道名等信息。
这对于app文件比较多,渠道信息比较多,耗时也相对会多很多。既然都往app里面写入文件了,为啥不往这个文件里面写入内容,这样可以存放更多的渠道信息了。
直接修改链接文章的脚本实现~
脚本:
import sys,os,shutil,zipfile,time,json srcFileName="source.apk" apksDir="apks" target_file="temp.apk" file=open("channel.txt") def writeChannelToApk(filename,channel): z=zipfile.ZipFile(filename,'a',zipfile.ZIP_DEFLATED) empty_channel_file="META-INF/channel.json" if not os.path.exists(target_file): open(target_file,'a').close() z.writestr(empty_channel_file,data=channel,compress_type=zipfile.ZIP_DEFLATED) print("path:"+filename+"\n"+"content:"+channel) z.close() def cpFile(srcPath,fileName): destPath=os.path.abspath('.')+os.path.sep+fileName if os.path.exists(srcPath)and not os.path.exists(destPath): shutil.copy(srcPath,destPath) if not os.path.exists(srcFileName): print("source file "+srcFileName+" not exists") sys.exit(1) start=time.clock() if not os.path.exists(apksDir): os.makedirs(apksDir) for line in file: channel=line.strip('\n').strip() data=json.loads(channel) targetFileName=apksDir+"/"+data['channel_name']+data['channel_code']+".apk" cpFile(srcFileName,targetFileName) writeChannelToApk(targetFileName,channel) end=time.clock() print("The function run time is : %.03f seconds"%(end-start))
与原脚本唯一不同就是固定了写入文件名,然后将channel.txt的内容写入到文件里。
channel.txt
{"channel_name":"qxb-student-","channel_code":1001,"channel_type":3} {"channel_name":"qxb-student-","channel_code":3001,"channel_type":5} {"channel_name":"qxb-student-","channel_code":3002,"channel_type":6}
执行脚本就会生成对应的渠道包,剩下的就需要到代码里面去解析渠道信息了。
String sourceDir = getApplicationInfo().sourceDir; ZipFile zipfile = null; InputStream inputStream = null; try { zipfile = new ZipFile(sourceDir); ZipEntry zipEntry = zipfile.getEntry('META-INF/channel.json'); inputStream = zipfile.getInputStream(zipEntry); byte[] buff = new byte[(int) zipEntry.getSize()]; inputStream.read(buff); channelInfo = new String(buff); } catch (IOException e) { e.printStackTrace(); } finally { try { if (inputStream != null) inputStream.close(); if (zipfile != null) zipfile.close(); } catch (IOException e) { e.printStackTrace(); } }
初始化ZipFile,可以根据文件路径获取它的ZipEntry对象,然后再根据ZipEntry拿到文件的流信息,读取就可以了。