最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Python的iOS自動(dòng)化打包實(shí)例代碼

 更新時(shí)間:2018年11月22日 08:40:09   作者:lxiaok  
這篇文章主要給大家介紹了關(guān)于Python的iOS自動(dòng)化打包的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

前言

這段時(shí)間剛剛學(xué)習(xí)了一段時(shí)間的Python,加上自己是做iOS開(kāi)發(fā)的,就想著用Python來(lái)做一個(gè)自動(dòng)化打包,可以自動(dòng)完成打包,上傳到蒲公英,并且發(fā)送郵箱給測(cè)試人員.

一是可以減少打包功夫,二來(lái)可以練練手,結(jié)合自己的工作來(lái)輸出一點(diǎn)東西.廢話不多說(shuō),直接上代碼...

原理

就是使用xcodebuild來(lái)控制Xcode進(jìn)行一系列的操作,從而完成打包的操作.


為什么要做這個(gè)?

在我們?nèi)粘i_(kāi)發(fā)的時(shí)候,特別是在內(nèi)部測(cè)試的時(shí)間,有可能需要頻繁的打包,打包的工作比較繁瑣,需要等待點(diǎn)擊下一步,選擇之類(lèi),影響了開(kāi)發(fā)的節(jié)奏.(開(kāi)玩笑,我能有啥節(jié)奏...), 為什么不能直接運(yùn)行,然后完成所有的操作呢?

思路:

從網(wǎng)上查找了一些關(guān)于xcodebuild來(lái)打包的資料,從而得到:

  1. 找到對(duì)應(yīng)的項(xiàng)目
  2. clean項(xiàng)目
  3. archive項(xiàng)目
  4. export IPA
  5. 上傳蒲公英
  6. 發(fā)送郵件
  7. 收工

思路有了,動(dòng)手起來(lái).

運(yùn)行環(huán)境

Python, Xcode

這些需要大家直接去搭建好環(huán)境...

準(zhǔn)備工作

  • 下載安裝pycharm(這只是我開(kāi)發(fā)Python的工具而已,大家可以根據(jù)自己喜歡的來(lái)選擇)
  • 注冊(cè)并認(rèn)證蒲公英(不認(rèn)證的話,是不能上傳的)
  • 郵箱開(kāi)啟POP3/SMTP服務(wù)(我使用的是QQ郵箱),記錄下16位授權(quán)碼
  • 一個(gè)ExportOptions.plist文件, 這個(gè)下面會(huì)解釋為什么需要還有怎么生成!
  • 一份iOS項(xiàng)目代碼→_→

完整代碼

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time : 2018/11/14 11:04 AM
# @Author : liangk
# @Site :
# @File : auto_archive_ios.py
# @Software: PyCharm


import os
import requests
import webbrowser
import subprocess
import time
import smtplib
from email.mime.text import MIMEText
from email import encoders
from email.header import Header
from email.utils import parseaddr, formataddr

project_name = 'TestArchive' # 項(xiàng)目名稱(chēng)
archive_workspace_path = '/Users/用戶/Desktop/TestArchive' # 項(xiàng)目路徑
export_directory = 'archive' # 輸出的文件夾
ipa_download_url = 'https://www.pgyer.com/XXX' #蒲公英的APP地址

# 蒲公英賬號(hào)USER_KEY、API_KEY
USER_KEY = 'XXXXXXXXXXXXXXXXXXXX'
API_KEY = 'XXXXXXXXXXXXXXXXXXXX'

from_address = 'XXXXXXXXXXXXXXXXXXXX@qq.com' # 發(fā)送人的地址
password = 'XXXXXXXXXXXXXXXXXXXX' # 郵箱密碼換成他提供的16位授權(quán)碼
to_address = 'XXXXXXXXXXXXXXXXXXXX@qq.com' # 收件人地址,可以是多個(gè)的
smtp_server = 'smtp.qq.com' # 因?yàn)槲沂鞘褂肣Q郵箱..


class AutoArchive(object):
"""自動(dòng)打包并上傳到蒲公英,發(fā)郵件通知"""

def __init__(self):
pass

