往往我们使用 egret 需要能够自动打包,本文介绍 egret 自动打包 iOS 和 Android,使用 python 来实现自动打包。
环境
- 安装了 egret 相关编辑器
- 安装python 3.x 版本
配置
env.profile
# add android ndk enviroment
export NDK_ROOT=/Users/pack/developer/android/android-ndk-r13
export PATH=$PATH:$NDK_ROOT
# add android sdk enviroment
export ANDROID_SDK_ROOT=/Users/pack/developer/android/android-sdk
export PATH=$PATH:$ANDROID_SDK_ROOT
export PATH=$PATH:$ANDROID_SDK_ROOT/tools
export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools
# add ant enviroment
export ANT_ROOT=/Users/pack/developer/android/apache-ant-1.9.14/bin
export PATH=$PATH:$ANT_ROOT
# add gradle environment variable for android studio
export GRADLE_HOME=/Applications/Android\ Studio.app/Contents/gradle/gradle-4.6
export PATH=${PATH}:${GRADLE_HOME}/bin
配置依赖文件 config.json
{
"work":{
"path":"/Users/pack/workspace/damai/damai-client"
},
"android":{
"path":"/Users/pack/workspace/damai/damai-client_android"
},
"ios":{
"path":"/Users/pack/workspace/damai/damai-client_ios"
},
"update":{
"path":"/Users/pack/workspace/damai/update",
"download_url":"mg.figurinn.xyz/update"
},
"tools":{
"path":"/Users/pack/workspace/damai/tools"
},
"ftp":{
"url":"192.168.3.250",
"account":"code",
"password":"code"
},
"ios-json":{
"bak-path":"/Users/pack/workspace/damai/damai-resources-bak/default.thm.json",
"target-path":"/Users/pack/workspace/damai/damai-client_ios/assets/game/resource/default.thm.json"
},
"android-json":{
"bak-path":"/Users/pack/workspace/damai/damai-resources-bak/default.thm.json",
"target-path":"/Users/pack/workspace/damai/damai-client_android/assets/game/resource/default.thm.json"
},
"ios-egret-json":{
"bak-path":"/Users/pack/workspace/damai/damai-resources-bak/ios/egretProperties.json",
"target-path":"/Users/pack/workspace/damai/damai-client/egretProperties.json"
},
"android-egret-json":{
"bak-path":"/Users/pack/workspace/damai/damai-resources-bak/android/egretProperties.json",
"target-path":"/Users/pack/workspace/damai/damai-client/egretProperties.json"
}
}
版本号配置文件 update_version.json
{"v1": 1, "v2": 0, "v3": 0}
安卓打包 python 脚本 android_package.py
import ftplib
import json
# import zen
import os
import time
global config
def load_json(file_name):
with open(file_name,"r") as f:
data = json.load(f)
return data
def build_android_package():
global config
c = config["work"]
print(" clean cmd\n");
os.system("clear")
print("===================================================")
print(" update git...")
os.chdir(c["path"])
os.system("git pull")
print("===================================================")
print(" modify egretproperties-json file begin...\n")
cpd1 = config["android-egret-json"]
cptarget1 = cpd1["target-path"]
cptemp1 = cpd1["bak-path"]
os.system("\cp " + cptemp1 + " " + cptarget1)
print(" modify egretproperties-json file done.\n")
print("===================================================")
print(" rebuild android projct, generate js code and resources\n")
print(" wait a few seconds...")
os.system("egret publish " + c["path"])
print(" rebuild done.")
print("===================================================")
print(" build android package...\n")
print(" modify default-thm-json file begin...\n")
cpd2 = config["android-json"]
cptarget2 = cpd2["target-path"]
cptemp2 = cpd2["bak-path"]
os.system("\cp " + cptemp2 + " " + cptarget2)
print(" modify default-thm-json file done.\n")
andr = config["android"]
os.chdir(andr["path"])
print(" gradle clean...\n")
os.system("gradle clean")
print(" gradle build...\n")
os.system("gradle build")
print(" gradle generate release apk...\n")
os.system("gradle assembleRelease")
return andr["path"] + "/app/build/outputs/apk/app-release.apk"
def send_message_to_zen(title,desc):
print("===================================================")
global config
c = config["zen"]
cli = zen.zentao_client(c["url"], c["account"], c["password"])
cli.login()
cli.add_todo(title,desc)
def upload_file_to_ftp(local_file_path,remote_path,remote_file_name):
print("===================================================")
global config
c = config["ftp"]
ftp = ftplib.FTP(c["url"])
ftp.login(c["account"], c["password"])
ftp.cwd(remote_path)
with open(local_file_path,"rb") as fd:
ftp.storbinary("STOR "+remote_file_name,fd)
ftp.close()
def init_evn():
global config
c = config["tools"]
os.chdir(c["path"])
print("initalize env profile")
os.system("source env.profile")
print("add gradle operator permission...\n")
os.system("chmod +x /Applications/Android\ Studio.app/Contents/gradle/gradle-4.6/bin/gradle")
if __name__ == "__main__":
global config
os.chdir("/Users/xindonghai/workspace/damai/tools")
config = load_json("config.json")
init_evn()
file_name = time.strftime("damai-%Y-%m-%d-%H-%M-%S-android.apk",time.localtime(time.time()))
remote_path = "client-package/damai"
apk_full_path = build_android_package()
print("===================================================")
print(" new generate apk route is:" + apk_full_path)
upload_file_to_ftp(apk_full_path,remote_path,file_name)
print("done!!!!!!")
iOS 打包 python 脚本 ios_package.py
import ftplib
import json
import os
import time
global config
def load_json(file_name):
with open(file_name,"r") as f:
data = json.load(f)
return data
def build_ios_package():
global config
c = config["work"]
print(" clean cmd\n");
os.system("clear")
print("===================================================")
print(" update git...")
os.chdir(c["path"])
os.system("git pull")
print("===================================================")
print(" modify egretproperties-json file begin...\n")
cpd1 = config["ios-egret-json"]
cptarget1 = cpd1["target-path"]
cptemp1 = cpd1["bak-path"]
os.system("\cp "+cptemp1+" "+cptarget1)
print(" modify egretproperties-json file done.\n")
print("===================================================")
print(" rebuild ios projct, generate js code and resources\n")
print(" wait a few seconds...")
os.system("egret publish " + c["path"])
print(" rebuild done.")
print("===================================================")
print(" build ios package...\n")
print(" modify default-thm-json file begin...\n")
cpd2 = config["ios-json"]
cptarget2 = cpd2["target-path"]
cptemp2 = cpd2["bak-path"]
os.system("\cp "+cptemp2+" "+cptarget2)
print(" modify default-thm-json file done.\n")
c = config["ios"]
os.chdir(c["path"])
print(" clean project...\n")
comm_pram = " -project " + c["path"] + "/damai.xcodeproj" + " -configuration Release " #" -target carrots-mobile" +
cmd = "xcodebuild clean " + comm_pram + " -target damai-mobile"
print(cmd)
os.system(cmd)
os.system("rm -rf ./archive.xcarchive")
cmd = "xcodebuild archive " + comm_pram + " -scheme damai-mobile " + " -archivePath ./archive.xcarchive"
print(cmd)
os.system(cmd)
os.system("rm -rf ./ipa/*")
cmd = "xcodebuild -exportArchive -archivePath ./archive.xcarchive -exportOptionsPlist ./ExportOptions.plist -exportPath ./ipa"
print(cmd)
os.system(cmd)
print("===================================================")
print(" rename ios package...")
file_name = time.strftime("damai-%Y-%m-%d-%H-%M-%S-ios.ipa",time.localtime(time.time()))
os.rename(c["path"]+"/ipa/damai-mobile.ipa" , c["path"]+"/ipa/"+file_name)
print(" rename ios done.")
return file_name
def send_message_to_zen(title,desc):
print("===================================================")
print(" send meaasge to chan dao ")
global config
c = config["zen"]
cli = zen.zentao_client(c["url"], c["account"], c["password"])
cli.login()
cli.add_todo(title,desc)
def upload_file_to_ftp(local_file_path,remote_path,remote_file_name):
print("===================================================")
print(" upload to ftp")
global config
c = config["ftp"]
ftp = ftplib.FTP(c["url"])
ftp.login(c["account"], c["password"])
ftp.cwd(remote_path)
with open(local_file_path,"rb") as fd:
ftp.storbinary("STOR "+remote_file_name,fd)
ftp.close()
if __name__ == "__main__":
global config
# change current dir work route to tools
os.chdir("/Users/xindonghai/workspace/damai/tools")
config = load_json("config.json")
# file_name = time.strftime("%Y-%m-%d-%H-%M-%S-ios.ipa",time.localtime(time.time()))
remote_path = "client-package/damai"
#process_js()
file_name = build_ios_package()
ipa_full_path = config["ios"]["path"] + "/ipa/" + file_name
print("===================================================")
print(" new generate ipa route is:" + ipa_full_path)
upload_file_to_ftp(ipa_full_path,remote_path,file_name)
# send_message_to_zen("damai build success!!!","ftp route:" + remote_path + "/" + file_name )
print("\nbuild ios package done.")
打包热更新包脚本(Android & iOS)python 脚本 update_package.py
import ftplib
import json
import os
import time
import sys
import hashlib
import zipfile
global config
global version
excludes = [".DS_Store"]
def isFileFilter(filename):
for name in excludes:
if filename.endswith(name) or filename == name :
return True
return False
def getmd5(filename):
m = hashlib.md5()
mfile = open(filename, 'rb')
m.update(mfile.read())
mfile.close()
md5value = m.hexdigest()
return md5value
def load_json(file_name):
with open(file_name,"r") as f:
data = json.load(f)
return data
def save_json(file_name,data):
with open(file_name,"w") as f:
json.dump(data,f,sort_keys = True)
def build_ios_update_package(path,os_path,desc_path,version_str,download_url,zip_name,os_type):
print(path)
print(desc_path)
os.chdir(path)
print("===================================================")
print(" update git...\n")
os.system("git pull")
print("===================================================")
print(" modify egretproperties-json file begin...\n")
cpd1 = config["ios-egret-json"]
cptarget1 = cpd1["target-path"]
cptemp1 = cpd1["bak-path"]
os.system("\cp "+cptemp1+" "+cptarget1)
print(" modify egretproperties-json file done.\n")
print("===================================================")
print(" rebuild ios projct, generate js code and resources\n")
print(" wait a few seconds...")
os.system("egret publish " + path)
print(" rebuild done.")
print("===================================================")
print(" modify default-thm-json file begin...\n")
cpd2 = config["ios-json"]
cptarget2 = cpd2["target-path"]
cptemp2 = cpd2["bak-path"]
os.system("\cp "+cptemp2+" "+cptarget2)
print(" modify default-thm-json file done.\n")
print("===================================================")
print(" change work directory to update folder...\n")
isExitFolder = os.path.exists(desc_path)
if not isExitFolder:
os.system("mkdir -p "+desc_path)
os.chdir(desc_path)
os.system("rm -rf ./*")
print(" copy resource from js and resource...\n")
os.system("cp -r " + os_path + "/assets/game" + "/js ./")
os.system("cp -r " + os_path + "/assets/game" + "/resource ./")
print("===================================================")
print(" create new filelist.json file...\n")
create_filelist_json(download_url,version_str,os_type)
print(" new filelist.json file create done.\n")
print(" create new version.json file...\n")
create_version_json(download_url,version_str,os_type)
print(" new version.json file create done.\n")
os.system("rm -rf ../" + zip_name)
zip_file_path("./","../",zip_name)
return desc_path + "/../" + zip_name
def build_android_update_package(path,os_path,desc_path,version_str,download_url,zip_name,os_type):
print(path)
print(desc_path)
os.chdir(path)
print("===================================================")
print(" update git...\n")
os.system("git pull")
print("===================================================")
print(" modify egretproperties-json file begin...\n")
cpd1 = config["android-egret-json"]
cptarget1 = cpd1["target-path"]
cptemp1 = cpd1["bak-path"]
os.system("\cp "+cptemp1+" "+cptarget1)
print(" modify egretproperties-json file done.\n")
print("===================================================")
print(" rebuild android projct, generate js code and resources\n")
print(" wait a few seconds...")
os.system("egret publish " + path)
print(" rebuild done.")
print("===================================================")
print(" modify android-thm-json file begin...\n")
cpd2 = config["android-json"]
cptarget2 = cpd2["target-path"]
cptemp2 = cpd2["bak-path"]
os.system("\cp "+cptemp2+" "+cptarget2)
print(" modify default-thm-json file done.\n")
print("===================================================")
print(" change work directory to update folder...\n")
isExitFolder = os.path.exists(desc_path)
if not isExitFolder:
os.system("mkdir -p "+desc_path)
os.chdir(desc_path)
os.system("rm -rf ./*")
print(" copy resource from js and resource...\n")
os.system("cp -r " + os_path + "/assets/game" + "/js ./")
os.system("cp -r " + os_path + "/assets/game" + "/resource ./")
print("===================================================")
print(" create new filelist.json file...\n")
create_filelist_json(download_url,version_str,os_type)
print(" new filelist.json file create done.\n")
print(" create new version.json file...\n")
create_version_json(download_url,version_str,os_type)
print(" new version.json file create done.\n")
os.system("rm -rf ../" + zip_name)
zip_file_path("./","../",zip_name)
return desc_path + "/../" + zip_name
def create_filelist_json(download_url,version_str,os_type):
newList = {}
newList["stage"] = []
walk_dir("resource/",newList)
walk_dir("js/",newList)
fileinfo = open('filelist.json','w')
buf ="{\n"
buf +="\t\"version\" : \"" + version_str + "\",\n"
buf +="\t\"engineVersion\" : \"5.2.15\",\n"
buf +="\t\"type\" : \""+os_type+"\",\n"
buf +="\t\"filelist\" : ["
for i in range(0,len(newList["stage"])):
file = newList["stage"][i]
buf += "\n\t\t{\n\t\t\t\"name\":\""+file["name"]+"\",\n"
buf += "\t\t\t\"md5\":\""+file["code"]+"\",\n"
buf += "\t\t\t\"size\":\""+str(file["size"])+"\"\n"
if i<len(newList["stage"])-1:
buf += "\t\t},"
else:
buf += "\t\t}"
buf += "\n\t],\n"
buf +="\n\t\"searchPaths\" : [\n"
buf +="\t]\n"
buf = buf + "}"
fileinfo.write(buf)
fileinfo.close()
def create_version_json(download_url,version_str,os_type):
fileinfo = open('version.json','w')
buf ="{\n"
buf += "\t\"filelist_url\" : \"http://"+download_url+"/"+os_type+"/filelist.json\",\n"
buf += "\t\"base_url\" : \"http://"+download_url+"/"+os_type+"/\",\n"
buf +="\t\"version\" : \""+version_str+"\",\n"
buf +="\t\"type\" : \""+os_type+"\",\n"
buf +="\t\"engineVersion\" : \"5.2.15\"\n"
buf = buf + "}"
fileinfo.write(buf)
fileinfo.close()
def walk_dir(dir,newList):
for root, dirs, files in os.walk(dir):
for name in files:
path = os.path.join(root,name)
newPath = path#path.replace(gamePath,"")
if not isFileFilter(newPath):
detail = {}
detail["name"] = newPath
detail["code"] = getmd5(path)
detail["size"] = os.path.getsize(path)
newList["stage"].append(detail)
return newList
def zip_file_path(input_path, output_path, output_name):
f = zipfile.ZipFile(output_path + '/' + output_name, 'w', zipfile.ZIP_DEFLATED)
filelists = []
get_zip_file(input_path, filelists)
for file in filelists:
f.write(file)
f.close()
return output_path + r"/" + output_name
def get_zip_file(input_path, result):
files = os.listdir(input_path)
for file in files:
if os.path.isdir(input_path + "/" + file):
get_zip_file(input_path + "/" + file, result)
else:
result.append(input_path + "/" + file)
def upload_file_to_ftp(local_file_path,remote_path,remote_file_name):
print("===================================================")
print(" update to ftp"+local_file_path+"...\n")
global config
c = config["ftp"]
ftp = ftplib.FTP(c["url"])
ftp.login(c["account"], c["password"])
ftp.cwd(remote_path)
with open(local_file_path,"rb") as fd:
ftp.storbinary("STOR "+remote_file_name,fd)
ftp.close()
if __name__ == "__main__":
global config,version
os.chdir("/Users/xindonghai/workspace/damai/tools")
config = load_json("config.json")
version = load_json("update_version.json")
version_str = str(version["v1"]) + "." + str(version["v2"]) + "." + str(version["v3"])
download_url = config["update"]["download_url"]
print("version: " + version_str + " download_url: " + download_url)
ios_path = config["ios"]["path"]
android_path = config["android"]["path"]
update_path = config["update"]["path"]
work_path = config["work"]["path"]
print("===================================================")
print(" build update package...\n")
ios_zip = build_ios_update_package(work_path,ios_path,update_path+"/ios",version_str,download_url,"ios.zip","ios")
android_zip = build_android_update_package(work_path,android_path,update_path+"/android",version_str,download_url,"android.zip","android")
print(ios_zip)
print(android_zip)
ios_file_name = time.strftime("damai-ios-%Y-%m-%d-%H-%M-%S-HotUpdate.zip",time.localtime(time.time()))
android_file_name = time.strftime("damai-android-%Y-%m-%d-%H-%M-%S-HotUpdate.zip",time.localtime(time.time()))
remote_path = "client-package/damai/update"
upload_file_to_ftp(ios_zip,remote_path,ios_file_name)
upload_file_to_ftp(android_zip,remote_path,android_file_name)
os.chdir(config["tools"]["path"])
version["v3"] = version["v3"] + 1
save_json("update_version.json",version)
print("===================================================")
print("done!!!!!!")
流程
Android 和 iOS 有所不同,所以拆分讲解流程
Android
- 初始化安卓打包环境 env.profile (需要生效 env.profile 以及 授权 androidstuudio 下的 gradle 可以修改的权限)
- 更新 client git (更新项目)
- 替换 egretproperties.json 文件,修改 egretproperties.json 中的 target/current 修改为 android
- 发布 egret
- 替换 default-thm.json 文件.(此处是个 bug ,若是skins里面有 exmls 文件,则下载一些失败文件会导致黑屏.若是把自动生成 skins 的字段置为 false ,则游戏启动会异常)
- 调用代码自动打包
- 将生成的 apk 重新命名,以名字-时间-平台.apk
- 将生成的 apk 发送到 ftp 上
iOS
- 更新 client git (更新项目)
- 替换egretproperties.json文件,修改egretproperties.json中的target/current修改为ios
- 发布 egret
- 替换 default-thm.json 文件.(此处是个 bug ,若是skins里面有 exmls 文件,则下载一些失败文件会导致黑屏.若是把自动生成 skins 的字段置为 false ,则游戏启动会异常)
- 调用代码自动打包
- 将生成的 apk 重新命名,以名字-时间-平台.ipa
- 将生成的 apk 发送到 ftp 上