1、原因:今天说一说多渠道快速打包--Python脚本多渠道打包。
2、背景:为什么想讲这个,相信我们安卓开发都有同样的烦恼,在项目上线时,如果项目的业务足够多,app就要求几十个甚至几百个渠道来支持这些业务。传统的打包无非有两种:
1、AS的gradle配置channel(渠道)打包。2、使用加固工具(360加固工具)打渠道包。
但是他们共同的特点就是慢。不是一般的慢。几十个包需要1个多小时的时间打出来 还不能保证每个包都成功。
3、解决方案:起初用了美团的瓦力多渠道打包,不过需要gradle配置,并不能单一拿出来当成一个独立的工具。
然后发现了美团提供的另一种Python脚本打包速度很快,所以有必要讲一下。
4、Python脚本实现:
-
首先看一下目录:
-
doc文件夹里放入公司的keystore文件
-
lib放入CheckAndroidV2Signature.jar和walle-cli-all.jar文件。
-
ApkResiger.py是运行签名、签名检查,写入渠道、对齐等功能的配置
-
channel是渠道号集合。
-
config.py是签名和路径配置。
-
Doumijagubao.apk是自己需要写入渠道的apk包 这个apk需要先加固不用重新签名。
5、Python文件配置详解:
config.py文件详解:
#!/usr/bin/python
#-*-coding:utf-8-*-
#keystore信息
#Windows 下路径分割线请注意使用\\转义
keystorePath = "doc\debug.key"
keyAlias = ""
keystorePassword = ""
keyPassword = ""
#加固后的源文件名(未重签名)
protectedSourceApkName = "Doumijiagubao.apk"
#加固后的源文件所在文件夹路径(...path),注意结尾不要带分隔符,默认在此文件夹根目录
protectedSourceApkDirPath = ""
#渠道包输出路径,默认在此文件夹Channels目录下
channelsOutputFilePath = ""
#渠道名配置文件路径,默认在此文件夹根目录
channelFilePath = ""
#额外信息配置文件(绝对路径,例如/Users/mac/Desktop/walle360/config.json)
#配置信息示例参看https://github.com/Meituan-Dianping/walle/blob/master/app/config.json
extraChannelFilePath = ""
#Android SDK buidtools path , please use above 25.0+
sdkBuildToolPath = "C:\DMData\AndroidTools\\android-sdk-windows\\build-tools\\25.0.3"
channel文件详解:
ApkResiger.py文件详情:
#!/usr/bin/python
#-*-coding:utf-8-*-
import os
import sys
import config
import platform
import shutil
#获取脚本文件的当前路径
def curFileDir():
#获取脚本路径
path = sys.path[0]
#判断为脚本文件还是py2exe编译后的文件,
#如果是脚本文件,则返回的是脚本的目录,
#如果是编译后的文件,则返回的是编译后的文件路径
if os.path.isdir(path):
return path
elif os.path.isfile(path):
return os.path.dirname(path)
#判断当前系统
def isWindows():
sysstr = platform.system()
if("Windows" in sysstr):
return 1
else:
return 0
#兼容不同系统的路径分隔符
def getBackslash():
if(isWindows() == 1):
return "\\"
else:
return "/"
# 清空临时资源
def cleanTempResource():
try:
os.remove(zipalignedApkPath)
os.remove(signedApkPath)
pass
except Exception:
pass
# 清空渠道信息
def cleanChannelsFiles():
try:
os.makedirs(channelsOutputFilePath)
pass
except Exception:
pass
# 创建Channels输出文件夹
def createChannelsDir():
try:
os.makedirs(channelsOutputFilePath)
pass
except Exception:
pass
#当前脚本文件所在目录
parentPath = curFileDir() + getBackslash()
#config
libPath = parentPath + "lib" + getBackslash()
buildToolsPath = config.sdkBuildToolPath + getBackslash()
checkAndroidV2SignaturePath = libPath + "CheckAndroidV2Signature.jar"
walleChannelWritterPath = libPath + "walle-cli-all.jar"
keystorePath = config.keystorePath
keyAlias = config.keyAlias
keystorePassword = config.keystorePassword
keyPassword = config.keyPassword
channelsOutputFilePath = parentPath + "channels"
channelFilePath = parentPath +"channel"
protectedSourceApkPath = parentPath + config.protectedSourceApkName
# 检查自定义路径,并作替换
if len(config.protectedSourceApkDirPath) > 0:
protectedSourceApkPath = config.protectedSourceApkDirPath + getBackslash() + config.protectedSourceApkName
if len(config.channelsOutputFilePath) > 0:
channelsOutputFilePath = config.channelsOutputFilePath
if len(config.channelFilePath) > 0:
channelFilePath = config.channelFilePath
zipalignedApkPath = protectedSourceApkPath[0 : -4] + "_aligned.apk"
signedApkPath = zipalignedApkPath[0 : -4] + "_signed.apk"
# 创建Channels输出文件夹
createChannelsDir()
#清空Channels输出文件夹
cleanChannelsFiles()
#对齐
zipalignShell = buildToolsPath + "zipalign -v 4 " + protectedSourceApkPath + " " + zipalignedApkPath
os.system(zipalignShell)
#签名
signShell = buildToolsPath + "apksigner sign --ks "+ keystorePath + " --ks-key-alias " + keyAlias + " --ks-pass pass:" + keystorePassword + " --key-pass pass:" + keyPassword + " --out " + signedApkPath + " " + zipalignedApkPath
os.system(signShell)
print(signShell)
#检查V2签名是否正确
checkV2Shell = "java -jar " + checkAndroidV2SignaturePath + " " + signedApkPath;
os.system(checkV2Shell)
#写入渠道
if len(config.extraChannelFilePath) > 0:
writeChannelShell = "java -jar " + walleChannelWritterPath + " batch2 -f " + config.extraChannelFilePath + " " + signedApkPath + " " + channelsOutputFilePath
else:
writeChannelShell = "java -jar " + walleChannelWritterPath + " batch -f " + channelFilePath + " " + signedApkPath + " " + channelsOutputFilePath
os.system(writeChannelShell)
cleanTempResource()
print ("\n**** =============================TASK FINISHED=================================== ****\n")
print ("\n↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ Please check channels in the path ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\n")
print ("\n"+channelsOutputFilePath+"\n")
print ("\n**** =============================TASK FINISHED=================================== ****\n")
6、运行方式:
打开命令行-->cd到脚本父目录下-->运行 python ApkResigner.py 即可。
成功后就可以发先父目录多了一个channels文件夹 里面就是所有的渠道包。是不是很快呢。
如果很快很好用,给个赞哦。