phonegap揭秘-流程

转载请注明出处:http://blog.csdn.net/awebkit


这一节主要解决如下问题:

js(如navigater.camera.getPicture)是如何被解析的?js是如何调用java代码的?即js和java结合的地方


        以如下HTML代码为例,说明浏览器是如何解析的。

<!DOCTYPE html>
<html>
  <head>
    <title>Capture Photo</title>

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

    var pictureSource;   // picture source
    var destinationType; // sets the format of returned value 

    // Wait for PhoneGap to connect with the device
    //
    document.addEventListener("deviceready",onDeviceReady,false);

    // PhoneGap is ready to be used!
    //
    function onDeviceReady() {
        pictureSource=navigator.camera.PictureSourceType;
        destinationType=navigator.camera.DestinationType;
    }

    // Called when a photo is successfully retrieved
    //
    function onPhotoDataSuccess(imageData) {
      // Uncomment to view the base64 encoded image data
      // console.log(imageData);

      // Get image handle
      //
      var smallImage = document.getElementById('smallImage');

      // Unhide image elements
      //
      smallImage.style.display = 'block';

      // Show the captured photo
      // The inline CSS rules are used to resize the image
      //
      smallImage.src = "data:image/jpeg;base64," + imageData;
    }

    // Called when a photo is successfully retrieved
    //
    function onPhotoURISuccess(imageURI) {
      // Uncomment to view the image file URI 
      // console.log(imageURI);

      // Get image handle
      //
      var largeImage = document.getElementById('largeImage');

      // Unhide image elements
      //
      largeImage.style.display = 'block';

      // Show the captured photo
      // The inline CSS rules are used to resize the image
      //
      largeImage.src = imageURI;
    }

    // A button will call this function
    //
    function capturePhoto() {
      // Take picture using device camera and retrieve image as base64-encoded string
      navigator.camera.getPicture(onPhotoDataSuccess, onFail, { quality: 50 });
    }

    // Called if something bad happens.
    // 
    function onFail(message) {
      alert('Failed because: ' + message);
    }

    </script>
  </head>
  <body>
    <button οnclick="capturePhoto();">Capture Photo</button> <br>
    <img style="display:none;width:60px;height:60px;" id="smallImage" src="" />
    <img style="display:none;" id="largeImage" src="" />
  </body>
</html>

        从例子中可以看到,在调用 camera 之前已经调用了 phonegap.js ,而在这个 js 里面定义了 camera 等相关类。如下所示。

var Camera = function() {
    this.successCallback = null;
    this.errorCallback = null;
    this.options = null;
};

Camera.prototype.getPicture = function(successCallback, errorCallback, options) {

    // successCallback required
    if (typeof successCallback !== "function") {
        console.log("Camera Error: successCallback is not a function");
        return;
    }

    // errorCallback optional
    if (errorCallback && (typeof errorCallback !== "function")) {
        console.log("Camera Error: errorCallback is not a function");
        return;
    }

    this.options = options;
    var quality = 80;
    if (options.quality) {
        quality = this.options.quality;
    }
    var destinationType = Camera.DestinationType.DATA_URL;
    if (this.options.destinationType) {
        destinationType = this.options.destinationType;
    }
    var sourceType = Camera.PictureSourceType.CAMERA;
    if (typeof this.options.sourceType === "number") {
        sourceType = this.options.sourceType;
    }
    PhoneGap.exec(successCallback, errorCallback, "Camera", "takePicture", [quality, destinationType, sourceType]);
};

PhoneGap.addConstructor(function() {
    if (typeof navigator.camera === "undefined") {
        navigator.camera = new Camera();
    }
});

        这样,就可以调用camara.getPicture接口了(不懂的童鞋请搜索JavaScript原型继承)。

        getPicture最终会调用到PhoneGap.exec,这就到了phonegap.js.base(这是核心啊)这个js里面了。我们看看这个js,如下

PhoneGap.exec = function(success, fail, service, action, args) {
    try {
        var callbackId = service + PhoneGap.callbackId++;
        if (success || fail) {
            PhoneGap.callbacks[callbackId] = {success:success, fail:fail};
        }   

        var r = prompt(PhoneGap.stringify(args), "gap:"+PhoneGap.stringify([service, action, callbackId, true]));

        // If a result was returned
        if (r.length > 0) {
            eval("var v="+r+";");

            // If status is OK, then return value back to caller
            if (v.status === PhoneGap.callbackStatus.OK) {

                // If there is a success callback, then call it now with
                // returned value
                if (success) {
                    try {
                        success(v.message);
                    } catch (e) {
                        console.log("Error in success callback: " + callbackId  + " = " + e); 
                    }   

                    // Clear callback if not expecting any more results
                    if (!v.keepCallback) {
                        delete PhoneGap.callbacks[callbackId];
                    }
                }
                return v.message;
            }

            // If no result

            else if (v.status === PhoneGap.callbackStatus.NO_RESULT) {

                // Clear callback if not expecting any more results
                if (!v.keepCallback) {
                    delete PhoneGap.callbacks[callbackId];
                }
            }

            // If error, then display error
            else {
                console.log("Error: Status="+v.status+" Message="+v.message);

                // If there is a fail callback, then call it now with returned value
                if (fail) {
                    try {
                        fail(v.message);
                    }
                    catch (e1) {
                        console.log("Error in error callback: "+callbackId+" = "+e1);
                    }

                    // Clear callback if not expecting any more results
                    if (!v.keepCallback) {
                        delete PhoneGap.callbacks[callbackId];
                    }
                }
                return null;
            }
        }
    } catch (e2) {
        console.log("Error: "+e2);
    }
};

        看着挺复杂,是不?其实也没那么复杂,就是根据一个js的prompt结果,分别调用成功或者失败的回调函数。注意成功或者失败的函数还是js。注意:这里的关键就是这个prompt,这是js和java的结合点!

        prompt在Android WebKit里面的实现对应WebChromeClient的onJsPrompt。咋样?是不是走到了DroidGap.java的onJsPrompt函数?是不是走到了Java里面?我们看一下代码。

        public boolean onJsPrompt(WebView view, String url, String message, String defaultValue, JsPromptResult result) {
     
            // Security check to make sure any requests are coming from the page initially
            // loaded in webview and not another loaded in an iframe.
            boolean reqOk = false;
            if (url.indexOf(this.ctx.baseUrl) == 0) { 
                reqOk = true;
            }    
     
            // Calling PluginManager.exec() to call a native service using 
            // prompt(this.stringify(args), "gap:"+this.stringify([service, action, callbackId, true]));
            if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(0, 4).equals("gap:")) {
                JSONArray array;
                try {
                    array = new JSONArray(defaultValue.substring(4));
                    String service = array.getString(0);
                    String action = array.getString(1);
                    String callbackId = array.getString(2);
                    boolean async = array.getBoolean(3);
                    String r = pluginManager.exec(service, action, callbackId, message, async);
                    result.confirm(r);
                } catch (JSONException e) { 
                    e.printStackTrace();
                }    
            }    
...
}

        最终会走到pluginManager.exec里面。pluginManager在 DroidGap 里面初始化,根据 plugins.xml 建立一个从名字(如camera)到对应类(如com.phonegap.CameraLauncher)的 HashMap。在 exec 的调用里面,搜索到camera,然后创建 Plugin (类似c++的虚拟构造函数?),调用对应exec,如 camera.exec。


        ok,phonegap的流程暂时就说到这里。

        由于这是我以前写的文章,而当时 phonegap 版本也就 1.1 ,所以我准备写一篇新文章分析最新的 phonegap。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值