使用面向 iOS 的本機插件擴展 PhoneGap – iPhone手機開發技術文章 iPhone軟體開發教學課程

本文細致探討瞭 Xcode(以 iOS 設備為目標)中的 PhoneGap(也稱為 Apache Cordova)應用程序本機插件。如果您剛開始接觸 PhoneGap 或者需要回顧 PhoneGap 基礎知識,請先閱讀 Xcode
for iOS 的 PhoneGap 入門,然後再繼續閱讀本文。

本文交替使用術語 CordovaPhoneGap 指示同一開源應用程序平臺,該平臺可供您使用 HTML 和 JavaScript 創建本機安裝的移動應用程序。PhoneGap 代碼庫已遷移至 Apache 軟件基金會的開放資源中,名為 Cordova。Adobe 則仍以 PhoneGap 名稱進行分發。有關更多信息,請參閱 Brian Leroux 發佈的博客文章“PhoneGap、Cordova、名稱有什麼關系?”正如
Brian 在這篇文章中所說,“目前唯一的區別在於下載包名稱的不同,並且這種情況仍將維持一段時間。

PhoneGap 不僅可讓您利用 Web 技術為本機安裝的移動應用程序構建用戶界面,還能提供基於 JavaScript 的 API 供您與本機設備功能進行交互。默認情況下,PhoneGap 可訪問設備攝像頭、加速計、文件系統、GPS 位置及其他功能間的媒體重放。但是,PhoneGap 並未揭示供您在 JavaScript 應用程序內使用的每一個本機 API。如果您希望 PhoneGap 執行其默認功能集以外的操作,可以使用 PhoneGap 本機插件模型擴展核心 PhoneGap API 的功能。

PhoneGap 本機插件與桌面瀏覽器的插件不同;它們為您提供瞭一種插件自定義代碼以增加 PhoneGap 應用程序框架功能的方式。PhoneGap 本機插件可讓您以本機代碼的形式創建全新的自定義功能,並通過 PhoneGap 的本機-JavaScript 橋將其顯示給 PhoneGap 應用程序。這意味著,您可以顯示所有本機庫或框架,以便在基於 JavaScript 的 PhoneGap 應用程序內部使用。

瞭解 PhoneGap 本機插件的結構

在您開始編寫 PhoneGap 本機插件之前,瞭解 PhoneGap 應用程序容器如何向基於 JavaScript 的應用程序顯示本機操作系統功能將會有所幫助。

所有 Cordova API 均包含以下兩個有關部件:一個可以在您的應用程序內部進行訪問的基於 JavaScript 的界面,以及用於以本機代碼執行操作的對應本機類。通常情況下,JavaScript 類和本機類具有相互鏡像的 API,這樣就能輕松地進行跟蹤。JavaScript 類使用 Cordova.exec() 函數調用本機代碼。當它調用 Cordova.exec時,可將其傳遞至結果處理程序函數和錯誤處理程序函數,同時還會將一組參數傳遞至本機代碼,並將引用傳遞至本機類名稱和本機函數名稱。Cordova
將負責管理 JavaScript 與本機之間的通信,您可以專心構建自己的應用程序。

要瞭解有關 PhoneGap 本機插件的更多信息,請登錄 Cordova
wiki 查看該核心 API 的源代碼。整個 PhoneGap 框架均構建於同一模式之上,您可以在這裡瞭解這一模式。

構建首個插件

要開始構建您的首個 PhoneGap 插件,您需要按照 Xcode
for iOS 的 PhoneGap 入門一文中所述的步驟創建一個新 PhoneGap 項目。我將自己的項目命名為 MyFirstPhoneGapNativePlugin。

JavaScript 類

在您設置完 Hello
Xcode 項目後,即可準備為本機插件創建 JavaScript 界面。您需要使用函數(將要鏡像通過本機代碼顯示的邏輯)創建類。在 www 文件夾下,創建一個名為 HelloPlugin.js 的 JavaScript 文件,其中包含如下所示的簡單 JavaScript 類。

var HelloPlugin = { callNativeFunction: function (success, fail, resultType) { return Cordova.exec( success, fail, "com.tricedesigns.HelloPlugin", "nativeFunction",
[resultType]); }};

HelloPlugin 類包含一個名為 callNativeFunction 的函數,它接收瞭一個成功回調函數、一個錯誤回調函數和一個 resultType 字符串參數。callNativeFunction 函數包含 Cordova.exec 函數,因而將會調用實際本機代碼。此類中沒有其他 JavaScript,但您可以根據自身需要在此處添加
JavaScript 代碼。

