http://blog.sina.com.cn/s/blog_6e4d9a9b0101ny26.html
Phonegap使用的java與js互相調用的原理。phonegap實現的模型剛也說了,有同步和異步兩種。js實現的api,所以是js先會調用java代碼,然後再返回給js。對於同步的而言,就是js調用java,然後java返回一個結果作爲返回值。對於異步的而言,可能js掉了很多java代碼,但是立即返回,然後java代碼執行結束後再回調js代碼,這裏就涉及到js調java,然後java再調用js。
對於js調用java:
js調用java的入口是通過在js中調用prompt方法,這很奇怪吧,這個方法本來是讓瀏覽器彈出個輸入框的。我當初找了好久也沒發現phonegap到底怎麼搞得的讓js調用java的代碼,後來看到一會覺得該是這個方法,但是這是一個瀏覽器的客戶端自己的東西,而且怪異的是瀏覽器並沒有彈出輸入框,後來終於發現。
在DroidGap.java中有個hack,重載了WebviewClient的onJsPrompt方法,然後執行了自己的邏輯。也就是js調用prompt的時候,java端瀏覽器代碼接受到這個,然後在響應的處理函數中根據傳過來的參數,實現了一些特別的邏輯。可以從這個方法的註釋上看出一二。
private LinkedList javascript;
服務器保存要回調的js的代碼,供js客戶端取回,這裏java端是服務器端,js端是客戶端,服務器端不可能請求客戶端做啥,是b/s模型,所以phonegap實現了兩種服務模型,一種是輪詢,一種是XHR異步回調,也就是Ajax的模型。src/com/phonegap/CallbackServer.java是回調服務器的代碼所在處。從類的註釋中可以看到。
This class provides a way for Java to run JavaScript in the web page that has loaded PhoneGap. The CallbackServer class implements an XHR server and a polling server with a list of JavaScript statements that are to be executed on the web page.
CallbackServer提供的這兩種模型,一種是XHR,一種是輪詢,輪詢很簡單了,callbackserver服務器端,有一個保存回調js的列表,前面所說,然後每隔一段時間客戶端的js會詢問一次服務器,是否有需要回調的js,如果有則調用,然後每隔一段時再查詢一次服務器。而基於XHR的,其實這個就是ajax用的機制了,js發起一個異步請求,然後服務器會在返回數據之前保持住這個連接,當返回數據就位後,服務器給請求客戶端返回數據,然後關閉連接。然後客戶端接受並且處理。
剛說了服務器端的代碼實現,現在來看一下客戶端js的相關代碼。
PhoneGap.JSCallback = function() {
...
xmlhttp.open("GET", "http://127.0.0.1:"+PhoneGap.JSCallbackPort+"/"+PhoneGap.JSCallbackToken , true);
xmlhttp.send();
}
這個是XHR模型的代碼,客戶端js使用xhr請求服務器來獲取js代碼,進行回調。
PhoneGap.JSCallbackPolling = function() {
...
var msg = prompt("", "gap_poll:");
if (msg) {
setTimeout(function() {
try {
var t = eval_r(""+msg);
}
catch (e) {
console.log("JSCallbackPolling: Message from Server: " + msg);
console.log("JSCallbackPolling Error: "+e);
}
}, 1);
setTimeout(PhoneGap.JSCallbackPolling, 1);
}
else {
setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod);
}
}
這個是輪詢方式的,可以看到客戶端每隔PhoneGap.JSCallbackPollingPeriod段時間,就請求一次服務器(通過prompt("","gap_poll:");)。
******************************************************************************************************************
iOS:
通過讓本地代碼攔截JavaScript中調用的 window.location=”gap://Class.method/args”命令,來實現從JavaScript到本地代碼之間的通信。在本地 代碼攔截該命令後,解析獲取的參數,然後調用對應的類、方法並傳遞參數。對應的,使用 UIWebView.stringByEvaluatingJavaScriptFromString來實現本地代碼調用JavaScript。
Android:
通 過攔截JavaScript的prompt命令實現從JavaScript到本地代碼的通信。JavaScript prompt命令默認會彈出對話框,而PhoneGap的Android本地代碼會攔截該對話框,並進一步取得JavaScript數據。相應 的,Android上的PhoneGap內部,使用Java實現了一個HTTP服務器,通過持久性的XHR連接,JavaScript可以不斷輪詢內部 XHR服務器存儲的信息,從而實現了從Java到JavaScript方向的通信。
BlackBerry 4.x:
JavaScript 與本地代碼之間的唯一通信方式是通過document.cookie實現的。JavaScript設定Cookie,本地代碼從Cookie中獲取信息。 對應的,本地代碼也可以設定Cookie,允許JavaScript從Cookie中獲取本地代碼信息。
BlackBerry WebWorks:
新 的BlackBerry WebWorks SDK更好地支持了Java與JavaScript之間的交互通信。通過ScriptEngine.addExtension,Java對象可以被暴露給 JavaScript,而對應的Java可以使用ScriptEngine.executeScript來調用JavaScript。
Windows Phone 7:
在Windows Phone 7中,JavaScript通過window.external.Notify可以將信息發送給本地代碼。而相應的,WebBrowser.InvokeScript允許本地代碼調用JavaScript。