轉(zhuǎn)自 ibuick.com,原文 http://ibuick.com/index.php/archives/add-automatic-update-support-over-cocoa-app-via-sparkle-framework
作為一名桌面軟件開(kāi)發(fā)者,應(yīng)該提早考慮程序的更新問(wèn)題。如何將程序更新及時(shí)優(yōu)雅的推送給用戶,是維持用戶忠誠(chéng)度和提高軟件使用體驗(yàn)的一個(gè)重要方面。而作為Cocoa應(yīng)用程序開(kāi)發(fā)者,我們可以選擇自己手動(dòng)來(lái)實(shí)現(xiàn)此功能,也可以選擇一些優(yōu)秀的開(kāi)源框架。Sparkle就是其中之一。
Sparkle是一個(gè)非常簡(jiǎn)單且易用的Cocoa應(yīng)用程序更新框架。本篇文章將使用一個(gè)簡(jiǎn)單的例子,教你如何使用Sparkle為你的Cocoa應(yīng)用程序加入更新支持。
1: 新建一個(gè)Cocoa Application,TestSparkle


2: 去到Sparkle下載Sparkle Framework,最新版本為 1.5b6,

Sparkle Test App.app 是一個(gè)用來(lái)演示Sparkle更新框架的一個(gè)應(yīng)用程序。
Extras文件夾下提供了Sparkle的標(biāo)準(zhǔn)圖標(biāo),Release Notes模版,軟件簽名工具,源代碼和Appcast.xml示例文件,我們后面會(huì)再講到這些工具和文件。
With Garbage Collection, 是一個(gè)加入了Garbage Collection支持的Sparkle分發(fā)版,如果你的應(yīng)用程序運(yùn)行在有GC的環(huán)境下,則可以使用這個(gè)版本的Sparkle
Sparkle.framework 是通用分發(fā)版,筆者建議大家使用此版本的Sparkle。
3: 鏈接Sparkle框架到TestSparkle工程
拖拽Sparkle.framework(或 with Garbage Collection下的
Sparkle.framework)到TestSparkle的Linked Frameworks下,在彈出窗口中記得選中”Copy items
into destination group’s folder (if needed)”前面的復(fù)選框。

4: 為你的工程新建一個(gè)Copy Files Build Phase,

5: 右鍵點(diǎn)擊這個(gè)新建的Copy Files Build Phase,并在彈出窗口中,點(diǎn)擊Destination下拉框,選擇Frameworks

6: 將Linked Framworks下的Sparkle.framework拖拽到這個(gè)新建的Copy Files Build Phase 中

7: 在Interface Builder中打開(kāi)TestSparkle的MainMenu.xib(nib), 然后點(diǎn)擊Interface Builder–>Files–>Read Class Files

8: 將Sparkle.framework中的所有頭文件選中并讀取

9: 從Library中拖拽一個(gè) NSObject到MainMenu主窗口.

10: 點(diǎn)擊此Object對(duì)象,點(diǎn)擊Inspector,設(shè)定此Object的Class為 SUUpdater

11: 添加一個(gè)菜單項(xiàng)到到TestSparkle Menu,重命名為 Check For Updates…

12: 將 Check for Updates…菜單項(xiàng)的Send Actions指向Updater Object的checkForUpdates方法

