首先, 來看一下phonegap 初始化流程以及Native 與 JS 交互流程圖。
說明:socket server模式下, phonegap.js 源碼實現的採用1 毫秒執行一次XHR請求, 當Native JS 隊列裏面有JS語句數據時,纔是真正的1毫秒調用一下; 當沒有數據, scoket server 會阻塞10毫秒, 也就是XHR 要等10秒鐘才能收到結果,並進行下一次的輪詢。
1、Activity繼承 DroidGap (extends PhonegapActivity)
從phonegap.xml 中加載白名單配置 和 log配置
2、loadUrl (每個Activity 都初始化一次)
》》初始化webview
》》初始化callbackServer
》》插件管理器PluginManager
3、加載插件配置:
》》讀取 plugins.xml 配置,用map存儲起來。
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]);
4、插件實現
》》編程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); } } } |
5、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 this .usePolling
= true ; this .stopServer(); } else if (android.net.Proxy.getDefaultHost()
!= null )
{ this .usePolling
= true ; this .stopServer(); } else { this .usePolling
= false ; this .startServer(); } } |
6、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); } }; |
7、總結
1、phonegap android 插件管理器PluginManager初始化時, 是每個Activity都要初始化一次, 數據都緩存一次, 導致同一份數據緩存多次。-- 暫不清楚爲啥這樣實現? 難道是phonegap 框架是爲單webview 實現的,如果有知道原因的請告知一下。
2、同第1點一樣, Socket Server 每個Activity都會初始化一下, 如果loadUrl 的url類型不同,會不會導致scoket server狀體錯亂, 待驗證!
3、phonegap 採用 prompt 和 XHR 輪詢機制,一是會導致手機耗電情況嚴重, 二是瞭解到prompt 調用是會阻塞js執行的, 這樣導致影響到頁面加載速度。
phonegap 已經改名cordova, 在最新版本cordova 框架裏面已經去掉了socket server模式, 詳細請查看:http://www.cnblogs.com/hubcarl/p/4202784.html