本文已受權code小生獨家發佈,轉載請註明出處https://juejin.im/post/5a0675b851882531d016ded1python
在開發的過程當中,不少時候完成了一個功能的開發,每每須要打包給測試進行測試,以前就是打個包,要麼是經過USB進行安裝,要麼就是打個包經過QQ給測試發送過去,後來接觸到Jenkins,發現能夠進行持續集成,可是不少時候每每只是改了一個很小的功能,好比說字體,或者顏色之類的,Jenkins就有點大材小用了,這個時候,總想着要是可以經過腳本進行自動打包上傳至服務器而且生成一個下載的二維碼就行了,最近學習了Python而且也接觸了fir這個第三方託管工具,發現,夢想仍是要有的,萬一實現了呢?下面介紹一下若是利用Python跟fir這兩個工具來實現夢想的。android
Python是一門高級編程語言,並且是一門動態語言,能夠用來編寫各類腳原本幫助人們從一些重複性的操做中解放出來,固然也能夠用來開發網站,不過實現Python的自動打包上傳只須要準備:ios
fir是一個第三方的託管網站, fir.im 爲開發者提供測試應用極速發佈,應用崩潰實時分析、用戶反饋收集等一系列開發測試效率工具服務,因此須要準備的是git
fir的註冊地址是fir註冊地址,不過免費的應用天天提供的免費下載次數是100次github
Python如今大體分爲兩個大的版本:2.X以及3.X,不過Python的3.X版本有些語法是不向下兼容的,因爲對Python不是很熟悉,因此仍是選擇了2.7版原本配置環境,官網下載地址是Python官網,我是Windows系統,因此下載的安裝包,而後下載了一個編輯Python的IDE名字是PyCharm,之因此選擇IDE沒有用SublimeText等文本編輯器是由於windows下的環境配置比較麻煩,並且剛開始有IDE的提示不至於在一些小問題上卡殼,固然若是你願意去配置文本編輯器,我推薦SublimeText,提供了不少插件。編程
服務器地址:http://api.fir.im/apps() 參數列表json
名稱 | 類型 | 標題 | 說明 |
---|---|---|---|
type | String | 是 | ios 或者 android(發佈新應用時必填) |
bundle_id | String | 是 | App 的 bundleId(發佈新應用時必填 |
api_token | String | 是 | 長度爲 32, 用戶在 fir 的 api_token |
Postman調試 windows
Python腳本編寫api
import requests
data = {'type': 'android', 'bundle_id': 'com.wustor.pythopackage',
'api_token': '9812fa28e4dac156673a5e45e7119631'}
req = requests.post(url='http://api.fir.im/apps', data=data)
print req.content
複製代碼
運行測試數組
{
"id": "5a059de3959d6961bb000257",
"type": "android",
"short": "asxn",
"cert": {
"icon": {
"key": "5cc5942ccb1b7b86bd39c0f3ad84ea0c3e93a5e7",
"token": "太長,以文字代替",
"upload_url": "https://upload.qbox.me"
},
"binary": {
"key": "63b159e5456d6151ace59ed7322d6942b05a4c6e.apk",
"token": "太長,以文字代替",
"upload_url": "https://upload.qbox.me"
},
"mqc": {
"total": 5,
"used": 0,
"is_mqc_availabled": true
},
"support": "qiniu",
"prefix": "x:"
}
}
複製代碼
服務器地址:upload_url
binary字段對應的binary
參數列表
名稱 | 類型 | 標題 | 說明 |
---|---|---|---|
key | String | 是 | binary字段對應的key |
token | String | 是 | binary字段對應的token |
file | File | 是 | 安裝包文件 |
x:name | String | 是 | 應用名稱 |
x:version | String | 是 | 版本號 |
x:build | String | 是 | Build 號 |
x:changelog | String | 是 | 長度爲 32, 用戶在 fir 的 api_token |
Postman進行測試
Python腳本編寫
# coding=utf-8
import requests
try:
print("上傳apk")
apk_path = 'F:/PythonDemo/Demo/app-release.apk'
file = {'file': open(apk_path, 'rb')}
param = {"key": '61a53809c7b58d8b68e537c3d4831b01325b1f0b.apk',
"token": '你本身的token',
"x:name": '測試',
"x:version": '1.0', "x:build": '1', "x:changelog": '暫無更新'}
req = requests.post('https://upload.qbox.me', files=file, data=param, verify=False)
print 'success:' + req.content
except Exception as e:
print'error:' + e
複製代碼
運行測試
{"is_completed":true}
複製代碼
在fir界面查看結果
界面顯示已經上傳成功,可是發現沒有Logo,我開始覺得他會自動提取apk中的logo,實際上並無,可是它提供了上傳logo的接口,如今來繼續上傳logo上傳應用圖標
服務器地址:upload_url
icon字段對應的upload_url
參數列表
名稱 | 類型 | 標題 | 說明 |
---|---|---|---|
key | String | 是 | binary字段對應的 key |
token | String | 是 | binary字段對應的 token |
file | File | 是 | icon |
Postman測試
fir查看上傳結果
這裏用了一張微信朋友圈的logo上傳,已經成功替換。
編寫Python腳本
# coding=utf-8
import requests
try:
print("上傳icon")
icon_path = 'F:/PythonDemo/Demo/demo.png'
file = {'file': open(icon_path, 'rb')}
param = {"key": 'd1bca0636623f17782d9f851aa9e08c77f875a62',
'token': '替換成你本身的token'
}
req = requests.post('https://upload.qbox.me', files=file, data=param, verify=False)
print 'success:' + req.content
except Exception as e:
print'error:' + e
複製代碼
運行結果
{"is_completed":true}
複製代碼
編寫gradle腳本
task debugToFir {
dependsOn 'assembleDebug'
doLast {
def upUrl = "http://api.fir.im/apps"
def appName = "Python2"
def bundleId = project.android.defaultConfig.applicationId
def verName = project.android.defaultConfig.versionName
def apiToken = "9812fa28e4dac156673a5e45e7119631"
def iconPath = "F:/PythoPackage/app/src/main/res/mipmap-xxhdpi/ic_launcher.png"
def apkPath = "F:/PythoPackage/app/build/outputs/apk/debug/app-debug.apk"
def buildNumber = project.android.defaultConfig.versionCode
def changeLog = "版本更新日誌"
//執行Python腳本
def process = "python upToFir.py ${upUrl} ${appName} ${bundleId} ${verName} ${apiToken} ${iconPath} ${apkPath} ${buildNumber} ${changeLog}".execute()
println("開始上傳至fir")
//獲取Python腳本日誌,便於出錯調試
ByteArrayOutputStream result = new ByteArrayOutputStream()
def inputStream = process.getInputStream()
byte[] buffer = new byte[1024]
int length
while ((length = inputStream.read(buffer)) != -1) {
result.write(buffer, 0, length)
}
println(result.toString("UTF-8"))
println "上傳結束 "
}
}
複製代碼
該腳本放在app/build.gradle中的android目錄下
統一Python腳本
# coding=utf-8
# encoding = utf-8
import requests
import sys
def upToFir():
# 打印傳遞過來的參數數組長度,便於校驗
print 'the argLength--->:' + len(sys.argv)
upUrl = sys.argv[1]
appName = sys.argv[2]
bundleId = sys.argv[3]
verName = sys.argv[4]
apiToken = sys.argv[5]
iconPath = sys.argv[6]
apkPath = sys.argv[7]
buildNumber = sys.argv[8]
changeLog = sys.argv[9]
queryData = {'type': 'android', 'bundle_id': bundleId, 'api_token': apiToken}
iconDict = {}
binaryDict = {}
# 獲取上傳信息
try:
response = requests.post(url=upUrl, data=queryData)
json = response.json()
iconDict = (json["cert"]["icon"])
binaryDict = (json["cert"]["binary"])
except Exception as e:
print('query:' + e)
# 上傳apk
try:
file = {'file': open(apkPath, 'rb')}
param = {"key": binaryDict['key'],
'token': binaryDict['token'],
"x:name": appName,
"x:version": verName,
"x:build": buildNumber,
"x:changelog": changeLog}
req = requests.post(url=binaryDict['upload_url'], files=file, data=param, verify=False)
print 'success_apk:' + req.content
except Exception as e:
print'error_apk:' + e
# 上傳logo
try:
file = {'file': open(iconPath, 'rb')}
param = {"key": iconDict['key'],
'token': iconDict['token']}
req = requests.post(url=iconDict['upload_url'], files=file, data=param, verify=False)
print 'success_icon:' + req.content
except Exception as e:
print'error_icon:' + e
if __name__ == '__main__':
upToFir()
複製代碼
前面的三個python腳本的參數都是寫死的,因此須要改變成動態從gradle中獲取,獲取的時候先判斷一下數組長度,看看是否是跟以前約定的同樣
總體進行測試
這個時候修改一下apk的一些參數,跟logo
versionCode 3
versionName "1.2"
iconPath=ic_launcher.png
appName="python"
複製代碼
執行gradle命令 gradlew debugToFir,運行結果
開始上傳至fir
http://api.fir.im/apps
success_apk:{"is_completed":true}
success_icon:{"is_completed":true}
上傳結束 with value 0
複製代碼
運行成功,到官網查看結果
完美,簡單,之後簡單的打包就用一行代碼就能夠搞定了,吼吼。
其實Python的語法很簡潔,做爲一門動態語言,不須要像Java定義各類類型變量,gradle的語法其實也同樣,掌握這兩種語言的基本用法,有助於更高效的開發Android。