13: 保存Interface Builder的所有更改,退出Interface Builder。
14: 為了安全防止應(yīng)用程序更新遭到惡意篡改,我推薦對(duì)應(yīng)用程序更新添加數(shù)字簽名。
Sparkle使用DAS SHA-1 來(lái)對(duì)程序更新包進(jìn)行數(shù)字簽名。
打開(kāi)終端,進(jìn)入步驟2中存放已下載的Sparkle包的文件夾,進(jìn)入Extras–>Signing Tools,
執(zhí)行,
這個(gè)命令將會(huì)生成兩個(gè)文件 dsa_priv.pem 和 dsa_pub.pem,也就是私鑰和公鑰,請(qǐng)妥善保存這兩個(gè)文件,如果私鑰丟失,你得用戶將再也無(wú)法自動(dòng)通過(guò)已安裝的程序來(lái)獲得更新的更新。
15: 建立一個(gè) App Cast Feed文件
Sparkle的運(yùn)作機(jī)理其實(shí)非常簡(jiǎn)潔,本地應(yīng)用程序Info.plist中含有一個(gè)URL,此URL指向一個(gè)在你網(wǎng)站上的App Cast
Feed XML文件。當(dāng)你發(fā)布更新的時(shí)候,上傳新的app到你的網(wǎng)站,更新此app cast xml
feed。這樣,客戶端程序在運(yùn)行檢查更新時(shí),會(huì)根據(jù)Info
Plist中的URL找到并Parse此文件,跟本地軟件版本進(jìn)行比對(duì)。如果發(fā)現(xiàn)更新,則提示用戶。這就是App Cast XML
Feed文件的作用。
在步驟14中提到的Extras文件夾下,有一個(gè)App Cast XML Feed文件的模版:
http://you.com/app/2.0.html
Wed, 09 Jan 2006 19:20:11 +0000
http://you.com/app/1.5.html
Wed, 01 Jan 2006 12:20:11 +0000
<!-- Now here's an example of a version with a
weird internal version number (like an SVN revision) but a
human-readable external one. -->
http://you.com/app/1.4.html
Wed, 25 Dec 2005 12:20:11 +0000
我們可以看出,這其實(shí)是一個(gè)標(biāo)準(zhǔn)的RSS Feed格式的XML文件。我們只要修改相應(yīng)的項(xiàng)目即可。
下面我們就來(lái)一步步的演示如何使用Sparkle為你的程序加入更新支持。
16: 我們首先在本地搭建一個(gè)可用于測(cè)試軟件更新的網(wǎng)站。打開(kāi)Mac OS X系統(tǒng)偏好設(shè)置(System Preferences),
找到共享(Sharing),開(kāi)啟Web共享(Web
Sharing),并通過(guò)點(diǎn)擊圖中所示URL測(cè)試Web共享是否成功開(kāi)啟。http://10.0.1.2/~buick 你的顯示可能與此不同,,,,

17: 打開(kāi)你的XCode中 TestSparkle 工程,編輯 TestSparkle-Info.plist,加入兩個(gè)屬性,SUPublicDSAKeyFile 和 SUFeedURL

其中,SUFeedURL 將是指向一個(gè) App Cast XML Fee 的 URL,比如我的測(cè)試地址是 http://10.0.1.2/~buick/testsparkleappcast.xml
,SUPublicDSAKeyFile 指向公鑰,我們把剛才步驟14中生成的 dsa_pub.pem 加入到工程的Resources中,并在
TestSparkle-Info.plist 中指定此公鑰的名稱,,,,那么現(xiàn)在的TestSparkle-Info.plist應(yīng)該是這樣

整個(gè)配置完成,我們現(xiàn)在來(lái)構(gòu)建一個(gè)TestSparkle.app的1.0版本,點(diǎn)擊Build and Run

啟動(dòng)TestSparkle.app, 在TestSparkle菜單下,確認(rèn)Check for Updates…按鈕處于可用狀態(tài),如果是灰色不可點(diǎn)擊,則返回Interface Builder修改。

將此 TestSparkle.app 1.0 版本拷貝到別處備用。然后返回XCode,將應(yīng)用程序版本改為1.1,然后構(gòu)建工程。將TestSparkle.app 的1.1版本打包成zip文件,改名為TestSparkle_1.1.zip
將 dsa_priv.pem (私鑰) 和 TestSparkle_1.1.zip 拷貝到 Extras下的Signing Tool文件夾中,