def clean(self):
print("\n\n===========開(kāi)始clean操作===========")
start = time.time()
clean_command = 'xcodebuild clean -workspace %s/%s.xcworkspace -scheme %s -configuration Release' % (
archive_workspace_path, project_name, project_name)
clean_command_run = subprocess.Popen(clean_command, shell=True)
clean_command_run.wait()
end = time.time()
# Code碼
clean_result_code = clean_command_run.returncode
if clean_result_code != 0:
print("=======clean失敗,用時(shí):%.2f秒=======" % (end - start))
else:
print("=======clean成功,用時(shí):%.2f秒=======" % (end - start))
self.archive()

def archive(self):
print("\n\n===========開(kāi)始archive操作===========")

# 刪除之前的文件
subprocess.call(['rm', '-rf', '%s/%s' % (archive_workspace_path, export_directory)])
time.sleep(1)
# 創(chuàng)建文件夾存放打包文件
subprocess.call(['mkdir', '-p', '%s/%s' % (archive_workspace_path, export_directory)])
time.sleep(1)

start = time.time()
archive_command = 'xcodebuild archive -workspace %s/%s.xcworkspace -scheme %s -configuration Release -archivePath %s/%s' % (
archive_workspace_path, project_name, project_name, archive_workspace_path, export_directory)
archive_command_run = subprocess.Popen(archive_command, shell=True)
archive_command_run.wait()
end = time.time()
# Code碼
archive_result_code = archive_command_run.returncode
if archive_result_code != 0:
print("=======archive失敗,用時(shí):%.2f秒=======" % (end - start))
else:
print("=======archive成功,用時(shí):%.2f秒=======" % (end - start))
# 導(dǎo)出IPA
self.export()

def export(self):
print("\n\n===========開(kāi)始export操作===========")
print("\n\n==========請(qǐng)你耐心等待一會(huì)~===========")
start = time.time()
# export_command = 'xcodebuild -exportArchive -archivePath /Users/liangk/Desktop/TestArchive/myArchivePath.xcarchive -exportPath /Users/liangk/Desktop/TestArchive/out -exportOptionsPlist /Users/liangk/Desktop/TestArchive/ExportOptions.plist'
export_command = 'xcodebuild -exportArchive -archivePath %s/%s.xcarchive -exportPath %s/%s -exportOptionsPlist %s/ExportOptions.plist' % (
archive_workspace_path, export_directory, archive_workspace_path, export_directory, archive_workspace_path)
export_command_run = subprocess.Popen(export_command, shell=True)
export_command_run.wait()
end = time.time()
# Code碼
export_result_code = export_command_run.returncode
if export_result_code != 0:
print("=======導(dǎo)出IPA失敗,用時(shí):%.2f秒=======" % (end - start))
else:
print("=======導(dǎo)出IPA成功,用時(shí):%.2f秒=======" % (end - start))
# 刪除archive.xcarchive文件
subprocess.call(['rm', '-rf', '%s/%s.xcarchive' % (archive_workspace_path, export_directory)])
self.upload('%s/%s/%s.ipa' % (archive_workspace_path, export_directory, project_name))

def upload(self, ipa_path):
print("\n\n===========開(kāi)始上傳蒲公英操作===========")
if ipa_path:
# https://www.pgyer.com/doc/api 具體參數(shù)大家可以進(jìn)去里面查看,
url = 'http://www.pgyer.com/apiv1/app/upload'
data = {
'uKey': USER_KEY,
'_api_key': API_KEY,
'installType': '1',
'updateDescription': description
}
files = {'file': open(ipa_path, 'rb')}
r = requests.post(url, data=data, files=files)
if r.status_code == 200:
# 是否需要打開(kāi)瀏覽器
# self.open_browser(self)
self.send_email()
else:
print("\n\n===========沒(méi)有找到對(duì)應(yīng)的ipa===========")
return

@staticmethod
def open_browser(self):
webbrowser.open(ipa_download_url, new=1, autoraise=True)

@staticmethod
def _format_address(self, s):
name, address = parseaddr(s)
return formataddr((Header(name, 'utf-8').encode(), address))

