Cordova android架構詳解

來源:互聯網
上載者:User

標籤:

一、Cordova 核心java類說明

 

CordovaActivity:Cordova Activity入口,已實現PluginManager、WebView的相關初始化工作, 只需繼承CordovaActivity實現自己的業務需求。

PluginManager: 外掛程式管理器

ExposedJsApi :javascript調用Native, 通過外掛程式管理器PluginManager 根據service找到具體實作類別。

NativeToJsMessageQueue:Native調用javascript,主要包括三種方式:loadUrl 、 輪詢、反射WebViewCore執行js

 

二、 Cordova架構類圖

 

三、Cordova架構啟動

 

當實現了DroidGap或者CordovaInterface介面的Activity的onCreate方法中調用DroidGap的loadUrl方法即啟動了Cordova架構。

 

Cordova提供了一個Class(DroidGap extends CordovaActivity)和一個interface(CordovaInterface)來讓Android開發人員開發Cordova。

一般情況下實現DroidGap即可,因為DroidGap類已經做了很多準備工作,可以說DroidGap類是Cordova架構的一個重要部分;如果在必要的情況下實現CordovaInterface介面,那麼這個類中很多DroidGap的功能需要自己去實現。繼承了DroidGap或者CordovaInterface的Activity就是一個獨立的Cordova模組,獨立的Cordova模組指的是每個實現了DroidGap或者CordovaInterface介面的Activity都對應一套獨立的WebView,Plugin,PluginManager,沒有共用的。

 

在初始化完CordovaWebView後調用CordovaWebView.loadUrl()。此時完成Cordova的啟動。


1.Cordova關聯對象初始化

在執行個體化CordovaWebView的時候, CordovaWebView對象會去建立一個屬於當前CordovaWebView對象的外掛程式管理器PluginManager對象,一個訊息佇列NativeToJsMessageQueue對象,一個JavascriptInterface對象ExposedJsApi,並將ExposedJsApi對象添加到CordovaWebView中,JavascriptInterface名字為:_cordovaNative。


2. Cordova的JavascriptInterface
在建立ExposedJsApi時需要CordovaWebView的PluginManager對象和NativeToJsMessageQueue對象。因為所有的JS端與Android native代碼互動都是通過ExposedJsApi對象的exec方法。在exec方法中執行PluginManager的exec方法,PluginManager去尋找具體的Plugin並執行個體化然後再執行Plugin的execute方法,並根據同步標識判斷是同步返回給JS訊息還是非同步。由NativeToJsMessageQueue統一管理返回給JS的訊息。


3. 何時載入Plugin,如何載入
 Cordova在啟動每個Activity的時候都會將設定檔中的所有plugin載入到PluginManager。那麼是什麼時候將這些plugin載入到PluginManager的呢?在b中說了最後會調用CordovaWebView.loadUrl(),對,就在這個時候會去初始化PluginManager並載入plugin。PluginManager在載入plugin的時候並不是馬上執行個體化plugin對象,而是只是將plugin的Class名字儲存到一個hashmap中,用service名字作為key值。
當JS端通過JavascriptInterface介面的ExposedJsApi對象請求Android時,PluginManager會從hashmap中尋找到plugin,如果該plugin還未執行個體化,利用java反射機制執行個體化該plugin,並執行plugin的execute方法。


4.Cordova的資料返回

Cordova中通過exec()函數請求android外掛程式,資料的返回可同步也可以非同步於exec()函數的請求。在開發android外掛程式的時候可以重寫public boolean isSynch(String action)方法來決定是同步還是非同步。Cordova在android端使用了一個隊列(NativeToJsMessageQueue)來專門管理返回給JS的資料。

   
1)同步
   Cordova在執行完exec()後,android會馬上返回資料,但不一定就是該次請求的資料,可能是前面某次請求的資料;因為當exec()請求的外掛程式是允許同步返回資料的情況下,Cordova也是從NativeToJsMessageQueue隊列頭pop頭資料並返回。然後再根據callbackID反向尋找某個JS請求,並將資料返回給該請求的success函數。
   
