Android gradle打包并自動上傳的方法
簡介
這篇文章主要介紹Android用gradle打包,并且調(diào)用python腳本將打包好的apk上傳到fir.im供相關(guān)人員下載,對于學(xué)習(xí)gradle 打包和python 幾個常用網(wǎng)絡(luò)庫有一定幫助
關(guān)鍵字 :Android Gradle Python fir.im
1 開發(fā)前準(zhǔn)備
開發(fā)前需要下載 AndroidStudio ,gradle(3.3版本),python3.6,Curl,pycurl
準(zhǔn)備fir.im賬號一個,有賬號對應(yīng)的apitoken,具體fir.im的細節(jié)可查看文檔fir.im
開發(fā)環(huán)境為macOS,windows推薦把pycurl部分全部替換為requests,即上傳apk部分代碼換為上傳圖標(biāo)的那種方式,詳細見代碼
2 Gradle 腳本編寫
我們腳本需要做的事情就是在APK打包完成以后,把apk的路徑傳遞給python腳本即可,如何保證打包好了,就用gradle的dependsOn方法,例如打debug包,我們就可以寫一個task ,這個task dependsOn ‘a(chǎn)ssembleDebug',這樣這個task調(diào)用時,會先執(zhí)行assembleDebug,然后在執(zhí)行里面的代碼,即符合我們的需要
具體代碼
//這個task 需要放在 app/build.gradle文件中的android 代碼塊里
task assemblewithlog {
dependsOn 'assembleDebug'
doLast {
//這個需要配置一下,app的圖標(biāo)
def appicon = "app/src/main/res/drawable/icon.png"
//這個需要配置一下,app的輸出到fir.im的名稱
def outId = "yitiji_Debug"
//取 apk的版本名和apk的輸出文件目錄
def verName = project.android.defaultConfig.versionName;
def apkpath = applicationVariants.first().outputs.first().outputFile
//調(diào)用python腳本 這個腳本需要放在工程目錄下
def process = "python3 uploadfirim.py ${outId} ${verName} ${appicon} ${apkpath}".execute()
// Wait till the process completes before continuing
println("上傳apk中")
//將python代碼里面打印的內(nèi)容在gradle窗口中打印出來
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"));
//阻塞gradle代碼直到python代碼執(zhí)行結(jié)束
int exitValue = process.waitFor()
println "上傳結(jié)束 with value $exitValue"
}
}
3 python腳本的編寫
這個python腳本有點學(xué)習(xí)的內(nèi)容,所以使用了 urllib ,requests,pycurl三個網(wǎng)絡(luò)請求庫,實際上只用一種就好了。這里關(guān)鍵是需要了解fir.im上傳的請求格式和響應(yīng),細節(jié)可以看文檔fir.im,主要是先將apk的標(biāo)識信息和用戶的apitoken傳給fir.im,它會響應(yīng)文件上傳的地址和圖標(biāo)上傳的地址,然后將對應(yīng)的文件和信息傳入返回的地址即可,最后在通過apk的標(biāo)識信息和用戶的apitoken可以查詢到此apk在fir.im對應(yīng)的下載頁面
那么就安裝這三步來講好了
3.1 查詢上傳地址
官方文檔 如下
調(diào)用示例
curl -X "POST" "http://api.fir.im/apps" \
-H "Content-Type: application/json" \
-d "{\"type\":\"android\", \"bundle_id\":\"xx.x\", \"api_token\":\"aa\"}"
響應(yīng)示例
# status: 201
{
"id": "5592ceb6537069f2a8000000",
"type": "ios",
"short": "yk37",
"cert": {
"icon": {
"key": "xxxxx",
"token": "xxxxxx",
"upload_url": "http://upload.qiniu.com"
},
"binary": {
"key": "xxxxx",
"token": "xxxxxx",
"upload_url": "http://upload.qiniu.com"
}
}
}
所以按照文檔寫python3 代碼如下
#encoding = utf-8
import traceback
from urllib import request
from urllib import parse
import requests
import pycurl
import json
from io import BytesIO
import time
import sys
def uploadtofirim():
minlen = 5
#檢查參數(shù)傳遞,定義好按照 name version 圖標(biāo)路徑 apk路徑 apitoken 的順序傳遞參數(shù)
syslen = len(sys.argv)
if syslen < minlen:
print("傳遞參數(shù)有誤")
return
if syslen > 5:
apitoken = sys.argv[5]
else:
#這是一個無效的token,只是為了展示用,需要替換為你自己的fir.imtoken
apitoken = "7a15a28c75005akkkklllle051c71"
appname = sys.argv[1]
appversion = sys.argv[2]
iconpath = sys.argv[3]
apkpath = sys.argv[4]
#利用urllib 請求并獲取響應(yīng),數(shù)據(jù)格式見fir.im文檔
data = parse.urlencode({'type': 'android', 'bundle_id': appname, 'api_token': apitoken})
datas = data.encode('utf-8')
req = request.Request(url='http://api.fir.im/apps', data=datas, method='POST')
icondict = {}
binarydict = {}
try:
with request.urlopen(req) as f:
strdec = f.read().decode('utf-8')
resjson = json.loads(strdec)
#將請求的結(jié)果存起來后面用
icondict = (resjson["cert"]["icon"])
binarydict = (resjson["cert"]["binary"])
except:
print("讀取地址失敗")
pass
3.2 上傳圖標(biāo)和apk
之前獲取了路徑,接下來將文件傳上去,注意 python3對于https的請求有坑,如果代碼報ssl錯誤,執(zhí)行python3 按照目錄下的Install Certificates.command文件 ,路徑參考 /Applications/Python 3.6/Certificates.command官方文檔如下,細節(jié)查閱官網(wǎng)
調(diào)用示例
curl -F "key=xxxxxx" \
-F "token=xxxxx" \
-F "file=@aa.apk" \
-F "x:name=aaaa" \
-F "x:version=a.b.c" \
-F "x:build=1" \
-F "x:release_type=Adhoc" \ #type=ios 使用
-F "x:changelog=first" \
https://up.qbox.me
響應(yīng)示例
# status: 201
{ "is_completed": true }
所以對應(yīng)的py腳本如下
#接上面的py代碼,復(fù)制時注意下格式和縮進
try:
local_filename = iconpath
c = pycurl.Curl()
print("上傳圖片")
files = {'file': open(local_filename, 'rb')}
paramdata = {'key': icondict["key"],"token":icondict["token"]}
#用 requests庫上傳圖標(biāo)文件并讀取響應(yīng),verify=False是因為上傳地址是https,不這樣寫會報錯
res = requests.post(icondict["upload_url"], files=files, data=paramdata,verify=False)
print(res.text)
local_apkfilename = apkpath
timenow = str('time :' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
#用 pycurl庫上傳apk文件并讀取響應(yīng)
c.setopt(c.URL, binarydict["upload_url"])
c.setopt(c.HTTPPOST, [
("file", (c.FORM_FILE, local_apkfilename)),
("key", binarydict["key"]),
("token", binarydict["token"]),
("x:name", appname),
("x:version", appversion),
("x:build", '1'),
("x:changelog", timenow)
])
print("上傳apk")
c.perform()
c.close()
print("上傳成功")
except Exception as e:
print(e)
print("上傳文件失敗,請檢查")
return
3.3獲得apk文件的下載頁面
apk上傳好了以后會生成下載分享頁面,可以直接通過get請求拿到
官方文檔
請求示例
curl http://api.fir.im/apps/latest/xxx?api_token=xxx #使用 `id` 請求
curl http://api.fir.im/apps/latest/im.fir.xxx?api_token=xxx&type=android #根據(jù)`bundle_id` 獲取更新
響應(yīng)數(shù)據(jù)
# status: 200
{
"name": "fir.im",
"version": "1.0",
"changelog": "更新日志",
"versionShort": "1.0.5",
"build": "6",
"installUrl": "http://download.fir.im/v2/app/install/xxxxxxxxxxxxxxxxxxxx?download_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"install_url": "http://download.fir.im/v2/app/install/xxxxxxxxxxxxxxxx?download_token=xxxxxxxxxxxxxxxxxxxxxxxxxxxx", # 新增字段
"update_url": "http://fir.im/fir", # 新增字段
"binary": {
"fsize": 6446245
}
}
我們用的就是bundle_id,這個bundleid就是我們gradle傳進去的名字,返回的update_url 就是分享apk的頁面
所以py代碼如下
#接上面的py代碼,復(fù)制時注意下格式和縮進
queryurl='http://api.fir.im/apps/latest/%s?api_token=%s&type=android'%(appname,apitoken)
print(queryurl)
req = request.Request(url=queryurl,method="GET")
try:
with request.urlopen(req) as f:
strdec = f.read().decode('utf-8')
resjson = json.loads(strdec)
print("apk下載地址 " + resjson["update_url"])
except Exception as e:
print(e)
traceback.print_exc()
print("讀取地址失敗")
pass
完整的py代碼如下
#encoding = utf-8
import traceback
from urllib import request
from urllib import parse
import requests
import pycurl
import json
from io import BytesIO
import time
import sys
def uploadtofirim():
minlen = 5
syslen = len(sys.argv)
if syslen < minlen:
print("傳遞參數(shù)有誤")
return
if syslen > 5:
apitoken = sys.argv[5]
else:
apitoken = "7akkkkkkkkkkkk1c71"
appname = sys.argv[1]
appversion = sys.argv[2]
iconpath = sys.argv[3]
apkpath = sys.argv[4]
data = parse.urlencode({'type': 'android', 'bundle_id': appname, 'api_token': apitoken})
datas = data.encode('utf-8')
req = request.Request(url='http://api.fir.im/apps', data=datas, method='POST')
icondict = {}
binarydict = {}
try:
with request.urlopen(req) as f:
strdec = f.read().decode('utf-8')
resjson = json.loads(strdec)
icondict = (resjson["cert"]["icon"])
binarydict = (resjson["cert"]["binary"])
except:
print("讀取地址失敗")
pass
try:
local_filename = iconpath
c = pycurl.Curl()
print("上傳圖片")
files = {'file': open(local_filename, 'rb')}
paramdata = {'key': icondict["key"],"token":icondict["token"]}
res = requests.post(icondict["upload_url"], files=files, data=paramdata,verify=False)
print(res.text)
local_apkfilename = apkpath
timenow = str('time :' + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
c.setopt(c.URL, binarydict["upload_url"])
c.setopt(c.HTTPPOST, [
("file", (c.FORM_FILE, local_apkfilename)),
("key", binarydict["key"]),
("token", binarydict["token"]),
("x:name", appname),
("x:version", appversion),
("x:build", '1'),
("x:changelog", timenow)
])
print("上傳apk")
c.perform()
c.close()
print("上傳成功")
except Exception as e:
print(e)
print("上傳文件失敗,請檢查")
return
queryurl='http://api.fir.im/apps/latest/%s?api_token=%s&type=android'%(appname,apitoken)
print(queryurl)
req = request.Request(url=queryurl,method="GET")
try:
with request.urlopen(req) as f:
strdec = f.read().decode('utf-8')
resjson = json.loads(strdec)
print("apk下載地址 " + resjson["update_url"])
except Exception as e:
print(e)
traceback.print_exc()
print("讀取地址失敗")
pass
# appid vesion icon apk apitoken
if __name__ == '__main__':
uploadtofirim()
這樣就好了
在Android studio對應(yīng)的工程里面執(zhí)行代碼 gradle assemblewithlog
就開始打包debug并上傳到fir.im了

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Android apk 項目一鍵打包并上傳到蒲公英的實現(xiàn)方法
- Android Studio新建工程默認(rèn)在build.gradle中加入maven阿里源的問題
- 解決android studio 3.0 加載項目過慢問題--maven倉庫選擇
- android 上傳aar到私有maven服務(wù)器的示例
- Android 如何實現(xiàn)exclude aar包中的某個jar包
- android studio編譯jar包或者aar包的方法教程詳解
- Android Studio打包jar及aar包的方法
- Android帶依賴樹的aar是如何生成的(推薦)
- Android Studio 多層級 Module 對 aar 引用問題解決方法
- Android Studio中生成aar文件及本地方式使用aar文件的方法
- Android打包上傳AAR文件到Maven倉庫的示例
相關(guān)文章
Android熱更新開源項目Tinker集成實踐總結(jié)
最近項目集成了Tinker,開始認(rèn)為集成會比較簡單,但是在實際操作的過程中還是遇到了一些問題,本文就會介紹在集成過程大家基本會遇到的主要問題。下面跟著小編一起來看下吧2017-01-01
Android開發(fā)中調(diào)用系統(tǒng)相冊上傳圖片到服務(wù)器OPPO等部分手機上出現(xiàn)短暫的顯示桌面問題的解決方法
這篇文章主要介紹了Android開發(fā)中調(diào)用系統(tǒng)相冊上傳圖片到服務(wù)器OPPO等部分手機上出現(xiàn)短暫的顯示桌面問題的解決方法,需要的朋友可以參考下2016-12-12
利用Kotlin如何實現(xiàn)Android開發(fā)中的Parcelable詳解
這篇文章主要給大家介紹了關(guān)于利用Kotlin如何實現(xiàn)Android開發(fā)中的Parcelable的相關(guān)資料,并且給大家介紹了關(guān)于Kotlin使用parcelable出現(xiàn):BadParcelableException: Parcelable protocol requires a Parcelable.Creator...問題的解決方法,需要的朋友可以參考下。2017-12-12
Android Service中使用Toast無法正常顯示問題的解決方法
這篇文章主要介紹了Android Service中使用Toast無法正常顯示問題的解決方法,分析了Service中Toast無法正常顯示的原因與相關(guān)的解決方法,具有一定參考借鑒價值,需要的朋友可以參考下2016-10-10
FragmentTabHost FrameLayout實現(xiàn)底部導(dǎo)航欄
這篇文章主要為大家詳細介紹了FragmentTabHost和FrameLayout實現(xiàn)底部導(dǎo)航欄,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03
Android Studio和阿里云數(shù)據(jù)庫實現(xiàn)一個遠程聊天程序
本文主要介紹了Android Studio和阿里云數(shù)據(jù)庫實現(xiàn)一個遠程聊天程序,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11

