編譯腳本組成
1趁餐、buildApk.py:位于根目錄,調(diào)用不同平臺(tái)shell的gradlew clean 和 根據(jù)用戶選擇gradlew assembleRelease或者 gradlew assembleDebug 篮绰,調(diào)用UploadUtil.uploadPuGongYing(vSysInfo=vSysInfo)上傳到蒲公英平臺(tái)
2后雷、upload_pgyer.py:蒲公英官方api 2.0上傳apk,獲取上傳后的apk信息
3吠各、upload.py: 調(diào)用蒲公英官方上傳api, 將獲取到apk信息發(fā)送到企業(yè)微信群機(jī)器人提醒
4臀突、buildUpdateMsg.txt:更新日志,此內(nèi)容會(huì)更新到蒲公英更新描述和企業(yè)微信群內(nèi)
編譯環(huán)境
1贾漏、安裝python 3版本
2候学、使用pip install requests庫(kù)
3、執(zhí)行python buildApk.py
buildApk.py
# -*- coding: utf-8 -*-
# -*- author: zhoulikai-*-
import subprocess
import os
import time
import platform
from buildScript import upload as UploadUtil
import sys
import shutil
from pathlib import Path
def main():
tip = """
請(qǐng)輸入編譯0:debug 1:release
0纵散、debug
1梳码、release
"""
print(tip)
vSys = input("")
vSysInfo = "Debug"
if vSys == "1":
vSysInfo = "Release"
else:
vSysInfo = "Debug"
print("編譯版本:" + vSysInfo)
print("*********************************編譯開(kāi)始**********************************")
#刪除以前的編譯文件
# apkFiles = os.path.join(os.getcwd(), "releaseApks")
# if (os.path.exists(apkFiles)):
# print("緩存目錄存在")
# for root, dirs, files in os.walk(apkFiles, topdown=False):
# for name in files:
# print(name)
# os.remove(os.path.join(root, name))
# for name in dirs:
# print(name)
# os.rmdir(os.path.join(root, name))
# time.sleep(3)
# os.rmdir(apkFiles)
print("開(kāi)始執(zhí)行 gradlew clean")
systemInfo = platform.system().lower()
print("編譯系統(tǒng):%s" % systemInfo)
commond = os.path.join(os.getcwd(), "gradlew.bat" if systemInfo == "windows" else "gradlew")
# cleanResult = os.system(commond)
# print(cleanResult)
# cleanResult = subprocess.call([commond, "clean"],shell=True)
cleanResult = os.system(commond + " clean")
# cleanResult = 0
if (cleanResult == 0):
print("執(zhí)行 gradlew clean結(jié)束")
print("開(kāi)始執(zhí)行 gradlew assemble")
# assembleResult = subprocess.call([commond, "assemble" + vSysInfo],shell=True)
assembleResult = os.system(commond + " assemble" + vSysInfo)
# assembleResult = 0
if (assembleResult == 0):
print("執(zhí)行g(shù)radlew assemble成功")
print("*********************************編譯結(jié)束**********************************")
UploadUtil.uploadPuGongYing(vSysInfo=vSysInfo)
else:
print("執(zhí)行g(shù)radlew assemble失敗")
else:
print("執(zhí)行g(shù)radlew clean 失敗")
if __name__ == "__main__":
main()
upload_pgyer.py
# -*- coding: utf-8 -*-
# -*- author: LinXunFeng -*-
import time
import requests
# 官方文檔
# https://www.pgyer.com/doc/view/api#fastUploadApp
def _getCOSToken(
api_key,
install_type,
password='',
update_description='',
callback=None
):
"""
獲取上傳的 token
"""
headers = {'enctype': 'multipart/form-data'}
payload = {
'_api_key': api_key, # API Key
'buildType': 'android', # 需要上傳的應(yīng)用類型隐圾,ios 或 android
'buildInstallType': install_type, # (選填)應(yīng)用安裝方式,值為(1,2,3边翁,默認(rèn)為1 公開(kāi)安裝)。1:公開(kāi)安裝硕盹,2:密碼安裝符匾,3:邀請(qǐng)安裝
'buildPassword': password, # (選填) 設(shè)置App安裝密碼,密碼為空時(shí)默認(rèn)公開(kāi)安裝
'buildUpdateDescription': update_description, # (選填) 版本更新描述瘩例,請(qǐng)傳空字符串啊胶,或不傳。
}
try:
r = requests.post('https://www.pgyer.com/apiv2/app/getCOSToken', data=payload, headers=headers)
if r.status_code == requests.codes.ok:
result = r.json()
# print(result)
if callback is not None:
callback(True, result)
else:
if callback is not None:
callback(False, None)
except Exception as e:
print('服務(wù)器暫時(shí)無(wú)法為您服務(wù)', e)
def upload_to_pgyer(path, api_key, install_type=2, password='', update_description='', callback=None):
"""
上傳到蒲公英
:param path: 文件路徑
:param api_key: API Key
:param install_type: 應(yīng)用安裝方式垛贤,值為(1,2,3)焰坪。1:公開(kāi),2:密碼安裝聘惦,3:邀請(qǐng)安裝某饰。默認(rèn)為1公開(kāi)
:param password: App安裝密碼
:param update_description:
:return: 版本更新描述
"""
def getCOSToken_callback(isSuccess, json):
if isSuccess:
_upload_url = json['data']['endpoint']
files = {'file': open(path, 'rb')}
headers = {'enctype': 'multipart/form-data'}
payload = json['data']['params']
print("上傳中...")
try:
r = requests.post(_upload_url, data=payload, files=files, headers=headers)
if r.status_code == 204:
# result = r.json()
# print(result)
print("上傳成功,正在獲取包處理信息善绎,請(qǐng)稍等...")
_getBuildInfo(api_key=api_key, json=json, callback=callback)
else:
print('HTTPError,Code:'+ str(r.status_code))
if callback is not None:
callback(False, None)
except Exception as e:
print('服務(wù)器暫時(shí)無(wú)法為您服務(wù)', e)
else:
pass
_getCOSToken(
api_key=api_key,
install_type=install_type,
password=password,
update_description=update_description,
callback=getCOSToken_callback,
)
def _getBuildInfo(api_key, json, callback=None):
"""
檢測(cè)應(yīng)用是否發(fā)布完成黔漂,并獲取發(fā)布應(yīng)用的信息
"""
time.sleep(3) # 先等個(gè)幾秒,上傳完直接獲取肯定app是還在處理中~
response = requests.get('https://www.pgyer.com/apiv2/app/buildInfo', params={
'_api_key': api_key,
'buildKey': json['data']['params']['key'],
})
if response.status_code == requests.codes.ok:
result = response.json()
code = result['code']
if code == 1247 or code == 1246: # 1246 應(yīng)用正在解析禀酱、1247 應(yīng)用正在發(fā)布中
print("------_getBuildInfo-------")
_getBuildInfo(api_key=api_key, json=json, callback=callback)
else:
if callback is not None:
callback(True, result)
else:
if callback is not None:
callback(False, None)
upload.py
# -*- coding: utf-8 -*-
# -*- author: zhoulikai -*-
from buildScript import upload_pgyer as PgyerUtil
import os
import requests
import json
import platform
#配置信息
os.environ['NO_PROXY']="www.pgyer.com,qyapi.weixin.qq.com"
pgyer_api_key = 'API KEY' # API KEY
pgyer_password = '1234' # 安裝密碼
update_description = ""
webhook_url="企業(yè)微信機(jī)器人webhook地址"
buildTime = ""
userBuild = ""
#讀取更新內(nèi)容
def readUpdateMsg():
f = open('buildUpdateMsg.txt', 'r', encoding='utf-8')
try:
lines = f.readlines()
# print(lines)
return lines
finally:
f.close()
pass
#發(fā)送企業(yè)微信機(jī)器人消息
def send_wechat_msg(content, webhook_url= "你的機(jī)器人webhook地址"):
headers = {"content-type": "application/json"}
data = {"msgtype": "markdown", "markdown": {"content": content, "mentioned_list":["@all"]} }
r = requests.post(headers=headers, url=webhook_url, data=json.dumps(data, ensure_ascii=False).encode('utf-8'), verify=False)
return r.status_code, r.text
#上傳蒲公英平臺(tái)
def uploadPuGongYing(vSysInfo="Release"):
def upload_complete_callback(isSuccess, result):
if isSuccess:
print('上傳完成')
print(result)
_data = result['data']
_url = _data['buildShortcutUrl'].strip() # 去除首尾空格
_appVer = _data['buildVersion']
_buildVer = _data['buildBuildVersion']
# print('鏈接: https://www.pgyer.com/%s'%_url)
# print('版本: %s (build %s)'%(_appVer, _buildVer))
print("*********************************上傳apk結(jié)束**********************************")
_buildName = _data['buildName']
_buildVersion = _data['buildVersion']
_buildVersionNo = _data['buildVersionNo']
_buildFileSize = _data['buildFileSize']
_buildUpdated = _data['buildUpdated']
_buildKey=_data['buildKey'].strip()
_buildUrl = 'https://www.pgyer.com/{buildKey}'.format(buildKey=_buildKey)
_updateDess = update_description.replace('\n', ";")
_buildQRCodeURL = _data['buildQRCodeURL']
_buildSystem = platform.system().lower()
content = """
應(yīng)用更新提醒
您的應(yīng)用上傳了新版本
應(yīng)用名稱:{buildName}
應(yīng)用類型:{buildPlatform}
版本信息:{buildVersion}(Build {buildVersionNo})
應(yīng)用大芯媸亍:{buildFileSize}M
安裝密碼:{pgyerPassword}
編譯系統(tǒng):{buildSystem}
編譯用戶: {userBuild}
編譯類型:{vSysInfo}
編譯時(shí)間: {buildTime}
更新時(shí)間:{buildUpdated}
更新內(nèi)容:{update_description}
點(diǎn)擊查看應(yīng)用:[{buildUrl}]({buildUrl})
下載二維碼:![下載二維碼]({buildQRCodeURL})
""".format(buildName=_buildName,
buildPlatform="Android",
buildVersion=_buildVersion,
buildVersionNo=_buildVer,
buildTime=buildTime,
buildSystem=_buildSystem,
buildFileSize=round(int(_buildFileSize) / 1024 / 1024, 2),
pgyerPassword=pgyer_password,
buildUpdated=_buildUpdated,
update_description=_updateDess,
buildUrl=_buildUrl,
userBuild=userBuild,
vSysInfo=vSysInfo,
buildQRCodeURL=_buildQRCodeURL)
print(content)
print("*********************************企業(yè)微信提醒開(kāi)始**********************************")
status_code, text = send_wechat_msg(content=content, webhook_url=webhook_url)
print("微信提醒", status_code, text)
print("*********************************企業(yè)微信提醒結(jié)束**********************************")
else:
print('上傳失敗')
rootDir = os.path.abspath(".")
print("編譯的根目錄:%s" %rootDir)
#buildApkPath = "releaseApks/" + vSysInfo.lower()
buildApkPath = "app/build/outputs/apk/" + vSysInfo.lower()
apkDir = os.path.join(rootDir, buildApkPath)
print("編譯的apk路徑:%s" % apkDir)
fileList = os.listdir(apkDir)
fileList = [os.path.join(apkDir, f) for f in fileList if f.endswith(".apk")]
print(fileList)
size = len(fileList)
if size != 1:
print("編譯文件錯(cuò)誤")
else:
f = fileList[0]
print("要上傳的文件 %s" %f)
app_path = f
fileName = os.path.basename(app_path)
print("要上傳的文件路徑:%s" %fileName)
files = fileName.replace(".apk", "").split('_')
buildTime = files[3][0:4] + "-" + files[3][4:6] + "-" + files[3][6:] + " " + files[4][0:2] + ":" + files[4][2:4] + ":" + files[4][4:]
print("編譯時(shí)間:%s" %buildTime)
userBuild = os.getlogin()
print("編譯用戶名:%s" %userBuild)
updateMsgs = readUpdateMsg()
update_description = ""
print("*********************************更新內(nèi)容開(kāi)始**********************************")
for msg in updateMsgs:
update_description += msg
print(msg)
print("*********************************更新內(nèi)容結(jié)束**********************************")
print("*********************************上傳apk開(kāi)始**********************************")
PgyerUtil.upload_to_pgyer(
path = app_path,
api_key = pgyer_api_key,
password=pgyer_password,
update_description=update_description,
callback=upload_complete_callback
)
#編譯腳本執(zhí)行入口
def main():
uploadPuGongYing()
if __name__ == "__main__":
main()
注意 apk文件名稱定義,目的腳本獲取到編譯時(shí)間及編譯類型
android.applicationVariants.all { variant ->
variant.outputs.all {output->
// output.getPackageApplication().outputDirectory = new File(project.rootDir.absolutePath + "/releaseApks/${buildType.name}")
def buildTime = new Date().format("YYYYMMdd_HHmmss", TimeZone.getTimeZone("GMT+08:00"))
outputFileName = "App_${defaultConfig.versionName}_${buildType.name}_${buildTime}.apk"
}
}