PhoneGap android方向解析

PhoneGap源碼解析



Phonegap的核心是插件。在phonegap的概念中,一切調用native功能,都被封裝成插件(plugin),由PlugInManager來管理。而在PhoneGap的使用方法中,PlugInManager是由重寫過的Activity,即DroidGap來調用的。


本文主要涉及到的類是PlugInManager,PlugIn,DroidGap, CallbackServer,主要探討phonegap源碼的實現和可供我們結合使用的方式。


1.

DroidGap繼承於PhonegapActivity,而PhonegapActivity繼承於activity。


PhonegapActivity是一個抽象類,其中方法不多,列舉如下:


abstract public void sendJavascript(String statement);

abstract public void startActivityForResult(IPlugin command, Intent intent, int requestCode);

abstract public void loadUrl(String url);

abstract public void setActivityResultCallback(IPlugin plugin);

abstract public void setActivityResultCallback(IPlugin plugin);


其中sendJavascript和loadUrl是phonegap的關鍵方法。還有兩個關鍵的繼承類,GapViewClient和GapClient。



sendJavascript會被具體的PlugIn回調,例如storage這個插件,在startPlaying方法中,會調用自己的sendJavascript,然後這個sendJavascript會繼續調用DroidGap的sendJavascript,然後繼續調用CallbackServer的sendJavascript方法,添加到CallbackServer的javascript linkedlist中去。


loadUrl事實上是調用了對應的webview的loadUrl,做了一些額外的處理。loadUrl中調用了loadUrlIntoView方法,其中在加載url之前,初始化了CallbackServer, pluginManager,還爲webview設置了超時時間。


DroidGap中,GapViewClient是對WebviewClient的繼承。


主要是針對撥打電話,調用地圖,發送郵件等本Intent的方式進行攔截和調用。這部分代碼我們可以直接copy過來使用。


DroidGap中,GapClient是對WebChromeClient的繼承。

在onJsAlert和onJsConfirm方法中,使用Dialog來代替js的默認實現。

在onJsPrompt中,對滿足以下條件


(url.startsWith("file://") || url.indexOf(this.ctx.baseUrl) == 0 || isUrlWhiteListed(url))

1).file://開頭的本地文件

2).在請求的url域名內

3).在配置的url白名單內,白名單是一個配置文件,通過addWhiteListEntry添加。 放在xml目錄下的phonegap.xml文件。默認配置了http://127.0.0.1。


並且滿足例如"gap:"等情況。進行了自行重寫。


重寫條件如下:

1)滿足"gap:"開頭的,調用plugInManager進行處理。此時每個gap:後面的內容會對應一個具體的調用本地操作的功能。例如攝像頭,本地存儲等。

2)滿足"gap_poll:"開頭的,調用callbackServer.getJavascript();

3)滿足"gap_callbackServer:"開頭的,調用callbackServer.restartServer()等操作。

4)滿足"gap_init:"開頭的,將webview設置爲不可見


其他情況,依然是以一個dialog形式彈出。


重點說一下重寫條件1)

調用PlugInManager的時候,每次都會重新開啓一個線程,在開啓線程前還做了一次同步檢查,保證同一時刻同一個插件只被調用一次。在線程中,調用對一個PlugIn,執行PlugIn的exec方法,執行具體功能。執行完成之後,返回一個PluginResult。其中以status標示了本地功能調用結果。如果調用成功或者無結果(也可以說是另一方面的調用成功,比如notifacation這種功能),則調用DroidGap的sendJavaScript方法,通知給CallbackServer。


另外還重寫了onPageFinish等一系列方法,我們都可以參考。


按我的理解,在這個部分的寫法的好處,從模式上講是將本地功能模塊化,明晰化,封裝的比較好,各自調用自己的功能,從執行效率上講避免了主線程執行功能,但是在異步線程中操作數據庫等功能,會不會引起問題,這個可能也是未來我們結合phonegap的方式來處理自己的程序需要注意的地方。


2.

另外一個比較重要的工具類是CallbackServer,這也是phonegap框架後來改名爲CallBack的原因。它是一個客戶端本地實現的 XHRServer。在調用完js中的代碼,執行完本地的功能後,需要給js發送一個反饋,也就是調用sendJavaScript方法。


初始化CallbackServer的時候,會建立一個泛型爲String的LinkedList,用於保存javascript代碼。CallbackServer在外部被調用最多的sendJavascript方法,實現中就是將發送過來的Js語句,添加到這個LinkedList中。

如果要加載的url不是以file://開頭,就會建立一個新的線程,CallbackServer本身是實現了Runnable接口的,這個線程就以this作爲參數。同時start這個線程。

所以,在整個CallbackServer中,最核心的方法凸顯出來了,就是Run。


Run方法中,建立了一個ServerSocket,將自己作爲一個服務器來接收請求。

當LinkedList中有沒有處理完的返回結果的時候,就會把鏈表中的最先進來的提出來,返回給客戶端。沒有請求來,則 10秒鐘返回一個空的回覆,以維持XHRServer。


在PhoneGap.js中,PhoneGap.JSCallbackPolling會被setTimeout(1)作爲輪詢,來訪問這個CallBackServer,監聽js需要處理的內容。

我個人對這個地方有些疑問,因爲這麼短時間的輪詢,雖然是本地執行,但是會不會有效率問題,需要真正進入開發實戰和測試後才能體現。



3.

至此,綜合1和2,phonegap對於本地方法的調用的結構已經清晰。

在對javascript的執行上,phonegap給我們提供了一個有別於addJavaScriptInterface 的另外一種方法。在phonegap1.0之前,它就是採用原生的addJavaScriptInterface 這種方法進行調用,後來才改成xhrserver的方式。原因可能是addJavaScripteInterface是一種同步調用,對效率較低或執行時間較長的js語句,會產生阻塞。

在對本地方法的調用上,phonegap給我們提供了一個用js來調用java的插件框架,我們可以這種思路拆分出來,並且進行優化,我目前覺得phonegap對插件的使用上還是比較死板,本地方法的調用都集成在phonegap.js中,實際上還是很難由用戶添加新功能,如果不改動此主要js文件的情況下。如果配合反射等手段,我們可能可以做到真正的插件化本地調用,用在我們的代碼中。

轉自:http://blog.csdn.net/yangdeli888/article/details/7419382

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章