def send_email(self):
# https://www.pgyer.com/XXX app地址
# 只是單純的發(fā)了一個(gè)文本郵箱,具體的發(fā)附件和圖片大家可以自己去補(bǔ)充
msg = MIMEText('<html><body><h1>Hello</h1>' +
'<p>╮(╯_╰)╭<a  rel="external nofollow" >應(yīng)用已更新,請(qǐng)下載測(cè)試</a>╮(╯_╰)╭</p>' +
'<p>蒲公英的更新會(huì)有延遲,具體版本時(shí)間以郵件時(shí)間為準(zhǔn)</p>' +
'</body></html>', 'html', 'utf-8')
msg['From'] = self._format_address(self, 'iOS開(kāi)發(fā)團(tuán)隊(duì) <%s>' % from_address)
msg['Subject'] = Header('來(lái)自iOS開(kāi)發(fā)團(tuán)隊(duì)的問(wèn)候……', 'utf-8').encode()
server = smtplib.SMTP(smtp_server, 25) # SMTP協(xié)議默認(rèn)端口是25
server.set_debuglevel(1)
server.login(from_address, password)
server.sendmail(from_address, [to_address], msg.as_string())
server.quit()
print("===========郵件發(fā)送成功===========")


if __name__ == '__main__':
description = input("請(qǐng)輸入內(nèi)容:")
archive = AutoArchive()
archive.clean()

關(guān)于ExportOptions.plist文件

因?yàn)?Xcode 9+ 默認(rèn)不允許訪問(wèn)鑰匙串的內(nèi)容,必須要設(shè)置 allowProvisioningUpdates 才會(huì)允許,Python的Xcode插件目前無(wú)法支持此項(xiàng)完成打包流程。

解決步驟如下:

1、手動(dòng)Xcode10打包,導(dǎo)出ExportOptions.plist文件;

2、編輯ExportOptions.plist文件,配置 provisioningProfiles 對(duì)應(yīng)填入Bundle identifier及證書(shū)關(guān)聯(lián)配置文件(打包時(shí)自動(dòng)匹配或手動(dòng)填入證書(shū),provisioningProfiles需配置的必填信息可自動(dòng)生成);

3、提供ExportOptions.plist文件路徑供Python腳本調(diào)用(詳請(qǐng)參看Python腳本代碼)。

具體的內(nèi)容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>compileBitcode</key>//是否編譯bitcode
<true/>
<key>method</key>
<string>ad-hoc</string>/
<key>provisioningProfiles</key>
<dict>
<key>文件bundle id</key>
<string>Adhoc_ID</string>
</dict>
<key>signingCertificate</key>//證書(shū)簽名
<string>這里填證書(shū)簽名</string>
<key>signingStyle</key>
<string>manual</string>
<key>stripSwiftSymbols</key>
<true/>
<key>teamID</key>
<string>AANCCUK4M3</string>//TeamID
<key>thinning</key>
<string>&lt;none&gt;</string>
</dict>
</plist>

分析

xcodebuild archive -workspace XXX.xcworkspace -scheme XXX -configuration Release -archivePath XXX CONFIGURATION_BUILD_DIR ./dir ODE_SIGN_IDENTITY=證書(shū) PROVISIONING_PROFILE=描述文件UUID

文件 說(shuō)明
-workspace XXX.xcworkspace XXX.xcworkspace需要編譯工程的工作空間名稱(chēng),如果工程不是.xcworkspace的,可以不需要-workspace XXX.xcworkspace這段話
-scheme XXX XXX是工程名稱(chēng),-scheme XXX是指定構(gòu)建工程的名稱(chēng)
-configuration Release 填入打包的方式是Debug或Release,就跟在Xcode中編譯前需要在Edit scheme的Build configuration中選擇打出來(lái)的包是Debug還是Release包一樣,-configuration就是配置編譯的Build configuration
-archivePath XXX 配置生成.xcarchive的路徑,
ODE_SIGN_IDENTITY=證書(shū) 配置打包的指定證書(shū),如果該工程的Xcode已經(jīng)配置好了證書(shū),那么不加入這段話也可以,打包出來(lái)的證書(shū)就是Xcode中配置好的。
PROVISIONING_PROFILE=描述文件UUID 配置打包的描述文件,同上,Xcode已經(jīng)配置好了就不用在填入這段話了
CONFIGURATION_BUILD_DIR 配置編譯文件的輸出路徑,如果需要用到.xcarchive文件內(nèi)部的dSYM等文件,可以使用改字段指定輸出路徑。

問(wèn)題一

配置一下compileBicode=NO即可

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。

