Cordova原始碼深入分析-第五講
阿新 • • 發佈:2019-01-08
上一講將主體流程和框架都已經介紹完了,
再次檢視整個程式碼的時候,發現我還是有一些細節並沒有列舉出來,
例如之前只是介紹了addJavaScript一種方式實現通訊,實際上還有另一種通訊方式就是prompt方式,本講再次介紹一下。
prompt有幾個優勢:
1.可以避免掉android 4.2以下,js安全問題
2.可以實現同步呼叫,直接返回值
下面開始分析程式碼邏輯:
重複的位置,不再累述。直接來到cordova.js中
define("cordova/android/nativeapiprovider", function(require, exports, module) { var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');//這裡其實如果沒有定義_cordovaNative就會走prompt var currentApi = nativeApi; module.exports = { get: function() { return currentApi; }, setPreferPrompt: function(value) { currentApi = value ? require('cordova/android/promptbasednativeapi') : nativeApi; }, // Used only by tests. set: function(value) { currentApi = value; } }; });
而在使用prompt方式的時候,方法都是一樣的。
define("cordova/android/promptbasednativeapi", function(require, exports, module) { module.exports = { exec: function(bridgeSecret, service, action, callbackId, argsJson) { return prompt(argsJson, 'gap:'+JSON.stringify([bridgeSecret, service, action, callbackId]));//直接進入java端,程式碼片段1 }, setNativeToJsBridgeMode: function(bridgeSecret, value) { prompt(value, 'gap_bridge_mode:' + bridgeSecret); }, retrieveJsMessages: function(bridgeSecret, fromOnlineEvent) { return prompt(+fromOnlineEvent, 'gap_poll:' + bridgeSecret); } }; });
程式碼段1:SystemWebChromeClient.java
@Override public boolean onJsPrompt(WebView view, String origin, String message, String defaultValue, final JsPromptResult result) { // Unlike the @JavascriptInterface bridge, this method is always called on the UI thread. String handledRet = parentEngine.bridge.promptOnJsPrompt(origin, message, defaultValue);//程式碼片段2 if (handledRet != null) { result.confirm(handledRet); } else { dialogsHelper.showPrompt(message, defaultValue, new CordovaDialogsHelper.Result() { @Override public void gotResult(boolean success, String value) { if (success) { result.confirm(value); } else { result.cancel(); } } }); } return true; }
程式碼片段2:CordovaBridge.java
public String promptOnJsPrompt(String origin, String message, String defaultValue) {
if (defaultValue != null && defaultValue.length() > 3 && defaultValue.startsWith("gap:")) {
JSONArray array;
try {
array = new JSONArray(defaultValue.substring(4));
int bridgeSecret = array.getInt(0);
String service = array.getString(1);
String action = array.getString(2);
String callbackId = array.getString(3);
String r = jsExec(bridgeSecret, service, action, callbackId, message);//執行與之前介紹的邏輯一樣的流程中了
return r == null ? "" : r;
} catch (JSONException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}
// Sets the native->JS bridge mode.
else if (defaultValue != null && defaultValue.startsWith("gap_bridge_mode:")) {
try {
int bridgeSecret = Integer.parseInt(defaultValue.substring(16));
jsSetNativeToJsBridgeMode(bridgeSecret, Integer.parseInt(message));
} catch (NumberFormatException e){
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}
// Polling for JavaScript messages
else if (defaultValue != null && defaultValue.startsWith("gap_poll:")) {
int bridgeSecret = Integer.parseInt(defaultValue.substring(9));
try {
String r = jsRetrieveJsMessages(bridgeSecret, "1".equals(message));
return r == null ? "" : r;
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return "";
}
else if (defaultValue != null && defaultValue.startsWith("gap_init:")) {
// Protect against random iframes being able to talk through the bridge.
// Trust only pages which the app would have been allowed to navigate to anyway.
if (pluginManager.shouldAllowBridgeAccess(origin)) {
// Enable the bridge
int bridgeMode = Integer.parseInt(defaultValue.substring(9));
jsMessageQueue.setBridgeMode(bridgeMode);
// Tell JS the bridge secret.
int secret = generateBridgeSecret();
return ""+secret;
} else {
LOG.e(LOG_TAG, "gap_init called from restricted origin: " + origin);
}
return "";
}
return null;
}
到這裡整個流程又銜接上了,就不在廢話了