在AIR中顯示HTML
AIR應用程式中顯示的HTML內容可以在記憶體中建立,從本地檔案載入,或者從遠端網站載入。為了在基於Flex的AIR應用程式顯示HTML內容,將使用mx:HTML元件,這個包在原始的Adobe AIR flash.html.HTMLLoader類外面的一個友好的Flex包裝器。從UIComponent繼承了該Flex版本,並且允許它以分層的形式在基於Flex的顯示器中呈現。在mx:HTML元件中,使實際的htmlLoader類通過htmlLoader屬性變得可用。
39.3.1 載入遠端內容
在AIR應用程式中檢視HTML內容最簡單的辦法就是使用以下的MXML載入遠端內容。
<mx:HTML
id="htmlContainer"
width="100%" height="100%"
complete="onHtmlLoadComplete(event)"
location="http://www.wrox.com"
>
</mx:HTML>
我們可以使用Flex的mx:HTML元件來設定遠端URL(http://www.wrox.com)的location屬性,用來載入和顯示網頁。在完成遠端內容的載入後,將呼叫onHTMLLoadCmoplete事件,同時指示HTML內容已經完成。從此時起,自定義程式碼就可以訪問HTML內容的DOM或JavaScript用於操作(分別參見39.4.3節和39.4節)。
1. 與安全沙箱一起工作
Adobe AIR將可執行程式碼分到沙箱中,這要依據HTML的內容來自哪裡。在大多數情況下,本地HTML內容直接從Adobe AIR應用程式的安裝目錄載入,這一操作將同時更新應用程式沙箱中的內容,並且支援Adobe AIR API的完整訪問以及JavaScript/ActionScript之間的雙向通訊。當從本地檔案系統載入HTML資料時(在應用程式安裝目錄外面),它將被放置在本地沙箱中。最後,遠端HTML內容,就像上面的示例程式碼那樣,將放置在它自已的安全沙箱中,這些沙箱基於內容源自的域,同時將會限制訪問在沙箱外為它建立的資源。
這個主要的應用程式沙箱允許充分訪問Adobe AIR API,以及從JavaScript訪問ActionScript程式碼,反之亦然。本章剩下的部分將講述當從AIR應用程式的本地目錄載入所有的HTML時,我們如何同安全沙箱一起工作。
注意:
因為HTML內容被載入到應用程式的安全沙箱中,但是這並不意味著JavaScript將獲得一個一勞永逸的訪問許可權。當在應用程式的沙箱中執行時,關於JavaScript可以執行的程式碼有相當多的侷限性:eval()表示式是受限的,載入遠端JavaScript庫是禁止的,XMLHttpRequest的響應僅限於JSON物件。沒有可執行的JavaScript,沒有cookies等。一個完整的清單,可以參見第7節中標題為“Developing Adobe Air Applications With Adobe Flex 3”的文件中找到,這些也能在www.adobe.com/support/documentation/en/air/#flex中找到。
2. 在不同的沙箱之間互動
載入到沙箱應用程式的內容不能直接與載入到任何其他沙箱的HTML內容通訊。許多意想不到的事情可能發生(就跨站指令碼攻擊方面考慮,但附帶上使用者的AIR應用程式可以訪問的本地檔案,您就可以開始看到可能的錯誤)。
然而,因為它也會對不同沙箱中內容之間的互動進行限制,Adobe AIR提供一組方法來顯式地使不同沙箱中的內容互相通訊。
● 沙箱橋接時,其中顯式地建立一個JavaScript介面,並且顯式地聲明瞭可以來回流動的資料。
● 跨指令碼,在這裡將html內容放置在嵌入的HTML內容中的AIR特定iframe標記中,然後設定幾個AIR特定屬性,如sandboxRoot和documentRoot。
關於細節的處理和AIR中不同安全沙箱之間的通訊不在本書的範圍內。務必提前閱讀前面引用的Adobe文件標題為“HTML內容”的這一節。它像這裡提到的那樣,當在應用程式中遇到過安全性錯誤,或者遇到嵌入的HTML頁面中錯誤的JavaScript程式碼,您就會詳細閱讀Adobe檔案中瞭解具有哪些限制。
39.3.2 載入記憶體中的內容
您可能想要在AIR中快速生成自己的HTML。不通過訪問一個遠端地址,可以只通過為自己的HTML字串提供mx:HTML.htmlLoader來達到目的:
private function loadInMemoryHTML():void
{
var html:XML =
<html>
<head>
<title>Test Title</title>
</head>
<body>
This is in-memory html
</body>
</html>;
htmlContainer.htmlLoader.loadString(html.toString());
}
這裡,htmlContainer與前面定義的mx:Flex元件相同,除此之外,不設定location屬性,通過設定已包含的htmlLoader的loadString屬性在執行時載入內容。這個程式碼示例也使用Flex 的XML的本地XML在程式碼中宣告XML,從而不需要使用混亂的字串連線。
這個示例中的HTML被載入到AIR應用程式的域中,它允許任何JavaScript直接訪問完整的AIR API,並且允許任何ActionScript HTML內容中的DOM和JavaScript。
39.3.3 載入本地檔案的內容
最後,由於Adobe AIR可以直接訪問本地檔案,因此可以把HTML內容讀取到mx:HTML元件中。這是在示例應用程式中為嵌入式YouTube控制元件建立自定義程式碼的方式:
private function loadCustomEmbeddedPlayerHTML():String
{
var file:File = File.applicationDirectory.resolvePath("embeddedPlayer.html");
var fs:FileStream = new FileStream();
fs.open( file, FileMode.READ );
// Read the entire contents of the HTML file
var html:String = fs.readUTFBytes( fs.bytesAvailable )
fs.close();
youTubeEmbeddedPlayer.htmlLoader.loadString(html);
}
這個函式使用AIR的File類從安裝AIR應用程式的檔案系統路徑中解析對embeddedPlayer.html檔案的引用。這個embeddedPlayer.html檔案宣告所有的HTML,包括把YouTube嵌入式Flash音訊播放器嵌入到HTML中的程式碼。這段程式碼包含引用外部JavaScript以及遠端SWF檔案。
獲取這個檔案引用之後,將把這個檔案引用賦予file變數,然後將建立並以只讀方式開啟FileStream,以便將HTML檔案的內容讀入一個變數。當完成的時候,記得關閉所有開啟的檔案引用。
然後,就像前面處理記憶體中的HTML一樣,把HTML字串載入到youTubeEmbeddedPlayer,這是AIR應用程式中用於呈現的一個mx:HTML控制元件,在MXML中其定義為:
<mx:HTML
id="youTubeEmbeddedPlayer" width="600" height="400"
complete="onHtmlLoadComplete(event)"
verticalScrollPolicy="off"
horizontalScrollPolicy="off"
/>
檢視embeddedPlayer.html檔案的內容
YouTube embeddedPlayer.html檔案包含大量JavaScript程式碼,它使用已歸檔的公有YouTube Embedded Player API來控制它們的嵌入式播放器。
此外,embeddedPlayer.html頁面有一個嵌入式SWF物件,其中包含用來顯示視訊的實際播放器。為了嵌入播放器,HTML程式碼採用swfobject.js程式碼函式庫,其在下面一行HTML中宣告:
<script src="swfobject.js" type="text/javascript"></script>
這從本地應用程式目錄(也即父頁面embeddedPlayer.html所在的相同目錄)載入swfobject.js,因為載入到mx:HTML元件的HTML內容將繼續使用子內容的相對路徑。
YouTube的原始嵌入式示例HTML頁面引用把JavaScript程式碼swfobject.js載入到一個script src HTML中的其中一個伺服器的過程,該HTML如下所示:
<script
src="http://swfobject.googlecode.com/svn/tags/rc3/swfobject/src/swfobject.js"
type="text/javascript">
</script>
Google在自己的伺服器上儲存swfobject.js,這樣,當使用它們的API時,就不必擔心駐留它們的任何特定檔案。但是,因為AIR沙箱的限制,當我們正在嘗試載入用於訪問這些APIS的本地HTML內容時,這並不能起作用。
如前所述,由於沙箱的衝突,將swfobject.js從Google伺服器載入到從本地載入內容的AIR應用程式將無法工作。由於embeddedPlayer.html內容是從AIR應用程式的目錄載入的,因此它被放置到常規的AIR應用程式沙箱中。當AIR應用程式從遠端域http://swfobject.googlecode.com載入swfobject.js時,所有的JavaScript程式碼和引用將放置在swfobject.js自己的沙箱中,它只能訪問自己擁有的有限個沙箱,其中不包括預設的AIR應用程式沙箱。
實現這種功能最簡單的方法是隻下載swfobject.js並從本地目錄載入它,而這正是在該示例中完成的。然而,把不同域中的JavaScript檔案載入到AIR應用程式並建立一個指令碼橋也是可能的。但是,對於這個示例,可能還有更多可行的方法,當可以完全控制使用AIR應用程式釋出的HTML檔案時就不值得建立指令碼橋。