一.Android生成原始apk
1.通過(guò)android studio打包生成
2.通過(guò)jenkins打包生成
如果選擇第1種
方式的壞處:android studio打包兵迅,再通過(guò)360加固工具加固抢韭,最后通過(guò)美團(tuán)的walle多渠道打包技術(shù),需要分成三步才能完成操作恍箭,比較繁瑣
如果選擇第2種
方式的好處:通過(guò)python腳本集成到j(luò)enkins中刻恭,可通過(guò)一鍵完成所有操作,比較簡(jiǎn)潔方便
二.選擇jenkins扯夭,介紹用python腳本怎樣三步集成到一起
1.關(guān)于通過(guò)jenkins編譯生成apk鳍贾,網(wǎng)上有多文章可以借鑒,在此就不做介紹了
2.jenkins項(xiàng)目配置中找到構(gòu)建交洗,如下圖設(shè)置:
jenkins構(gòu)建.png
從上圖可以看到在step2編譯打包任務(wù)的之前增加了step1骑科,目的是為了在編譯打包之前修改想要的代碼或者其他android配置,step3是為了打包完之后對(duì)這個(gè)包進(jìn)行類(lèi)似于上傳到蒲公英平臺(tái)的操作供測(cè)試人員下載藕筋,對(duì)于正式的發(fā)布這個(gè)step3其實(shí)是可以省略的纵散,最后step4就是加固命令+美團(tuán)多渠道打包命令,最終腳本添加方式就如上圖
三.腳本代碼(重點(diǎn)隐圾!重點(diǎn)伍掀!重點(diǎn)!)
step1. pre-build.py
#coding=utf-8
from __future__ import print_function
import os
import requests
import sys
import re
import argparse
#獲取執(zhí)行命令時(shí)設(shè)置的參數(shù)值
def parse_args():
parser = argparse.ArgumentParser(description='Pre build script.')
#python ${WORKSPACE}/Build_scripts/pre-build.py \--workspace ${WORKSPACE}
#如果執(zhí)行上面的語(yǔ)句暇藏,那workspace這個(gè)參數(shù)對(duì)應(yīng)的值的獲取就如下面
parser.add_argument('--workspace', dest="workspace", default=None, help="the workspace DIR")
args = parser.parse_args()
return args
def main():
args = parse_args()
#舉例說(shuō)明 可以修改gradle.properties蜜笤、settings.gradle的參數(shù),
#其實(shí)只要android項(xiàng)目里的都可以進(jìn)行修改盐碱,我這里修改的原因是我開(kāi)發(fā)用的是windows把兔,
#但jenkins是放在mac的服務(wù)器中,所以會(huì)產(chǎn)生路徑的不一致瓮顽,所以在進(jìn)行編譯打包之前要進(jìn)行修改一下
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 此腳本內(nèi)引用了config.py的配置腳本
import os
import sys
#這個(gè)config導(dǎo)入其實(shí)是配置文件也是自己定義的县好,
#再后面會(huì)介紹這個(gè)配置
import config
import platform
import shutil
#獲取腳本文件的當(dāng)前路徑
def curFileDir():
#獲取腳本路徑
path = sys.path[0]
#判斷為腳本文件還是py2exe編譯后的文件,
#如果是腳本文件暖混,則返回的是腳本的目錄缕贡,
#如果是編譯后的文件,則返回的是編譯后的文件路徑
if os.path.isdir(path):
return path
elif os.path.isfile(path):
return os.path.dirname(path)
#判斷當(dāng)前系統(tǒng)
def isWindows():
sysstr = platform.system()
if("Windows" in sysstr):
return 1
else:
return 0
#兼容不同系統(tǒng)的路徑分隔符
def getBackslash():
if(isWindows() == 1):
return "\\"
else:
return "/"
# 清空臨時(shí)資源
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
# 創(chuàng)建Channels輸出文件夾
def createChannelsDir():
try:
os.makedirs(channelsOutputFilePath)
pass
except Exception:
pass
#當(dāng)前腳本文件所在目錄
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
# 創(chuàng)建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)
#對(duì)齊
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)
#寫(xiě)入渠道
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)
#清理無(wú)用的文件
cleanTempResource()
print ("\n"+channelsOutputFilePath+"\n")
config.py的配置腳本
#Windows 下路徑分割線請(qǐng)注意使用\\轉(zhuǎn)義
#keystore信息
# xxx.keystore放在與config.py同一級(jí)別目錄
keystorePath = "xxx.keystore"
keyAlias = "xxx"
keystorePassword = "xxx"
keyPassword = "xxx"
#360jiagu賬號(hào)密碼
jiaguName="xxx"
jiaguPassword="xxx"
#app版本號(hào)
#此參數(shù)其實(shí)可以通過(guò)pre-build.py中獲取workspace的方式傳入晾咪,
#也可以通過(guò)文件的讀寫(xiě)直接去android項(xiàng)目的代碼中直接去讀取出來(lái)
appVersion = "607"
#android sudio打包的apk完整路徑
originReleaseApkPath = "C:\\Users\\xxx\\Desktop\\release\\app-release.apk"
#加固后的源文件名(未重簽名)
protectedSourceApkName = "app-release_" + appVersion + "_jiagu.apk"
#加固后的源文件所在文件夾路徑(...path),注意結(jié)尾不要帶分隔符,默認(rèn)在此文件夾根目錄
protectedSourceApkDirPath = ""
#渠道包輸出路徑贮配,默認(rèn)在此文件夾Channels目錄下
channelsOutputFilePath = ""
#渠道名配置文件路徑谍倦,默認(rèn)在此文件夾根目錄
channelFilePath = ""
#額外信息配置文件(絕對(duì)路徑,例如/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"
最后泪勒,所有的配置方式大致這樣昼蛀,每一個(gè)步驟雖然都不是細(xì)致到手把手教的程度宴猾,但是給出了整體的思路,大家可以根據(jù)大致的步驟思路一步一步配置曹洽,慢慢采坑才能更加的理解記住
上述腳本借鑒了github的資源ProtectedApkResignerForWalle鳍置,并對(duì)腳本增加了360加固命令和一些適當(dāng)?shù)哪_本修改