编译脚本组成
1、buildApk.py:位于根目录,调用不同平台shell的gradlew clean 和 根据用户选择gradlew assembleRelease或者 gradlew assembleDebug ,调用UploadUtil.uploadPuGongYing(vSysInfo=vSysInfo)上传到蒲公英平台
2、upload_pgyer.py:蒲公英官方api 2.0上传apk,获取上传后的apk信息
3、upload.py: 调用蒲公英官方上传api, 将获取到apk信息发送到企业微信群机器人提醒
4、buildUpdateMsg.txt:更新日志,此内容会更新到蒲公英更新描述和企业微信群内
编译环境
1、安装python 3版本
2、使用pip install requests库
3、执行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 = """
请输入编译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("*********************************编译开始**********************************")
#删除以前的编译文件
# 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("开始执行 gradlew clean")
systemInfo = platform.system().lower()
print("编译系统:%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("执行 gradlew clean结束")
print("开始执行 gradlew assemble")
# assembleResult = subprocess.call([commond, "assemble" + vSysInfo],shell=True)
assembleResult = os.system(commond + " assemble" + vSysInfo)
# assembleResult = 0
if (assembleResult == 0):
print("执行gradlew assemble成功")
print("*********************************编译结束**********************************")
UploadUtil.uploadPuGongYing(vSysInfo=vSysInfo)
else:
print("执行gradlew assemble失败")
else:
print("执行gradlew 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', # 需要上传的应用类型,ios 或 android
'buildInstallType': install_type, # (选填)应用安装方式,值为(1,2,3,默认为1 公开安装)。1:公开安装,2:密码安装,3:邀请安装
'buildPassword': password, # (选填) 设置App安装密码,密码为空时默认公开安装
'buildUpdateDescription': update_description, # (选填) 版本更新描述,请传空字符串,或不传。
}
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('服务器暂时无法为您服务', 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: 应用安装方式,值为(1,2,3)。1:公开,2:密码安装,3:邀请安装。默认为1公开
: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("上传成功,正在获取包处理信息,请稍等...")
_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('服务器暂时无法为您服务', 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):
"""
检测应用是否发布完成,并获取发布应用的信息
"""
time.sleep(3) # 先等个几秒,上传完直接获取肯定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 应用正在解析、1247 应用正在发布中
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="企业微信机器人webhook地址"
buildTime = ""
userBuild = ""
#读取更新内容
def readUpdateMsg():
f = open('buildUpdateMsg.txt', 'r', encoding='utf-8')
try:
lines = f.readlines()
# print(lines)
return lines
finally:
f.close()
pass
#发送企业微信机器人消息
def send_wechat_msg(content, webhook_url= "你的机器人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
#上传蒲公英平台
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结束**********************************")
_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 = """
应用更新提醒
您的应用上传了新版本
应用名称:{buildName}
应用类型:{buildPlatform}
版本信息:{buildVersion}(Build {buildVersionNo})
应用大小:{buildFileSize}M
安装密码:{pgyerPassword}
编译系统:{buildSystem}
编译用户: {userBuild}
编译类型:{vSysInfo}
编译时间: {buildTime}
更新时间:{buildUpdated}
更新内容:{update_description}
点击查看应用:[{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("*********************************企业微信提醒开始**********************************")
status_code, text = send_wechat_msg(content=content, webhook_url=webhook_url)
print("微信提醒", status_code, text)
print("*********************************企业微信提醒结束**********************************")
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("编译文件错误")
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("编译时间:%s" %buildTime)
userBuild = os.getlogin()
print("编译用户名:%s" %userBuild)
updateMsgs = readUpdateMsg()
update_description = ""
print("*********************************更新内容开始**********************************")
for msg in updateMsgs:
update_description += msg
print(msg)
print("*********************************更新内容结束**********************************")
print("*********************************上传apk开始**********************************")
PgyerUtil.upload_to_pgyer(
path = app_path,
api_key = pgyer_api_key,
password=pgyer_password,
update_description=update_description,
callback=upload_complete_callback
)
#编译脚本执行入口
def main():
uploadPuGongYing()
if __name__ == "__main__":
main()
注意 apk文件名称定义,目的脚本获取到编译时间及编译类型
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"
}
}