一鍵式Android打包(打包+加固+多渠道)

一.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)行類似于上傳到蒲公英平臺(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)行修改,我這里修改的原因是我開發(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)

#寫入渠道
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ò)文件的讀寫直接去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ù)哪_本修改

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容