簡介: 移動應用開發(fā)已經(jīng)成為軟件開發(fā)的一個重要方向,但是移動開發(fā)面臨的一個重要問題就是跨平臺的問題。 PhoneGap 作為一個多平臺的軟件開發(fā)框架,提供了一次編寫多個平臺的運行。目前已經(jīng)支持多達 6 個移動平臺。對應平臺的插件開發(fā)則可以為 PhoneGap 擴展 API 的本地接口,提供更加復雜的特性。了解 PhoneGap 框架的原理以便為 PhoneGap 提供本地的插件接口成為 PhoneGap 應用開發(fā)的重要方面。本文將以一個簡單的實例介紹 PhoneGap 在 Android 上的插件開發(fā)方法。閱讀本文需要基本的 Android 開發(fā)經(jīng)驗和 PhoneGap 開發(fā)經(jīng)驗。
PhoneGap 是利用 HTML 來開發(fā)移動應用的一個開放源代碼的框架,利用它就可以僅僅使用 HTML 和 Javascript 實現(xiàn)一次編寫,多個移動平臺運行的應用。目前已經(jīng)可以支持 Android、iOS、BlackBerry 等 6 個平臺。在完成這篇短文的過程中,PhoneGap 正式發(fā)布了 1.0.0 版本。因而短文中的版本使用的是 1.0.0rc2 版本的代碼。 PhoneGap 在 Android 平臺上的實現(xiàn)的框架是利用了在本地代碼和瀏覽器間建立中間層來實現(xiàn)對 Java 代碼的隔離。利用瀏覽器的接口和網(wǎng)絡 socket 接口實現(xiàn)數(shù)據(jù)的通訊。因此在對 PhoneGap 框架的理解上,需要從 Java 端和瀏覽器端兩部分來分別學習。 關于 Android 開發(fā)環(huán)境和 PhoneGap 開發(fā)環(huán)境的搭建,請參考參考資料中的開發(fā)者網(wǎng)站實施。
Java 端作為后臺調(diào)用 Android 本地 SDK 的接口,主要實現(xiàn)了如下的功能:
而這三部分的功能對應到代碼中則是如下的幾個重要的 Java 類:
因此我們需要依次來了解這幾個重要的 Java 類的具體實現(xiàn),這樣才可以對 PhoneGap 在 Android 上的體系有一個很好的了解。 當我們完成一個基本的 PhoneGap 的示例后,我們就會發(fā)現(xiàn),在使用 PhoneGap 進行開發(fā)的手機應用中,第一步就是將繼承關系 extends Activity 修改為 extends DroidGap。因此,DroidGap 是整個應用開始的地點,首先需要了解 DroidGap 的內(nèi)容。 在源碼中可以看到 DroidGap 繼承自 PhonegapActivity,而 PhonegapActivity 是一個抽象類,繼承自 Activity,但是具體的實現(xiàn)都是集中在 DroidGap 類中。 因此,我們繼續(xù)回到 DroidGap 類中,當我們知道 DroidGap 類也是一個 Acitvity 后,就會明白,DroidGap 在 onCreate 方法中實現(xiàn)了整個類最初的一些操作,代碼的實現(xiàn)則集中在 onCreate() 和 init() 這兩個方法中,具體的流程如下:
設置 WebView 的代碼都集中在 init() 方法中,其中一個值得注意的工作是設置 WebChromClient。代碼中提供了一個繼承自 WebChromClient 的類,重寫了其中的 onJsAlert,onJsConfirm,onJsPrompt 等方法。而在 onJsPrompt() 方法中,實現(xiàn)了 PhoneGap 中 Java 端和瀏覽器端通訊的關鍵一步。因此,值得我們專門的關注其代碼,具體的功能實現(xiàn)代碼如下,我們已經(jīng)過濾了一些錯誤處理、安全驗證等等可能會妨礙我們對重要 的功能實現(xiàn)理解的代碼: 代碼清單 1. WebView 代碼
在此,我們就可以明白,實現(xiàn) JavaScript 與 Java 端通訊的原理是 JavaScript 利用 prompt 來傳遞調(diào)用信息的數(shù)據(jù),在 onJsPrompt 中,重寫的方法截獲了這些數(shù)據(jù),在完成了對數(shù)據(jù)格式等等分析后,按照要求進行具體的調(diào)用。而具體的調(diào)用利用是的 PluginManager 類,這將在隨后說明。
在完成 WebView 的設置后,再將 PhoneGap 和 js 綁定,實現(xiàn) js 與 PhoneGap 的通訊。在這一步中主要的內(nèi)容就是實例化了 CallbackServer 和 PluginManager 兩個類。因此,更多的內(nèi)容會在隨后對這兩個類的介紹中再說明。
LoadUrl 方法也是實現(xiàn)一個 PhoneGap 示例后很熟悉的方法,在 loadUrl 中,完成基本的字符串處理后,主要利用 runOnUiThread 開始處理,其中第一步檢測是否需要提供載入的顯示,之后使用 WebView 的 loadUrl 載入內(nèi)容,并且設置超時時間。 至此,Java 端的準備工作也就完成,實現(xiàn)了 UI 的載入。可以看到,在 DroidGap 類中最重要的一個部分就是截獲 JavaScript 的 prompt 數(shù)據(jù)。這是實現(xiàn)瀏覽器端和 Java 端通訊的基礎。 Plugin 是一個抽象類,實現(xiàn)了 IPlugin 接口,PhoneGap 中利用 Android SDK 實現(xiàn)邏輯代碼的途徑就是通過繼承 Plugin 來實現(xiàn)。應此 Plugin 本身非常簡單,最主要的部分是提供一個 execute 方法,如下:
Plugin 的實現(xiàn)中的重要邏輯在其中來實現(xiàn),它返回的是一個 PluginResult 對象,這個對象主要負責傳遞數(shù)據(jù)信息,包括的成員主要如下:
用于返回狀態(tài),status 與一個 enum 類型相關,用于標注插件的執(zhí)行結果如何。
用于返回數(shù)據(jù)信息。 PluginManager 事實上是 DroidGap 類和具體的繼承自 Plugin 的插件的聯(lián)系紐帶,由它來尋找和載入插件,并且調(diào)用。 首先,PluginManager 在構造函數(shù)中,調(diào)用了 loadPlugins 方法,該方法負責解析 xml 配置文件,對應每個 plugin,調(diào)用一次 addService 用于注冊插件,具體的注冊地點,是通過維護一個 HashMap<String, String> 來實現(xiàn),分別保存 serviceType, className。在成員中,有另外一個 HashMap<String, IPlugin> 用于實現(xiàn) className 和 IPlugin 類的綁定。這樣就實現(xiàn)了 serviceType 和 IPlugin 的對應。 在 PluginManager 中,執(zhí)行插件的方法 exec 是主要功能,我們將會詳細說明一下這個方法的過程:
執(zhí)行結果的轉(zhuǎn)換則是利用 PluginResult 中的一些 to***String 方法。這些方法返回了一個 String 類型,其中包括了具體的 JSON 對象和 callbackId,具體的形式則是一個 js 代碼,用于前端的調(diào)用。 CallbackServer 實現(xiàn)了 Runnable 接口,具體的功能就是維護一個數(shù)據(jù)的隊列,并且建立一個服務器,用于 XHR 的數(shù)據(jù)傳遞,對數(shù)據(jù)的隊列的維護利用的是 LinkedList<String>。 由于實現(xiàn)的是 Runnable 接口,在 CallbackServer 中,最主要的方法就是 run() 方法,run() 方法的具體內(nèi)容簡介如下:
之后就是對隊列維護的方法,這時理解之前的 sendJavaScript 則很簡單,該方法與 getJavaScript 相反,一個是從 LinkedList 中取出 js 代碼,一個則是加入。 綜上,CallbackServer 實現(xiàn)的是兩個功能,一個是 XHR 的 SocketServer,一個是對隊列的維護。而完成 CallbackServer 類的說明后,Java 端的主要功能也都說明完畢。隨后會說明瀏覽器端的說明,在完成瀏覽器端說明后,我們就會明白整個 PhoneGap 框架運行的原理。
瀏覽器端的 JavaScript 代碼較多,但是實現(xiàn)其中核心功能的代碼都在 PhoneGap 類中,其他的都是 PhoneGap 框架中自帶的一些 Plugin 的 JavaScript 代碼。 在瀏覽器端,其中一個最重要的函數(shù)就是 PhoneGap.exec 函數(shù),因為大部分的函數(shù)調(diào)用,最終都會在這里實現(xiàn)與本地 Java 端的數(shù)據(jù)通訊,轉(zhuǎn)而去調(diào)用 Java 端的 Plugin 來實現(xiàn)具體的執(zhí)行。主要的內(nèi)容如下,我們已經(jīng)去除一些非功能的錯誤處理代碼段,集中于具體的功能實現(xiàn): 代碼清單 2. PhonGap.exec 代碼
在以上標紅加粗的代碼段上,我們可以看到,調(diào)用的是 prompt 方法 , 我們在之前特別提到了,PhoneGap 在 DroidGap 類中,繼承了一個 這時我們會有一個好奇,那就是 CallbackServer 的 SocketServer 的作用在哪里,因為至此我們已經(jīng)看到了整個數(shù)據(jù)在瀏覽器端和 Java 端的通訊,那么這樣的一個 SocketServer 又是提供的什么數(shù)據(jù)通訊呢? 顯然,在 PluginManager 中的
掌握了上文中對 PhoneGap 框架的分析,我們就可以通過自己實現(xiàn)相關的插件來完成自己希望實現(xiàn)的功能,這樣就可以不斷豐富自己應用的功能。我們假設開發(fā)者已經(jīng)熟悉了 PhoneGap 和 Android 的基本開發(fā)知識,Android 和 PhoneGap 開發(fā)環(huán)境搭建已經(jīng)完成。 在具體的 Plugin 實現(xiàn)中,要分兩個部分來實現(xiàn),Java 代碼和 JavaScript 代碼,就此流程,我們來通過一個簡單的例子來看一下如何具體的完成 Plugin 的實現(xiàn)。 在 Java 端,我們要繼承一個 Plugin 類,實現(xiàn)其中的 execute 方法,在這里,我們省略具體的功能邏輯。 在 JavaScript 端,我們要利用現(xiàn)有 PhoneGap.exec 來調(diào)用具體的 Java 端,而且需要注意的是要在 PhoneGap 中注冊這一個插件, 首先,完成 Java 端的代碼實現(xiàn)。 我們實現(xiàn)一個簡單的字符串回射程序,來模擬具體的邏輯,代碼如下: 清單 3. 插件實例 Java 端代碼
實現(xiàn)的功能如下:
之后,完成 JavaScript 代碼 請注意 JavaScipt 代碼是需要 HTML 代碼包含后才能使用的: 清單 4. 插件實例 JavaScript 端代碼
在這里我們需要有一個特別的說明: 在上述 JavaScript 代碼中,我們注釋了 addConstructor 函數(shù)中的一行,因為我們在開發(fā)過程中發(fā)現(xiàn)這條代碼的執(zhí)行在 Javascript 端沒有被實現(xiàn)。 因此這段代碼具體的執(zhí)行則需要我們在 Java 端實現(xiàn)代碼,那么為了實現(xiàn)這段 JavaScript 代碼所做的補償性的 Java 代碼要在自己實現(xiàn)的 Java 端的 onCreate 函數(shù)中實現(xiàn),內(nèi)容是很簡單的一句(當然,也可以通過修改 xml 文件來實現(xiàn)這一功能,上文提到過,PluginManager 類會掃描 xml 文件來依次以對應 xml 文件中的插件名作為參數(shù)執(zhí)行這一調(diào)用):
注意第二個參數(shù)是實現(xiàn)的插件的代碼的位置,Hello 插件的位置是“src.qj.Hello.java”,對應的位置信息就是去除 .java 后綴名后的位置信息,整個項目的組織結構如圖。 圖 1. 項目組織結構圖示例 至此,Hello 插件已經(jīng)實現(xiàn),如果需要調(diào)用,則 JavaScript 代碼如下: 清單 5. 插件調(diào)用代碼
我們簡單的將返回的數(shù)據(jù)通過 alert() 展示出來,插件的執(zhí)行結果如下: 點擊 SayHello, 圖 2. 點擊 SayHello 示例 點擊 SayBingo 圖 3. 點擊 SayBingo 示例
至此插件的開發(fā)已經(jīng)完成,其中很大的篇幅都是通過對 PhoneGap 的框架的說明,讓我們可以對插件的運行過程有一個更加底層的認識,我想這是比實現(xiàn)一個簡單的插件更加重要的東西。如果讀者需要了解更多的信息,請瀏覽參考資料中的開發(fā)者網(wǎng)站,獲得更加實時的信息。 文章出處:IBM developerWorks
|
|