調用 Cordova.exec 後,將會看到以下五個參數:

  • 一個成功回調函數(本機代碼層成功響應時調用的函數)引用

  • 一個錯誤回調函數(本機代碼層錯誤響應時調用的函數)

  • 一個本機代碼類字符串引用(我將會在下文進行詳細介紹)

  • 一個應當調用的函數名稱字符串引用

  • 一個將要傳遞至本機代碼的參數數組

    請記住,JavaScript 和本機代碼層之間的代碼執行操作並不同步,因此,在開發 PhoneGap 本機插件時需要使用回調函數和異步編碼實踐。

    本機類

    要創建本機代碼層,請首先創建一個新的本機 Objective-C 類,它擴展核心 Cordova API 的 CDVPlugin 類:

    1. 右鍵單擊 PhoneGap 項目內的 Plugins 目錄,然後選擇 New File(參見圖 1)。

      創建新文件。

      圖 1. 創建新文件。

      1. 在 New File 向導中,選擇 Objective-C 類模板,然後單擊 Next(參見圖 2)。

        選擇 Object-C class 模板。

        圖 2. 選擇 Object-C class 模板。

        1. 鍵入 HelloPlugin 作為新類的名稱,並將該類納為 CDVPlugin 的子類(參見圖 3)。

          命名該類。

          圖 3. 命名該類。

          CDVPlugin 類是所有 Cordova 類均必須擴展的父類。CDVPlugin 類通過 PhoneGAP API 封裝本機 JavaScript 通信所需的所有必要邏輯。PhoneGap.exec 函數可讓您調用該新類上的函數。CDVPlugin 類包含一個名為writeJavascript 的核心函數,可讓您調用 PhoneGap 應用程序 Web 視圖內的 JavaScript。本機到 Web JavaScript
          這一方向的所有通信均必須使用 writeJavascript 函數完成。

          1. 單擊 Next。

          2. 出現提示後,為新文件指定位置(最好指定在 Xcode 項目內的 Plugins 目錄下),然後單擊 Finish 繼續操作。

            您將會在 PhoneGap 項目內看到一個新的頭文件 (.h) 和一個新的實現文件 (.m)(參見圖 4)。

            圖 4. 新的本機類文件。

            圖 4. 新的本機類文件。

            1. 接下來,在您的 .h 文件中為 nativeFunction 函數添加定義;例如:

              #import @interface HelloPlugin : CDVPlugin- (void) nativeFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;@end

              此定義包含以下兩個參數:一個是 NSMutableArray,其中包含從 JavaScript 層和選項字典(地圖)接收到的參數。在本例中,您隻需要關註參數數組。頭文件隻包含方法簽名;您無需在 .h 文件中包含任何應用程序邏輯。

              1. 在您創建類簽名後,將邏輯添加到 .m 文件的 nativeFunction 函數實例中。您將在下面看到此本機插件類內部使用的 Objective-C 函數示例。

                #import "HelloPlugin.h"@implementation HelloPlugin- (void) nativeFunction:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options { //get the
                callback id NSString *callbackId = [arguments pop]; NSLog(@"Hello, this is a native function called from PhoneGap/Cordova!"); NSString *resultType = [arguments objectAtIndex:0]; CDVPluginResult *result; if ( [resultType isEqualToString:@"success"] ) { result
                = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: @"Success :)"]; [self writeJavascript:[result toSuccessCallbackString:callbackId]]; } else { result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString: @"Error
                :("]; [self writeJavascript:[result toErrorCallbackString:callbackId]]; }}@end

                nativeFunction 方法內部,您首先需要獲取一個 NSString callbackId 引用,核心 PhoneGap API 借此將此函數響應映射到調用此函數的原始 JavaScript。

                接下來,此方法使用 NSLog 將消息寫入 Xcode 調試控制臺;這隻是表明它目前正在執行本機代碼。

                寫入到調試控制臺後,該函數將會檢查傳遞到該函數的 resultType,然後創建相應的 CDVPluginResult 實例。resultType 值是一個簡單字符串。如果 resultTypesuccess",則該函數將創建 success 結果,並使用 [self
                writeJavascript]
                函數將成功回調函數寫入 JavaScript 層。任何其他 resultType 參數值均將生成 error 結果,並且該函數會將錯誤回調寫入 JavaScript 層。

                當您將成功或錯誤回調函數寫回 JavaScript 時,始終使用 CDVPluginResult 實例。但是,您也可以使用writeJavascript 函數將任意 JavaScript 字符串傳遞回 JavaScript 層。這項技術甚至還可用於將數據從本機層實時推送至 JavaScript 層。

                調用插件

                鑒於您已經創建插件,因而可以從 PhoneGap 應用程序內部進行調用。

                1. 首先,您需要向新插件的 JavaScript 接口類 (HelloPlugin.js) 添加一個引用。在您的 index.html 文件內添加一個新的 <script> 標記:

                  <script type="text/javascript" charset="utf-8" src="HelloPlugin.js"></script>

                  1. 同樣也是在onDeviceReady() 函數後,添加 JavaScript 以調用本機插件及處理插件結果。添加名為callNativePluginnativePluginResultHandlernativePluginErrorHandler 的 JavaScript 函數,如下所示:

                    function callNativePlugin( returnSuccess ) { HelloPlugin.callNativeFunction( nativePluginResultHandler, nativePluginErrorHandler, returnSuccess );} function
                    nativePluginResultHandler (result) { alert("SUCCESS: \r\n"+result );}function nativePluginErrorHandler (error) { alert("ERROR: \r\n"+error );}

                    1. callNativePlugin 函數隻需調用 JavaScript 的本機插件類接口。當其調用 callNativeFunction 方法時,即會傳遞從本機代碼層接收到的成功和錯誤狀態回調函數。如果本機層成功返回回調函數,將會調用nativePluginResultHandler 函數,而當本機層傳回錯誤回調時,則調用nativePluginErrorHandler 函數。

                      1. 接下來,根據下列代碼添加兩個 JavaScript 按鈕以調用該插件。

                        Hey, it's Cordova!


                        單擊第一個按鈕將調用 callNativeFunction 方法,同時生成參數 “success”。PhoneGap 將於隨後執行本機代碼並在 JavaScript 層調用成功回調(它將會調用 nativePluginResultHandler 函數)。

                        當您單擊第二個按鈕時,將會調用 callNativeFunction 方法,同時生成參數 “error”。PhoneGap 將執行本機代碼並在 JavaScript 層調用錯誤回調(它將會調用 nativePluginErrorHandler 函數)。

                        映射本機代碼類

                        此時,您幾乎已將所有事物串聯起來並可準備執行操作,但您還必須再完成一個步驟,才能調用 JavaScript 中的本機代碼。

                        您必須添加一個映射,以便 Cordova 識別您的本機代碼類。還記得在調用 Cordova.exec 時用來識別本機類的字符串引用嗎?您需要將該字符串映射到 Cordova.plist 文件中的實際類實例。Cordova.plist 文件包含當前 Cordova 項目的所有配置信息。

                        1. 在項目導航器中,打開 Supporting Files 文件夾,然後單擊名為 Cordova.plist 的文件。

                        2. 在右側向下滾動至 Plugins 條目並單擊將其展開。

                        3. 添加一個帶有 code>com.tricedesigns.HelloPlugin 項和 "HelloPlugin" 值的條目(參見圖 5),用貴公司的標識替換 com.tricedesigns。當調用 Cordova.exec 時,您將利用此字符串引用識別第三個參數中的本機類。

                          keyPhoneGap.exec 映射至本機代碼類所使用的唯一一個字符串引用。value是將要調用的實際本機類名稱。

                          1. 保存更改。

                            編輯 Cordova.plist。

                            圖 5. 編輯 Cordova.plist。

                            現在,您可以啟動該應用程序並進行徹底檢查。

                            要啟動該應用程序,請單擊 Run 按鈕或選擇 Product > Run。

                            在 iOS Simulator 中(或連接設備上)啟動該應用程序後,您將會看到帶有兩個按鈕的簡單界面(參見圖 6)。單擊任一按鈕調用本機插件的本機代碼,無論調用成功回調還是錯誤回調,都會通過 JavaScript 顯示一條警告消息。

                            iOS 模擬器中運行的應用程序。

                            圖 6. iOS 模擬器中運行的應用程序。

                            當調用本機代碼時,您還能夠在 Xcode 調試控制臺窗口中看到輸出內容,反映調用本機插件 NSLog 生成的輸出內容(參見圖 7)。

                            Xcode 調試控制臺的記錄信息。

                            圖 7. Xcode 調試控制臺的記錄信息。

發佈留言