PhoneGap 1.5版本 cordova.js 简析 2(转)

原文:http://peng-jiesi.iteye.com/blog/1485347

在了解了phonegap的最基本的定义和调用的方法之后,继续看看和手机的通信部分. 

在1.5之前的版本,phonegap在android的通信方式是通过js的prompt来实现的(具体其他文章有详细讲解),关键的部分由下面的几个函数组成 

Js代码  收藏代码
  1. PhoneGap.exec = function(success, fail, service, action, args)  
  2. PhoneGap.callbackSuccess = function(callbackId, args)  
  3. PhoneGap.callbackError = function(callbackId, args)  



而在1.5之后,采用的往往是这种格式 

Js代码  收藏代码
  1. var exec = require("cordova/exec");  
  2. exec(successCallback, errorCallback, "Accelerometer","getAcceleration", []);  




首先还是从exec函数入手,分析下phonegap的通信方式,在js端的exec定义中可以看到执行命令实际只是一个简单的js的prompt函数,将调用的方法、参数等信息以字符串的方式传入。 

Js代码  收藏代码
  1. var r = prompt(JSON.stringify(args), "gap:"+ JSON.stringify([service,action,callbackId, true]));  



在android端通过,下面的代码,劫持了字符串信息,并且通过分析最终调用到具体的服务类. 

Java代码  收藏代码
  1. //所在函数 org.apache.cordova.CordovaChromeClient.onJsPrompt  
  2. if (reqOk && defaultValue != null && defaultValue.length() > 3 && defaultValue.substring(04).equals("gap:")) {  
  3.       JSONArray array;  
  4.       try {  
  5.           array = new JSONArray(defaultValue.substring(4));  
  6.           String service = array.getString(0);  
  7.           String action = array.getString(1);  
  8.           String callbackId = array.getString(2);  
  9.           boolean async = array.getBoolean(3);  
  10.           String r = ctx.pluginManager.exec(service, action, callbackId, message, async);  
  11.             result.confirm(r);  
  12.         } catch (JSONException e) {  
  13.             e.printStackTrace();  
  14.         }  
  15.     }  


对普通的插件而言存在两种结果 
1. 异步调用,在非异常的情况下都返回"" 
2. 同步调用,会将结果作为json字符串传送回js端 

取得结果后js端会直接放弃所有的""结果,然后分析同步结果 

Js代码  收藏代码
  1. // line 757 成功返回处理  
  2. if (v.status === cordova.callbackStatus.OK) {  
  3.     if (success) {  
  4.         try {  
  5.             success(v.message);  
  6.         } catch (e) {  
  7.             console.log("Error in success callback: "  
  8.                     + callbackId + " = " + e);  
  9.         }  
  10.         if (!v.keepCallback) {  
  11.             delete cordova.callbacks[callbackId];  
  12.         }  
  13.     }  
  14.     return v.message;  
  15. }  
  16.   
  17. // line 788 失败处理  
  18. else {     
  19.     if (fail) {  
  20.         try {  
  21.             fail(v.message);  
  22.         } catch (e1) {  
  23.             console.log("Error in error callback: "  
  24.                     + callbackId + " = " + e1);  
  25.         }  
  26.         if (!v.keepCallback) {  
  27.             delete cordova.callbacks[callbackId];  
  28.         }  
  29.     }  
  30.     return null;  
  31. }  


对于同步的请求,在返回结果后会直接调用插件定义的回调函数进行处理. 

而异步的请求,则需要通过android的处理,触发页面的页面的事件,然后相应.在最开始可以看到每个请求都有唯一的服务id,并且通过回调事件缓存池将方法缓存. 

Js代码  收藏代码
  1. var callbackId = service + cordova.callbackId++;  
  2.         if (success || fail) {  
  3.             cordova.callbacks[callbackId] = {  
  4.                 success : success,  
  5.                 fail : fail  
  6.             };  
  7.         }  


当android的任务完成以后,会通过Plugin类的success函数返回成功结果,而这个操作实际就是向webview发起一个js请求. 

Java代码  收藏代码
  1. //line 157   org.apache.cordova.api.Plugin    
  2.     public void success(PluginResult pluginResult, String callbackId) {  
  3.         this.ctx.sendJavascript(pluginResult.toSuccessCallbackString(callbackId));  
  4.     }  
  5.   
  6. //line 86 org.apache.cordova.api.PluginResult  
  7.     public String toSuccessCallbackString(String callbackId) {  
  8.         return "require('cordova').callbackSuccess('"+callbackId+"',"+this.getJSONString()+");";  
  9.     }  


然后通过js端的回调服务callbackSuccess来实现异步结果返回. 

但是任然有部分的代码中的返回是通过特定的函数来实现,如地理位置中的返回,就仍然采用了原有的模式(因为大部分设备使用的是浏览器自带的定位,所以感觉不到问题),所以如果不做相应修改就会产生错误. 

Java代码  收藏代码
    1. //  line 81   org.apache.cordova.GeoListener.success  
    2.     void success(Location loc) {  
    3.           
    4.         String params = loc.getLatitude() + "," + loc.getLongitude() + ", " + loc.getAltitude() +   
    5.                 "," + loc.getAccuracy() + "," + loc.getBearing() +  
    6.                 "," + loc.getSpeed() + "," + loc.getTime();  
    7.           
    8.         if (id == "global") {  
    9.             this.stop();  
    10.         }  
    11.         this.broker.sendJavascript("navigator._geo.success('" + id + "'," +  params + ");");  
    12.     }  

posted on 2012-08-15 14:49  亭子  阅读(338)  评论(0编辑  收藏  举报

导航