用 Eclipse 開發(fā) iPhone Web 應(yīng)用程序
Apple 的 iPhone 平臺為開發(fā)人員提供了一個有趣的機(jī)會。借助其小型的交互式觸摸屏,iPhone 和 iPod Touch 在很短的時間內(nèi)迅速吸引了數(shù)百萬用戶。但是這種新穎的設(shè)計和專利平臺給應(yīng)用程序開發(fā)人員帶來了一系列新的挑戰(zhàn)。在 2008 年 2 月 Apple 發(fā)布其軟件開發(fā)包 (SDK) 以前,想要在該平臺上進(jìn)行研究的開發(fā)人員必須創(chuàng)建模擬 iPhone 的本機(jī)界面外觀的 Web 應(yīng)用程序。
幸運(yùn)的是,使用一系列新的開源工具可以更輕松地完成這項工作。Aptana 的針對 Eclipse 的 iPhone Development 插件可以生成特定于 iPhone 的項目,并在可旋轉(zhuǎn)取景器中預(yù)覽應(yīng)用程序。Joe Hewitt 的 iUi、層疊樣式表(Cascading Style Sheets,CSS)和 JavaScript 框架包含模擬本機(jī) iPhone 體驗的部件和頁面集。
在本文中,我們使用 Aptana 和 iUi 創(chuàng)建一個新應(yīng)用程序:針對 iPhone 的簡單 Javadoc 查看器。首先,設(shè)計一個在 iPhone 中瀏覽 Javadoc 的用戶界面 (UI),然后創(chuàng)建用于從任何源代碼生成 Javadoc 頁面的定制 doclet。在此過程中將描述針對 iPhone 的 UI 問題,如何使用這些開源工具簡化開發(fā)和調(diào)試,以及 iPhone 開發(fā)的未來趨勢。
首先安裝 Aptana 并下載 iUi:
- 在 Eclipse V3.2 中,選擇 Help > Software Updates > Find and Install。
- 選擇 Search for new features to install。此窗口列出了可以從中下載插件的站點以及 Eclipse 預(yù)定義的插件。
- 單擊 New Remote Site 將 Aptana 添加到此列表中,并使用 URL
http://update.aptana.com/3.2
對其進(jìn)行定義。 - 從列表中選擇新定義的 Aptana 站點,單擊 Next,然后安裝所有可用功能。完成此窗口安裝基本的 Aptana Editor。
- 重新啟動 Eclipse。
- 選擇 Window > Open Perspective > Other,然后從窗口選擇 Aptana。工具欄中將顯示一組新圖標(biāo)。
- 單擊主頁圖標(biāo)。將顯示 Aptana 功能的概覽。
- 在 Apple iPhone Development 部分中,單擊 Download and Install。
- 安裝所有功能,然后完成此窗口以用特定于 iPhone 的功能配置 Aptana。
- 重新啟動 Eclipse。
- 下載最新版本的 iUi。
一切就緒之后,請使用 Eclipse 創(chuàng)建一個名為 iDoc 的新 iPhone Project,如圖 1 所示。
圖 1. 創(chuàng)建新 iPhone Project
圖 2 顯示了生成的項目,其中包含簡單 iPhone 應(yīng)用程序。
圖 2. 在 Eclipse 中生成的 iPhone Project
注意由 Aptana 的基本編輯器提供的突出顯示的語法,它支持 HTML、CSS 和 JavaScript。
iPhone Preview 模式和應(yīng)用服務(wù)器
在文本編輯器的底部,您將看到 Source、iPhone Preview 選項卡,以及系統(tǒng)中安裝的所有瀏覽器(例如,Safari Preview、Firefox Preview)。單擊 iPhone Preview 查看示例應(yīng)用程序在 iPhone 中的外觀。在瀏覽器外部單擊可以旋轉(zhuǎn)電話,單擊電話標(biāo)題欄可以隱藏導(dǎo)航欄。下面顯示了水平顯示的 iPhone Preview 模式。
圖 3. iPhone Preview 模式下的水平視圖
使用 iPhone Preview 模式可以節(jié)省大量時間:可以快速測試新設(shè)計想法并重復(fù)進(jìn)行開發(fā)而無需離開計算機(jī)。當(dāng)應(yīng)該在實際的 iPhone 上測試您的應(yīng)用程序時,Aptana 的內(nèi)置應(yīng)用服務(wù)器將十分有用。單擊 Eclipse 工具欄中的 Run 圖標(biāo)啟動服務(wù)器。圖 4 顯示了在 Eclipse 中運(yùn)行的應(yīng)用服務(wù)器。
圖 4. Aptana 的 iPhone Application Server 托管頁面并創(chuàng)建帶有 URL 的電子郵件
如果通過 WiFi 連接將 iPhone 連接到本地網(wǎng)絡(luò),則可以訪問服務(wù)器窗口中顯示的 URL。單擊 E-mail this url 并向 iPhone 中的電子郵件帳戶發(fā)送一條消息,這可以省去一個步驟。單擊電子郵件中的鏈接,應(yīng)用程序?qū)⒃?iPhone 的 Web 瀏覽器中啟動。
雖然 Aptana 的啟動應(yīng)用程序包含特定于 iPhone 的 HTML 和 CSS 文件,但是這些文件的功能有限。一種更好的備用解決方案是使用 iUi 框架,此框架擁有一組豐富的自定義部件和 JavaScript 效果,可以精確地模擬本機(jī) iPhone 界面。
解壓縮已下載的 iUi 發(fā)行版 iui-0.13.tar,然后把文件復(fù)制到 Eclipse 的 iDoc Project 中。圖 5 顯示了包含 iUi 的項目。
圖 5. 帶有 iUi 框架和示例項目的 iDoc 項目
iUi 的演示 Web 應(yīng)用程序可以在上面展開的 samples 文件夾中找到。其中包括音樂瀏覽器、劇院清單和類似 Digg 的站點。使用 Aptana 的 iPhone Preview 模式,我們可以在 Eclipse 中查看這些組件。圖 6 顯示了劇院清單 Web 應(yīng)用程序 (samples/theaters/index.html) 的搜索頁面。
圖 6. iUi 的示例劇院清單 Web 應(yīng)用程序
注意,該演示與本機(jī) iPhone 的界面外觀極為相似。使用這些預(yù)打包的部件可以快速開發(fā) iPhone Web 應(yīng)用程序。
在本例中,將為 iPhone 創(chuàng)建一個名為 iDoc 的 Javadoc 查看器。由 Sun Microsystems 的標(biāo)準(zhǔn) Javadoc 生成器創(chuàng)建的緊密 HTML 文件在臺式機(jī)上一切正常,但是在 iPhone 中卻很難導(dǎo)航和讀取。iDoc 將生成 iPhone 支持的 Javadoc —— 非常適合于在地鐵中瀏覽應(yīng)用程序編程接口 (API) 或者讓合作的編程團(tuán)隊中的觀察員幫助解決困難。
在開始設(shè)計 iDoc 的 UI 之前,一定要先了解 iPhone 開發(fā)與普通 Web 開發(fā)的不同之處。圖 7 來自 Apple 的 iPhone Dev Center(請參閱 參考資料),很好地總結(jié)了兩者的不同之處:手指不是鼠標(biāo)。這樣做得不到桌面應(yīng)用程序中的像素精度,但是通過輕敲、輕彈和輕壓將開啟一個豐富的新用戶交互模型。此外,iPhone 與用戶一起移動并且通常用于有干擾的環(huán)境中,因此應(yīng)用程序需要能夠快速容易地訪問目標(biāo)信息。
Apple 的 iPhone 人機(jī)接口指南(請參閱 參考資料)定義了三種類型的 iPhone Web 內(nèi)容。
- 與 iPhone 中的 Safari 兼容
- 可以正確顯示的任意類型的 Web 頁面,即使頁面的一部分依賴于諸如 Adobe Flash 或 Java™ applet 之類的不受支持的插件
- 最適于 iPhone 中的 Safari
- 為 iPhone 正確縮放內(nèi)容并且不依賴于不受支持插件的 Web 頁面
- iPhone 應(yīng)用程序
- 通過模擬 iPhone 界面外觀來模擬本機(jī)應(yīng)用程序的 Web 頁面,并且在適當(dāng)?shù)臅r候,與諸如電話、電子郵件或 Google Maps 之類的 iPhone 服務(wù)集成
標(biāo)準(zhǔn) Javadoc 頁面屬于第一種類型,與 iPhone 中的 Safari 兼容。這些頁面可以正確顯示,但是要求很好地處理輕壓和輕彈才能找到相關(guān)信息。iDoc 針對的是完整的 iPhone 應(yīng)用程序。雖然不能與其他服務(wù)集成,但是 iDoc 的接口能夠在 iPhone 中很好地使用。
針對 iPhone 進(jìn)行開發(fā)時,必須只關(guān)注 iPhone。應(yīng)用程序應(yīng)當(dāng)快速地完成特定任務(wù),不應(yīng)該嘗試包括所有可能的功能。使用 iDoc,用戶必須找到關(guān)于 Java 類的基本文檔,例如類名、方法名、方法簽名和注釋。通過指向目標(biāo)詳細(xì)信息頁面的三個導(dǎo)航級別顯示這些信息。
- 包導(dǎo)航
- 頂層包
- 類導(dǎo)航
- 包內(nèi)的類、接口、異常和錯誤
- 類細(xì)節(jié)導(dǎo)航
- 類中的描述、字段、構(gòu)造函數(shù)和方法
- 詳細(xì)信息頁面
- 注釋、簽名和參數(shù)
為了使 iDoc 保持整齊并且以任務(wù)為目的,需要省略一些傳統(tǒng) Javadoc 功能。例如,不顯示包描述注釋。由于這些功能通常不包含有用信息(例如,acme.client 包含客戶機(jī)代碼),并且有時被同時省略,因此把它們從 iDoc 中移除并簡化接口就顯得十分有意義。
要獲得三個導(dǎo)航級別,請使用邊對邊 (edge-to-edge) 列表。這是在本機(jī) iPhone 應(yīng)用程序中常用的構(gòu)造,用于瀏覽聯(lián)系人、電子郵件和音樂。邊對邊列表將在 44 像素的等高行中顯示項,并且有助于在大量信息中滾動查找。Apple 的 iPhone 人機(jī)接口指南 提供了構(gòu)造邊對邊列表的規(guī)格,包括字體、字體大小和邊框間距。iUi 框架用 CSS 和 JavaScript 語言實現(xiàn)這些規(guī)格,允許您創(chuàng)建像本機(jī) iPhone 組件那樣顯示的簡單 HTML 列表。
清單 1 顯示了頁眉,以及 java.applet 和 java.rmi 包的前兩個導(dǎo)航級別。
清單 1. 帶有頁眉和前兩個導(dǎo)航級別的 HTML 文檔
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>iDoc</title> <meta name="viewport" content="width=320; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/> <style type="text/css" media="screen">@import "iui/iui.css";</style> <style type="text/css" media="screen">@import "iDoc.css";</style> <script type="application/x-javascript" src="iui/iui.js"></script> </head> <body onclick="console.log('Hello', event.target);"> <div class="toolbar"> <h1 id="pageTitle"></h1> <a id="backButton" class="button" href="#"></a> </div> <ul id="home" title="Packages" selected="true"> <li><a href="#java.applet">java.applet</a></li> <!-- more packages...--> <li><a href="#java.rmi">java.rmi</a></li> </ul> <ul id="java.applet" title="java.applet"> <li class="group">Interfaces</li> <li><a href="java.applet.AppletContext.html"> AppletContext</a></li> <li><a href="java.applet.AppletStub.html"> AppletStub</a></li> <li><a href="java.applet.AudioClip.html"> AudioClip</a></li> <li class="group">Classes</li> <li><a href="java.applet.Applet.html">Applet </a></li> <li><a href="java.applet.Applet.AccessibleApplet.html"> AccessibleApplet</a></li> </ul> <ul id="java.rmi" title="java.rmi"> <li class="group">Interfaces</li> <li><a href="java.rmi.Remote.html"> Remote</a></li> <li class="group">Classes</li> <li><a href="java.rmi.MarshalledObject.html"> MarshalledObject</a></li> <li><a href="java.rmi.Naming.html"> Naming</a></li> <li><a href="java.rmi.RMISecurityManager.html"> RMISecurityManager</a></li> <li class="group">Exceptions</li> <li><a href="java.rmi.AccessException.html"> AccessException</a></li> <li><a href="java.rmi.AlreadyBoundException.html"> AlreadyBoundException</a></li> <li><a href="java.rmi.ConnectException.html"> ConnectException</a></li> <li><a href="java.rmi.ConnectIOException.html"> ConnectIOException</a></li> <li><a href="java.rmi.MarshalException.html"> MarshalException</a></li> <li><a href="java.rmi.NoSuchObjectException.html"> NoSuchObjectException</a></li> <li><a href="java.rmi.NotBoundException.html"> NotBoundException</a></li> <li><a href="java.rmi.RemoteException.html"> RemoteException</a></li> <li><a href="java.rmi.RMISecurityException.html"> RMISecurityException</a></li> <li><a href="java.rmi.ServerError.html"> ServerError</a></li> <li><a href="java.rmi.ServerException.html"> ServerException</a></li> <li><a href="java.rmi.ServerRuntimeException.html"> ServerRuntimeException</a></li> <li><a href="java.rmi.StubNotFoundException.html"> StubNotFoundException</a></li> <li><a href="java.rmi.UnexpectedException.html"> UnexpectedException</a></li> <li><a href="java.rmi.UnknownHostException.html"> UnknownHostException</a></li> <li><a href="java.rmi.UnmarshalException.html"> UnmarshalException</a></li> </ul> |
圖 8 顯示了使用邊對邊列表生成的頂層選擇包導(dǎo)航級別。
圖 8. 像導(dǎo)航本機(jī) iPhone 應(yīng)用程序一樣導(dǎo)航 Javadoc 包
圖 9 顯示了在 iPhone Preview 模式下顯示的最終的 java.rmi 包。
圖 9. 在 java.rmi 包中導(dǎo)航接口、類和異常
對于 iDoc 的目標(biāo)詳細(xì)信息頁面,使用另一種 iPhone 構(gòu)造:圓角矩形列表。這些列表對于分組信息十分有用,并且 iPhone 中的設(shè)置面板都使用這種列表。使用圓角矩形列表可以分隔方法簽名與參數(shù)及異常清單。在 V0.13 中,iUi 只支持將圓角矩形列表用于表單輸入;將其元素用于靜態(tài)文本將生成格式錯誤的塊。 使用定制的 iDoc.css 文件擴(kuò)展這些 CSS(如清單 2 所示),以添加用于顯示帶有靜態(tài)文本的圓角矩形列表的 textRow
元素。
清單 2. 定制 textRow
CSS 擴(kuò)展以正確顯示靜態(tài)文本
/* Adding a new row CSS style to iUi for displaying blocks of text */ .textRow { position: relative; border-bottom: 1px solid #999999; -webkit-border-radius: 0; text-align: right; } .textRow > p { text-align: left; margin: 5px 8px 5px 10px; padding: 0px 0px 0px 0px; } fieldset > .textRow:last-child { border-bottom: none !important; } |
清單 3 顯示了 java.math.BigDecimal
的一種構(gòu)造方法的詳細(xì)信息頁面。
清單 3. 使用 textRow
元素的 HTML 詳細(xì)信息頁面
<div id="java.math.BigDecimal(long,java.math.MathContext)" title="BigDecimal" class="panel"> <fieldset> <div class="textRow"><p><b> public BigDecimal(long, MathContext)</b></p></div> <div class="textRow"><p>Translates a <code>long</code> into a <code>BigDecimal</code>, with rounding according to the context settings. The scale of the <code>BigDecimal</code>, before any rounding, is zero. </p></div> </fieldset> <h2>Parameters</h2> <fieldset> <div class="textRow"><p><b>long val </b>: <code>long</code> value to be converted to <code>BigDecimal</code>.</p></div> <div class="textRow"><p><b>MathContext mc </b>: the context to use.</p></div> </fieldset> <h2>Throws</h2> <fieldset> <div class="textRow"><p><b>ArithmeticException </b>: if the result is inexact but the rounding mode is <code>UNNECESSARY</code>.</p></div> </fieldset> </div> |
<fieldset>
標(biāo)記內(nèi)的所有內(nèi)容都位于圓角矩形內(nèi),textRow <div>
用于分隔行。帶有 <h2>
標(biāo)記的標(biāo)題顯示為列表上方的組標(biāo)簽。圖 10 顯示了最終頁面。
圖 10. java.math.BigDecimal 中的構(gòu)造函數(shù)的詳細(xì)視圖
擁有三個導(dǎo)航級別和目標(biāo)詳細(xì)信息頁面后,UI 就完成了。iDoc 使用戶可以專注于具體任務(wù)。借助 iUi 框架和一些定制的 CSS,它看上去很像本機(jī) iPhone 應(yīng)用程序。
現(xiàn)在已經(jīng)設(shè)計了 UI,接下來需要編寫代碼來生成 HTML 文件。創(chuàng)建一個插入到 Sun 的 javadoc
命令中的簡單 doclet。我們的示例將使用標(biāo)準(zhǔn) java.* 包,但是 iDoc 可以從任何源代碼生成 Javadoc。使用 OpenJDK 源代碼,因為它可以公開獲得并且 GNU Public License (GPL) V2 許可證允許我們生成和發(fā)布其 Javadoc。
使用 iDoc,只需迭代包和類并調(diào)用方法打印上述格式的靜態(tài) HTML 頁面。清單 4 顯示打印目標(biāo)詳細(xì)信息頁面的方法。
private void printDetail(PrintStream p, ProgramElementDoc doc, String id, String name) { divHeader(p, id, name, "panel"); textHeader(p, null); textRow(p, getSignature(doc)); textRow(p, getCommentText(doc.commentText())); textFooter(p); if (doc instanceof ExecutableMemberDoc) { printMethodDetail(p, (ExecutableMemberDoc) doc); } divFooter(p); } private void printMethodDetail(PrintStream p, ExecutableMemberDoc field) { if (field.parameters().length > 0) { textHeader(p, "Parameters"); for (int i=0; i<field.paramTags().length; i++) { textRow(p, "<b>" + field.parameters()[i].typeName() + " " + field.paramTags()[i].parameterName() + "</b>: " + getCommentText(field.paramTags()[i].parameterComment())); } textFooter(p); } if (field.throwsTags().length > 0) { textHeader(p, "Throws"); for (int i=0; i<field.throwsTags().length; i++) { textRow(p, "<b>" + field.throwsTags()[i].exceptionName() + "</b>: " + getCommentText(field.throwsTags()[i].exceptionComment())); } textFooter(p); } } |
代碼是通用的,這樣 printDetail()
將處理類描述、字段、構(gòu)造函數(shù)和方法的輸出。后兩種類型是 ExecutableMemberDoc
的子類,因此打印關(guān)于其參數(shù)和已拋出異常的附加信息。
Aptana 的 iPhone Preview 模式將幫助調(diào)試輸出文件。在每次迭代后,您可以快速單擊該應(yīng)用程序查找已設(shè)計界面中的不一致性。但是,使用 Preview 模式可以掩蓋性能問題:現(xiàn)代計算機(jī)的運(yùn)行速度比 iPhone 的 620-MHz ARM 處理器快三至五倍。此外,用戶經(jīng)常通過速度慢的蜂窩網(wǎng)絡(luò)下載頁面,因此必須用實際 iPhone 運(yùn)行您的應(yīng)用程序。
當(dāng)我在 iPhone 中測試查看 iDoc 時,我發(fā)現(xiàn)輸出一個大型 HTML 文件將導(dǎo)致跳幀和性能下降。要解決此問題,創(chuàng)建一個用于導(dǎo)航包名/類名的主文件,然后為帶有注釋和方法細(xì)節(jié)的每個類創(chuàng)建獨(dú)立文件(參見清單 5)。雖然此過程將生成大量文件,但是各個文件大小都非常小,并且應(yīng)用程序運(yùn)行得十分流暢。
清單 5. Doclet 代碼將迭代每個包,然后為每個類創(chuàng)建文件
out = new FileOutputStream(index); p = new PrintStream(out); printHeader(p); PackageDoc[] packages = root.specifiedPackages(); Arrays.sort(packages); printPackages(p, packages); for (int i=0; i<packages.length; i++) { printPackageDetail(p, packages[i]); } for (int i=0; i<packages.length; i++) { ClassDoc[] classes = packages[i].allClasses(); Arrays.sort(classes); for (int j=0; j<classes.length; j++) { // Creating a separate file for each class. PrintStream p2 = new PrintStream(new FileOutputStream(getFilename(classes[j]))); printClassDetail(p2, classes[j]); p2.close(); } } printFooter(p); p.close(); |
在經(jīng)過該性能增強(qiáng)之后,就能運(yùn)行 iDoc 了。為 OpenJDK 中的 51 個 java.* 和 javax.* 包(表示 1,304 個類)生成 Javadoc,然后把所有內(nèi)容上傳到 Web 服務(wù)器中。這包括超過 16 MB 的文件,但是主要導(dǎo)航頁面只有 112 KB,并且每個單獨(dú)類的詳細(xì)信息頁面平均為 13 KB。即使在使用 EDGE 網(wǎng)絡(luò)時,應(yīng)用程序也能夠快速響應(yīng)。如果您已經(jīng)擁有了 iPhone,請訪問 iDoc 站點(請參閱 參考資料)并嘗試使用,也可以下載 iDoc 來為您自己的代碼庫生成特定于 iPhone 的 Javadoc。圖 11 顯示了最終的應(yīng)用程序。
圖 11. 用于 iPhone 的全部 51 個包的 Javadoc
可能對 iDoc 進(jìn)行的擴(kuò)展包括支持顯示 Java 5 泛型,以及更智能地捕捉 Javadoc 注釋內(nèi)的標(biāo)記來實現(xiàn)頁面之間的鏈接。如果您有興趣添加 iDoc 的功能,則可以下載完整的源代碼.
2007 年 10 月,Steve Jobs 宣稱 Apple 將于 2008 年 2 月發(fā)布 iPhone SDK。詳細(xì)信息很少,因為這是在 2007 年 12 月編寫的,但是 SDK 將允許您在不需要使用 Safari 的情況下創(chuàng)建能夠在 iPhone 上本機(jī)運(yùn)行的應(yīng)用程序。給定 iPhone 底層架構(gòu)之后,開發(fā)平臺很可能是類似于 Mac OS X 的 Cocoa 和 Objective-C。Apple 主管人員的最新評論暗示第三方應(yīng)用程序?qū)⑿枰邮苣撤N類型的認(rèn)證過程。
通過在本機(jī)運(yùn)行,需要高級動畫、圖形和網(wǎng)絡(luò)訪問的應(yīng)用程序?qū)闹蝎@益。不過,即使在發(fā)布了 SDK 之后,iPhone 的 Web 開發(fā)仍會是一個吸引人的主題。Web 應(yīng)用程序很容易創(chuàng)建和部署。諸如 Aptana 和 iUi 之類的工具簡化了開發(fā),并且能夠快速創(chuàng)建 Web 應(yīng)用程序。正如 iDoc 所展示的,沒有必要等待 SDK 的發(fā)布:使用現(xiàn)有的工具,您可以創(chuàng)建具有本機(jī)界面外觀的全功能 iPhone Web 應(yīng)用程序。