2)非同步
   Cordova在執行完exec()後並不會同步得到一個返回資料。Cordova在執行exec()的同時啟動了一個XMLHttpRequest對象方式或者prompt()函數方式的迴圈函數來不停的去擷取NativeToJsMessageQueue隊列中的資料,並根據callbackID反向尋找到相對應的JS請求,並將該資料交給success函數。
   註:Cordova對本地的HTML檔案(file:// 開頭的URL)或者手機設定有代理的情況下使用XMLHttpRequest方式擷取返回資料,其他則使用prompt()函數方式擷取返回資料。

 

5、webView.sendJavascript 發送到js隊列,onNativeToJsMessageAvailable 負責執行js.

 

Native 調用 JS 執行方式有三種實現 LoadUrlBridgeMode、 OnlineEventsBridgeMode、PrivateApiBridgeMode

1、webView.sendJavascript 發送js方法到JS隊列

2、onJsPrompt 方法攔截,擷取調用方式

》》如果是gap_bridge_mode,則執行 appView.exposedJsApi.setNativeToJsBridgeMode(Integer.parseInt(message));
》》如果是gap_poll, 則執行 appView.exposedJsApi.retrieveJsMessages("1".equals(message));

3、調用setBridgeMode 方法調用onNativeToJsMessageAvailable 執行javascript調用

 

四、Native調用javascript 方式:NativeToJsMessageQueue


1、loadUrl javascript 調用方式

 

private class LoadUrlBridgeMode extends BridgeMode

if (url.startsWith("file://") || url.startsWith("javascript:") || Config.isUrlWhiteListed(url)) {

}


2、Navitive事件通知javascript輪詢擷取Navitive資料

 

private class OnlineEventsBridgeMode extends BridgeMode

 

3、通過Java反射擷取webview 的sendMessage 方法執行js, 支援 Android 3.2.4之上(包含)

 

---可以解決loadUrl 隱藏鍵盤的問題:當你的焦點在輸入,如果這通過loadUrl調用js,會導致鍵盤隱藏

private class PrivateApiBridgeMode extends BridgeMode

Field f = webViewClass.getDeclaredField("mProvider");
f.setAccessible(true);
webViewObject = f.get(webView);
webViewClass = webViewObject.getClass();

Field f = webViewClass.getDeclaredField("mWebViewCore");
f.setAccessible(true);
webViewCore = f.get(webViewObject);

if (webViewCore != null) {
sendMessageMethod = webViewCore.getClass().getDeclaredMethod("sendMessage", Message.class);
sendMessageMethod.setAccessible(true);
}

Message execJsMessage = Message.obtain(null, EXECUTE_JS, url);
sendMessageMethod.invoke(webViewCore, execJsMessage);

 


4、Native註冊javascript介面 _cordovaNative


boolean isHoneycomb = (SDK_INT >= Build.VERSION_CODES.HONEYCOMB && SDK_INT <= Build.VERSION_CODES.HONEYCOMB_MR2);
// Bug being that Java Strings do not get converted to JS strings automatically.This isn‘t hard to work-around on the JS side, but it‘s easier to just use the prompt bridge instead.
if (isHoneycomb || (SDK_INT < Build.VERSION_CODES.GINGERBREAD)) {
Log.i(TAG, "Disabled addJavascriptInterface() bridge since Android version is old.");
return; 
} else if (SDK_INT < Build.VERSION_CODES.HONEYCOMB && Build.MANUFACTURER.equals("unknown")) {
// addJavascriptInterface crashes on the 2.3 emulator.
Log.i(TAG, "Disabled addJavascriptInterface() bridge callback due to a bug on the 2.3 emulator");
return;
}
this.addJavascriptInterface(exposedJsApi, "_cordovaNative");

 

Cordova android架構詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.