相關(guān)文章

  • Python?itertools中accumulate函數(shù)用法及使用運(yùn)用詳細(xì)講解

    Python?itertools中accumulate函數(shù)用法及使用運(yùn)用詳細(xì)講解

    這篇文章主要介紹了Python的itertools庫(kù)中的accumulate函數(shù),該函數(shù)可以計(jì)算累積和或通過(guò)指定函數(shù)進(jìn)行累積運(yùn)算,文中通過(guò)代碼將用法介紹的非常詳細(xì),需要的朋友可以參考下
    2025-02-02
  • 詳解python itertools功能

    詳解python itertools功能

    itertools是python內(nèi)置的模塊,使用簡(jiǎn)單且功能強(qiáng)大,這里嘗試匯總整理下,并提供簡(jiǎn)單應(yīng)用示例,這篇文章主要介紹了python itertools功能,需要的朋友可以參考下
    2020-02-02
  • Python多任務(wù)版靜態(tài)Web服務(wù)器實(shí)現(xiàn)示例

    Python多任務(wù)版靜態(tài)Web服務(wù)器實(shí)現(xiàn)示例

    這篇文章主要為大家介紹了Python靜態(tài)Web服務(wù)器多任務(wù)版實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • python中的np.argmax() 返回最大值索引號(hào)

    python中的np.argmax() 返回最大值索引號(hào)

    這篇文章主要介紹了python中的np.argmax() 返回最大值索引號(hào)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • 使用Python對(duì)SQLite數(shù)據(jù)庫(kù)操作

    使用Python對(duì)SQLite數(shù)據(jù)庫(kù)操作

    本文主要介紹了Python對(duì)SQLite數(shù)據(jù)庫(kù)操作的簡(jiǎn)單教程。SQLite是一種嵌入式數(shù)據(jù)庫(kù),它的數(shù)據(jù)庫(kù)就是一個(gè)文件。由于SQLite本身是C寫(xiě)的,而且體積很小,所以,經(jīng)常被集成到各種應(yīng)用程序中,甚至在IOS和Android的APP中都可以集成。
    2017-04-04
  • Python設(shè)計(jì)模式之橋接模式原理與用法實(shí)例分析

    Python設(shè)計(jì)模式之橋接模式原理與用法實(shí)例分析

    這篇文章主要介紹了Python設(shè)計(jì)模式之橋接模式原理與用法,結(jié)合具體實(shí)例形式分析了Python橋接模式的相關(guān)概念、原理、定義及使用方法,需要的朋友可以參考下
    2019-01-01
  • Python numpy和matlab的幾點(diǎn)差異介紹

    Python numpy和matlab的幾點(diǎn)差異介紹

    這篇文章主要介紹了Python numpy和matlab的幾點(diǎn)差異,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • python入門(mén):argparse淺析 nargs=''+''作用

    python入門(mén):argparse淺析 nargs=''+''作用

    這篇文章主要介紹了python入門(mén):argparse淺析 nargs='+'作用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • 運(yùn)用Python巧妙處理Word文檔的方法詳解

    運(yùn)用Python巧妙處理Word文檔的方法詳解

    大家平時(shí)在工作與學(xué)習(xí)中都會(huì)操作到Word文件格式,特別是很多數(shù)據(jù)的時(shí)候,靠人力去識(shí)別操作非常容易出錯(cuò)。今天就帶大家用python來(lái)處理Word文件,感興趣的可以了解一下
    2022-05-05
  • Python對(duì)象的底層實(shí)現(xiàn)源碼學(xué)習(xí)

    Python對(duì)象的底層實(shí)現(xiàn)源碼學(xué)習(xí)

    這篇文章主要為大家介紹了Python對(duì)象的底層實(shí)現(xiàn)源碼學(xué)習(xí),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-05-05

最新評(píng)論

醴陵市| 新兴县| 澎湖县| 浪卡子县| 武清区| 新安县| 元江| 临湘市| 贺州市| 绥宁县| 通化县| 辽宁省| 运城市| 思南县| 剑川县| 阳朔县| 乌审旗| 宁晋县| 大兴区| 来宾市| 新民市| 砚山县| 柘城县| 卢湾区| 津南区| 余干县| 眉山市| 宁海县| 宝坻区| 栾川县| 桦甸市| 瓮安县| 牡丹江市| 阿克陶县| 远安县| 额尔古纳市| 蕉岭县| 洱源县| 楚雄市| 宁城县| 卢氏县|