phonegap

phonegap 框架詳解

 轉自:http://www.cnblogs.com/hubcarl/p/4216844.html

首先, 來看一下phonegap 初始化流程以及Native 與 JS 交互流程圖。javascript

 

說明:socket server模式下, phonegap.js 源碼實現的採用1 毫秒執行一次XHR請求,  當Native  JS 隊列裏面有JS語句數據時,纔是真正的1毫秒調用一下;  當沒有數據, scoket server 會阻塞10毫秒, 也就是XHR 要等10秒鐘才能收到結果,並進行下一次的輪詢。html

 

一、Activity繼承 DroidGap (extends PhonegapActivity)java

從phonegap.xml 中加載白名單配置 和 log配置android


二、loadUrl (每一個Activity 都初始化一次)web

》》初始化webview
》》初始化callbackServer
》》插件管理器PluginManager 編程

 

三、加載插件配置:緩存

》》讀取 plugins.xml 配置,用map存儲起來。app

1
2
3
4
5
6
7
< plugins >
< plugin  name="Camera" value="com.phonegap.CameraLauncher"/>
< plugin  name="Contacts" value="com.phonegap.ContactManager"/>
< plugin  name="Crypto" value="com.phonegap.CryptoHandler"/>
< plugin  name="File" value="com.phonegap.FileUtils"/>
< plugin  name="Network Status" value="com.phonegap.NetworkManager"/>
</ plugins >

說明:
name 是別名,javascript調用時經過別名來調用。
value:java具體實現類框架

web頁面調用(例如查找聯想人)
PhoneGap.exec(successCB, errorCB, "Contacts", "search", [fields, options]);socket


四、插件實現