打開(kāi)終端進(jìn)入到此文件夾,執(zhí)行:
ruby sign_update.rb TestSparkle_1.1.zip dsa_priv.pem

便可得到升級(jí)包的簽名,MCwCFDZsrVGB+PewvxioJcvptkqchXi3AhQOZDJ4UukRM2/bYmZzzbHTxM2kpA==
用文本編輯器創(chuàng)建一個(gè)xml文件(UTF-8 編碼),內(nèi)容如下:
http://10.0.1.2/~buick The latest TestSparkle updates from localhost, more hot features and sweeties
en
Fri, 10 Sept 2010 0:00:00 +0300 http://10.0.1.2/~buick
注意(由于本網(wǎng)站HTML的設(shè)置問(wèn)題,如果你直接拷貝以上XML Feed文件到你本地測(cè)試可能會(huì)出編碼問(wèn)題導(dǎo)致XML Parse失敗,請(qǐng)到本文最后下載此文件,以及工程壓縮包)。
把此XML另存為 testsparkleappcast.xml
熟悉RSS Feed的讀者可能很容易理解此文件,,如果我們?cè)跒g覽器中直接訪問(wèn)此URL,我們會(huì)看到

而我們要關(guān)注的只是這兩段:
這段指定的URL是一個(gè)介紹頁(yè)面,如果你希望在更新提示窗口中出現(xiàn)一個(gè)介紹新版本的頁(yè)面(或者說(shuō)release notes),則使用此URL定向到你網(wǎng)站上的新版本介紹頁(yè)面。
Sparkle非常貼心的為大家提供了一個(gè)模版,在Extras/Release Notes Templates 文件夾下可找到
enclosure sparkle:version=“1.1”
sparkle:dsaSignature=“MCwCFDZsrVGB+PewvxioJcvptkqchXi3AhQOZDJ4UukRM2/bYmZzzbHTxM2kpA==“
url=“http://10.0.1.2/~buick/TestSparkle_1.1.zip” length=“436264”
type=“application/octet-stream”/>
這段是實(shí)現(xiàn)Sparkle Update的關(guān)鍵,
sparkle:version=“1.1” 是指當(dāng)前更新包版本號(hào),客戶端程序就是根據(jù)這個(gè)版本號(hào)來(lái)和本地APP進(jìn)行比對(duì),如果發(fā)現(xiàn)不同則提示更新。
sparkle:dsaSignature=“MCwCFDZsrVGB+PewvxioJcvptkqchXi3AhQOZDJ4UukRM2/bYmZzzbHTxM2kpA==“ 這個(gè)就是我們剛才為更新包生成的數(shù)字簽名
url=“http://10.0.1.2/~buick/TestSparkle_1.1.zip” 指向更新包下載地址
length=“436264” 指更新包的大小,上傳上去前用 終端 ls -al 命令可查看
type=“application/octet-stream” 是一個(gè)想對(duì)固定的值,一般不用修改。
現(xiàn)在把testsparkleappcast.xml 和 TestSparkle_1.1.zip 拷貝到
你的用戶主目錄/Sites 下 (~/Sites,具體路徑依你個(gè)人配置而定)

然后在瀏覽器敲入 http://10.0.1.2/~buick/testsparkleappcast.xml
如果能夠看到類似網(wǎng)頁(yè),,,說(shuō)明一切正常。
下面找到我們剛才保存的TestSparkle.app 1.0版本,運(yùn)行并點(diǎn)擊 Check for Updates… 如果一切正常,你可以看到

點(diǎn)擊Install Update,如果更新成功,即可顯示:

然后再次點(diǎn)擊Check for Updates, 你會(huì)看到

最后希望你與Sparkle合作愉快。
點(diǎn)擊此處下載本次工程源代碼和示例XML Feed文件,另外,安裝包里面還帶有一個(gè)Sparkle的簡(jiǎn)體中文包,將它放入你的Sparkle.framework/Resources下即可。