PhoneGap原理分析

PhoneGap提供了Native Api的支持(如:重力感應、相機、聯繫人、文件、地址位置…),javascript

好比要用js獲取本機的聯繫人,能夠用:html

      var options = new ContactFindOptions();java

        options.filter = "";android

        options.multiple = true;git

        var fields = ["displayName", "phoneNumbers", "emails"];github

        navigator.contacts.find(fields, onSuccess, onError, options);apache

就樣就能夠獲取到名稱中包含‘李’的人了。json

 

如今PhoneGap彷佛已經成爲apache開源項目api

 

PhoneGap主頁數組

http://phonegap.com/

 

apache cordova(android版)

http://incubator.apache.org/cordova/index.html

源碼:https://github.com/apache/incubator-cordova-android

文檔:https://github.com/apache/incubator-cordova-docs

 

 

 

 

org.apache.cordova.CordovaChromeClient.onJsConfirm(WebView view, String url, String message, final JsResult result);

這個方法會攔截html頁面發送過來的Native Api請求(調用window.prompt()),而後交由對應的Plugin處理。

 

 

 

1.   服務器流程:

1) Plugin來提供服務供客戶端js調用,參見PhoneGap的plugin配置文件:plugins.xml,若是要本身定製plugin,須要繼承Plugin類並在plugins.xml中進行相應的配置。

2) 同步/異步

服務器根據2個參數來判斷是同步OR異步,

客戶端傳過來的異步參數 + 服務端Plugin.isSynch(action)

若是是同步,則直接把處理請求並把響應寫到客戶端

若是是異步,則啓動一個線程來處理,處理完後,將結果經過CallbackServer寫到客戶端。

3) CallbackServer至關於xmlHttpResponse,負責將數據異步寫到客戶端。它在內部會有一個socket監聽,不停的接收來自於客戶端的請求,

若是發現變量(javascript)中有數據的話,就寫到客戶端,

若是沒有,則睡眠10s,10s後,若是有數據,則寫到客戶端,不然寫一個404異常到客戶端而後這次鏈接中斷,從新接收新的客戶端請求(客戶端有一個輪詢,若是服務端返回404,則客戶端會每隔一段時間請求一次服務器)

4) 服務器異步返回給客戶端的數據格式:

// 正常處理後的返回(Contacts2表示請求的ID,客戶端根據這個ID調用對應的回調函數):

// 其中,紅色的json對象是PluginResult對象(自定義plugin時也須要返回一個PluginResult對象

// 黑色的javascript腳本是通過PluginManager.exec()包裝過的,被客戶端eval解釋執行。

HTTP/1.1 200 OK

require('cordova').callbackSuccess('Contacts2',{status:1,message:[{"displayName":"%E6%9D%8E%E6%8C%9A","id":"44","rawId":"46","phoneNumbers":[{"type":"mobile","value":"18608020312","id":"92","pref":false}]}],keepCallback:false});

 

// 404保持鏈接的返回

HTTP/1.1 404 NO DATA

 

2.   客戶端流程:

1) 調用Native Api

PhoneGap的js框架,在調用Native Api時,都會匯聚到exec這個方法:

define('cordova/exec', function(require, exports, module) {

    var cordova = require('cordova');

module.exports = function(success, fail, service, action, args) {

        try {

            var callbackId = service + cordova.callbackId++;

            if (success || fail) {

                cordova.callbacks[callbackId] = {

                    success: success,

                    fail: fail

                };

            }

        //這裏給服務器發送請求,

        //service表示採用哪一個

//true表示採用異步調用

//服務器會判斷這個service+action是否支持異步調用

//若是是同步,則服務器會當即返回處理結果到變量r

//若是是異步,則服務器返回空串」」

            var r = prompt(JSON.stringify(args),

"gap:" + JSON.stringify([service, action, callbackId, true]));

            // If a result was returned

            if (r.length > 0) {

          ……

            }

        } catch(e2) {

            console.log("Error: " + e2);

        }

    };

});

2) 異步回調

define('cordova/plugin/android/callback', function(require, exports, module) {

    ……

    callback = function() {

        ……

        var xmlhttp = new XMLHttpRequest();

        xmlhttp.onreadystatechange = function() {

            if (xmlhttp.readyState === 4) {

                // 服務器端返回結果數據,客戶端經過eval執行結果

            // 再次往服務器發起請求。

                if (xmlhttp.status === 200) {

                    // Need to url decode the response

                    var msg = decodeURIComponent(xmlhttp.responseText);

                    setTimeout(function() {

                        try {

                            var t = eval(msg);

                        } catch(e) {

                            console.log("JSCallback: Message from Server: " + msg);

                            console.log("JSCallback Error: " + e);

                        }

                    }, 1);

                    setTimeout(callback, 1);

                }

                // 服務器與客戶端約定若是404,則客戶端接着請求服務器,10s內,

            // 若是客戶端調用了Native Api,則服務器服務數據後,進入上面200的邏輯,

            // 若是客戶端沒調用,則服務器依然返回404,如此循環

                else if (xmlhttp.status === 404) {

                    setTimeout(callback, 10);

                }

             ……

            }

        };

        xmlhttp.open("GET", "http://127.0.0.1:" + port + "/" + token, true);

        xmlhttp.send();

    };

});

 

3.   自定義plugin流程:

1) 服務端:

繼承com.phonegap.api.Plugin類,重寫execute方法

public PluginResult execute(String action, JSONArray args, String callbackId){}

在plugins.xml中配置咱們的類,

<plugin name="LoginPlugin" value="com.synnex.plugin.LoginPlugin"/>

 

NOTE:

isSynch()方法是告訴PhoneGap框架,此處理是同步OR異步,true表示同步,false表示異步,默認爲flase

在同步處理的時候,不要去作UI操做(如:修改EditText內容),能夠交由Handler更新UI

2) 客戶端:

// PhoneGap註冊服務

var LoginPlugin = function(){};

LoginPlugin.prototype.dologin = function(successCallback, failureCallback, args)

{

 //」LoginPlugin」須要與服務端xml中的名稱一致。

 //」login」即傳給服務端excute()方法的action參數

 //args必須是一個數組,對應execute()方法的args參數

 return cordova.exec(successCallback, failureCallback, "LoginPlugin""login"args);

};

cordova.addConstructor(function()

{

 cordova.addPlugin("loginPlugin", new LoginPlugin());

});

 

 

// 調用時:

// 此處loginPlugin爲上面addPlugin的第1個參數,

// dologin爲上面LoginPlugin函數的方法名

// msg爲服務端返回的數據。

       plugins.loginPlugin.dologin(function(msg)

         {

              navigator.notification.alert(msg, undefined, "Success", "OK");

         }, function(msg)

         {

              navigator.notification.alert(msg || "Error", undefined, "Failure", "OK");

         }, [{username: "troyz", password: "123456"}]);

相關文章
相關標籤/搜索