》》編程java類,繼承Plugin類(Plugin 實現了IPlugin接口),並實現execute方法。
例如聯繫人管理插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public  class  ContactManager  extends  Plugin{
     /**
      * action : 用來指定一個具體動做  search 表示搜索聯繫人
      * args: 方法參數
      * callbackId:js與java指定一個標識,
      */
     public  PluginResult execute(String action, JSONArray args, String callbackId) {
         try  {
             if  (action.equals( "search" )) {
                 JSONArray res = contactAccessor.search(args.getJSONArray( 0 ), args.optJSONObject( 1 ));
                 return  new  PluginResult(status, res,  "navigator.contacts.cast" );
             }
             else  if  (action.equals( "save" )) {
                 String id = contactAccessor.save(args.getJSONObject( 0 ));
                 if  (id !=  null ) {
                                   JSONObject res = contactAccessor.getContactById(id);
                                       if  (res !=  null ) {
                                          return  new  PluginResult(status, res);
                                      }
                 }
             }
             else  if  (action.equals( "remove" )) {
                 if  (contactAccessor.remove(args.getString( 0 ))) {
                     return  new  PluginResult(status, result);                   
                 }
             }
             // If we get to this point an error has occurred
                 JSONObject r =  new  JSONObject();
                     r.put( "code" , UNKNOWN_ERROR);
                             return  new  PluginResult(PluginResult.Status.ERROR, r);
         catch  (JSONException e) {
             Log.e(LOG_TAG, e.getMessage(), e);
             return  new  PluginResult(PluginResult.Status.JSON_EXCEPTION);
         }
     }
}

  


五、polling和server初始化


android DroidGap 初始化時,若是loadUrl的url不是以file:// 開頭時,polling = true, 不然是socket server方式

代碼見CallbackServer.java 類init方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public  void  init(String url) {
     //System.out.println("CallbackServer.start("+url+")");
     // Determine if XHR or polling is to be used
     if  ((url !=  null ) && !url.startsWith( "file://" )) {
        this .usePolling =  true ;
        this .stopServer();
     }
     else  if  (android.net.Proxy.getDefaultHost() !=  null ) {
         this .usePolling =  true ;
         this .stopServer();
     }
     else  {
         this .usePolling =  false ;
         this .startServer();
     }
}

  


六、phonegap.js  關鍵代碼說明

 

phonegap.js在啓動時,首先會經過prompt("usePolling", "gap_callbackServer:")獲取調用方式: XHR 輪詢 OR prompt 輪詢,  若是是XHR的話, 會啓動XHR調用獲取http server端口 和token。


方法PhoneGap.Channel.join 啓動 js server 或者polling調用 

UsePolling 默認爲false。 經過var polling = prompt("usePolling", "gap_callbackServer:") 獲取調用方式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
PhoneGap.Channel.join( function  () {
 
     // Start listening for XHR callbacks
     setTimeout( function  () {
       if  (PhoneGap.UsePolling) {
         PhoneGap.JSCallbackPolling();
       }
       else  {
         console.log( 'PhoneGap.Channel.join>>>>>>>>>>>>>>>>>>>>>>>>>' );<br>       <span style= "color: #ff6600;" //phonegap js 首次啓動獲取js調用Native方式</span>
         var  polling = prompt( "usePolling" "gap_callbackServer:" );
         PhoneGap.UsePolling = polling;
         if  (polling ==  "true" ) {
           PhoneGap.UsePolling =  true ;
           <span style= "color: #ff6600;" >PhoneGap.JSCallbackPolling();</span>
         }
         else  {
           PhoneGap.UsePolling =  false ;
          <span style= "color: #ff6600;" > PhoneGap.JSCallback();</span>
         }
       }
     }, 1);
}

  

XHR輪詢:PhoneGap.JSCallback方法

經過XHR 與java端 socket進行通訊,每一毫秒執行一次JSCallback,從android socket獲取javascript執行結果代碼,最後經過eval動態執行javascript

XHR調用, 經過prompt 獲取socket端口 和 token(uuid)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if  (PhoneGap.JSCallbackPort ===  null ) {
    PhoneGap.JSCallbackPort = <span style= "color: #ff6600;" >prompt( "getPort" "gap_callbackServer:" );</span>
    console.log( 'PhoneGap.JSCallback getPort>>>>>>>>>>>>>>>>>>>>>>>>>:'  + PhoneGap.JSCallbackPort);
}
if  (PhoneGap.JSCallbackToken ===  null ) {
  PhoneGap.JSCallbackToken =<span style= "color: #ff6600;" > prompt( "getToken" "gap_callbackServer:" );</span>
  console.log( 'PhoneGap.JSCallback getToken>>>>>>>>>>>>>>>>>>>>>>>>>:'  + PhoneGap.JSCallbackToken);
}
xmlhttp.open( "GET" "http://127.0.0.1:"  + PhoneGap.JSCallbackPort +  "/"  + PhoneGap.JSCallbackToken,  true );
xmlhttp.send();
 
XHR返回結果代碼片斷
var  msg = decodeURIComponent(xmlhttp.responseText);
setTimeout( function  () {
try  {
     var  t = eval(msg);
}
catch  (e) {
   // If we're getting an error here, seeing the message will help in debugging
   console.log( "JSCallback: Message from Server: "  + msg);
   console.log( "JSCallback Error: "  + e);
}
  }, 1);
  <span style= "color: #ff6600;" >setTimeout(PhoneGap.JSCallback, 1);</span><br>}

  

prompt輪詢: PhoneGap.JSCallbackPolling方法

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<span style= "color: #ff6600;" >PhoneGap.JSCallbackPolling</span> =  function  () {
 
     // Exit if shutting down app
     if  (PhoneGap.shuttingDown) {
       return ;
     }
 
     // If polling flag was changed, stop using polling from now on
     if  (!PhoneGap.UsePolling) {
       PhoneGap.JSCallback();
       return ;
     }
 
     var  msg = prompt( "" "gap_poll:" );
     if  (msg) {
       setTimeout( function  () {
         try  {
           var  t = eval( ""  + msg);
         }
         catch  (e) {
           console.log( "JSCallbackPolling: Message from Server: "  + msg);
           console.log( "JSCallbackPolling Error: "  + e);
         }
       }, 1);
       <span style= "color: #ff6600;" >setTimeout(PhoneGap.JSCallbackPolling, 1);</span>
     }
     else  {
       setTimeout(PhoneGap.JSCallbackPolling, PhoneGap.JSCallbackPollingPeriod);
     }
   };

  

 七、總結

  一、phonegap android 插件管理器PluginManager初始化時, 是每一個Activity都要初始化一次, 數據都緩存一次, 致使同一份數據緩存屢次。-- 暫不清楚爲啥這樣實現? 難道是phonegap 框架是爲單webview 實現的,若是有知道緣由的請告知一下。

     二、同第1點同樣, Socket Server 每一個Activity都會初始化一下, 若是loadUrl 的url類型不一樣,會不會致使scoket server狀體錯亂, 待驗證!

     三、phonegap 採用 prompt 和 XHR 輪詢機制,一是會致使手機耗電狀況嚴重, 二是瞭解到prompt 調用是會阻塞js執行的, 這樣致使影響到頁面加載速度。

 

  phonegap 已經更名cordova, 在最新版本cordova 框架裏面已經去掉了socket server模式, 詳細請查看:http://www.cnblogs.com/hubcarl/p/4202784.html

相關文章
相關標籤/搜索