一.Android生成原始apk
1.通过android studio打包生成
2.通过jenkins打包生成
如果选择第1种
方式的坏处:android studio打包,再通过360加固工具加固,最后通过美团的walle多渠道打包技术,需要分成三步才能完成操作,比较繁琐
如果选择第2种
方式的好处:通过python脚本集成到jenkins中,可通过一键完成所有操作,比较简洁方便
二.选择jenkins,介绍用python脚本怎样三步集成到一起
1.关于通过jenkins编译生成apk,网上有多文章可以借鉴,在此就不做介绍了
2.jenkins项目配置中找到构建,如下图设置:
jenkins构建.png
从上图可以看到在step2编译打包任务的之前增加了step1,目的是为了在编译打包之前修改想要的代码或者其他android配置,step3是为了打包完之后对这个包进行类似于上传到蒲公英平台的操作供测试人员下载,对于正式的发布这个step3其实是可以省略的,最后step4就是加固命令+美团多渠道打包命令,最终脚本添加方式就如上图
三.脚本代码(重点!重点!重点!)
step1. pre-build.py
#coding=utf-8
from __future__ import print_function
import os
import requests
import sys
import re
import argparse
#获取执行命令时设置的参数值
def parse_args():
parser = argparse.ArgumentParser(description='Pre build script.')
#python ${WORKSPACE}/Build_scripts/pre-build.py \--workspace ${WORKSPACE}
#如果执行上面的语句,那workspace这个参数对应的值的获取就如下面
parser.add_argument('--workspace', dest="workspace", default=None, help="the workspace DIR")
args = parser.parse_args()
return args
def main():
args = parse_args()
#举例说明 可以修改gradle.properties、settings.gradle的参数,
#其实只要android项目里的都可以进行修改,我这里修改的原因是我开发用的是windows,
#但jenkins是放在mac的服务器中,所以会产生路径的不一致,所以在进行编译打包之前要进行修改一下
file_path = "%s/gradle.properties" % args.workspace
with open(file_path, 'r') as f:
text = f.read()
with open(file_path, 'w') as f:
f.write(text.replace('D:/xxx' , '../xxx'))
file_path = "%s/settings.gradle" % args.workspace
with open(file_path , 'r') as f:
text = f.read()
with open(file_path, 'w') as f:
f.write(text.replace('../xxx', './xxx'))
if __name__ == '__main__':
main()
step3. build.py正式版本可以省略--不作介绍
step4. app-singer.py 此脚本内引用了config.py的配置脚本
import os
import sys
#这个config导入其实是配置文件也是自己定义的,
#再后面会介绍这个配置
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(protectedSourceApkPath)
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 = parentPath + config.keystorePath
keyAlias = config.keyAlias
keystorePassword = config.keystorePassword
keyPassword = config.keyPassword
jiaguName = config.jiaguName
jiaguPassword = config.jiaguPassword
channelsOutputFilePath = parentPath + "channels"
channelFilePath = parentPath +"channel"
protectedSourceApkPath = parentPath + config.protectedSourceApkName
jiagujarPath = config.jiagujarPath + getBackslash() + "jiagu.jar"
originReleaseApkPath = config.originReleaseApkPath
# 检查自定义路径,并作替换
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 = protectedSourceApkPath[0 : -10] + ".apk" #_signed
# 创建Channels输出文件夹
createChannelsDir()
#清空Channels输出文件夹
cleanChannelsFiles()
#360加固login
jiagu360LoginShell = "java -jar " + jiagujarPath + " -login " + jiaguName + " " + jiaguPassword ;
os.system(jiagu360LoginShell)
#360加固apk
jiagu360Shell = "java -jar " + jiagujarPath + " -jiagu " + originReleaseApkPath + " " + parentPath;
os.system(jiagu360Shell)
print(jiagu360Shell)
#对齐
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"+channelsOutputFilePath+"\n")
config.py的配置脚本
#Windows 下路径分割线请注意使用\\转义
#keystore信息
# xxx.keystore放在与config.py同一级别目录
keystorePath = "xxx.keystore"
keyAlias = "xxx"
keystorePassword = "xxx"
keyPassword = "xxx"
#360jiagu账号密码
jiaguName="xxx"
jiaguPassword="xxx"
#app版本号
#此参数其实可以通过pre-build.py中获取workspace的方式传入,
#也可以通过文件的读写直接去android项目的代码中直接去读取出来
appVersion = "607"
#android sudio打包的apk完整路径
originReleaseApkPath = "C:\\Users\\xxx\\Desktop\\release\\app-release.apk"
#加固后的源文件名(未重签名)
protectedSourceApkName = "app-release_" + appVersion + "_jiagu.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:\\Users\\xxx\\Android\\sdk\\build-tools\\26.0.2"
#jiagu.jar的源文件路径
jiagujarPath = "D:\\360jiagubao_windows_64\\jiagu"
最后,所有的配置方式大致这样,每一个步骤虽然都不是细致到手把手教的程度,但是给出了整体的思路,大家可以根据大致的步骤思路一步一步配置,慢慢采坑才能更加的理解记住
上述脚本借鉴了github的资源ProtectedApkResignerForWalle,并对脚本增加了360加固命令和一些适当的脚本修改
网友评论