Cordova插件中JavaScript代碼與Java的交互細節介紹

                    小編:管理員 658閱讀 2022.09.13

                    在Cordova官網中有這么一張架構圖:大家看右下角藍色的矩形框"Custom Plugin"——自定義插件。意思就是如果您用Cordova打包Mobile應用時,發現您的移動應用里需要使用一些功能,這些功能用普通的JavaScript無法實現,而是需要調用移動平臺的一些原生API才能實現時,我們就需要自己實現自定義插件。這些插件通過在特定的移動平臺上采用原生開發實現,比如Android Studio中的Java開發,然后再通過JavaScript wrapper的方式暴露給您的Mobile應用。比如您是用Cordova在Android平臺上打包生成APK文件,那么您的Mobile代碼(JavaScript)里還是不會直接調用您用Java實現的Custom Plugin,而是調用Custom Plugin對應的JavaScript wrapper。

                    那么JavaScript wrapper本身是JavaScript代碼,它是怎么調用到Custom Plugin的Java實現的?本文就會介紹這個細節。

                    下圖是OData離線存儲插件(OData Offline Store)的JavaScript實現代碼的一部分。下圖第232行會調用設備的native API進行離線存儲的打開操作:

                    exec(win, error, 'OData', 'openOfflineStore', this, options ? options : {});

                    這個exec函數從哪里來?由Cordova框架實現,通過語句 require(‘cordova/exec’)返回。

                    那么當應用執行到JavaScript代碼:exec(win, error, 'OData', 'openOfflineStore', this, options ? options : {}); 的時候,程序流是如何從這個JavaScript的exec函數進入到Android平臺的原生API執行呢?

                    打開PackagedApp文件夾里的android子文件夾,有一個JavaScript文件:cordova.js:

                    里面能看到函數exec的定義和實現:

                    進而去查看androidExec函數的實現細節:

                    第938行:var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);

                    第943行的五個參數含義:

                    success, fail, service, action, args

                    • success & fail: JavaScript回調函數,當移動平臺上的Java原生API執行完畢后,這個JavaScript回調函數會被調用到。
                    • service: 待執行的Java Native API的Java實現類名稱。
                    • action: 待執行的Java Native API的Java實現類的方法名稱。
                    • args: JavaScript傳遞給Java native API的參數數組。

                    2. 在安卓平臺上,JavaScript調用Java的技術實現方式有兩種:定義在下圖JavaScript代碼中的jsToNativeModes對象中:PROMPT和JS_OBJECT。相對應的,Java調用JavaScript有三種模式:POLLING, LOAD_URL和ONLINE_EVENT:

                    看下面這段Java代碼,暴露了一個方法getSomeString給JavaScript端消費:

                    import android.app.Activity;
                    
                    import android.os.Bundle;
                    
                    import android.webkit.WebView;
                    
                    public class WebViewGUI extends Activity {
                    
                    	WebView mWebView;
                    
                    	public void onCreate(Bundle savedInstanceState) {
                    
                    		super.onCreate(savedInstanceState);
                    
                    		mWebView = new WebView(this);
                    
                    		mWebView.getSettings().setJavaScriptEnabled(true);
                    
                    		mWebView.addJavascriptInterface(new JavaScriptInterface(),
                    				"jsinterface");
                    
                    		mWebView.loadUrl("file:///android_asset/www/index.html");
                    
                    		setContentView(mWebView);
                    
                    	}
                    
                    	final class JavaScriptInterface {
                    
                    		JavaScriptInterface() {
                    		}
                    
                    		public String getSomeString() {
                    
                    			return "string";
                    
                    		}
                    
                    	}
                    
                    }
                    復制

                    在JavaScript代碼里消費上述Java代碼暴露的getSomeString方法:

                    復制

                    我們再回過頭來看看AndroidExec的實現:

                    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);

                    在AndroidExec的實現里, nativeApiProvider的get方法返回一個實例,然后執行exec方法。而881行代碼說明nativeApiProvider的實現位于文件夾cordova/android下面的nativeapiprovider.js里:

                    打開nativeapiprovider.js,在第21行的注釋里我們得到了重要信息: currentApi要么來自Java文件ExposedJsApi.java,要么來自PromptBasedNativeApi.java。

                    Java文件ExposedJsApi.java可以在這個文件夾內找到:

                    platform/android/CordovaLib/src/org/apache/cordova

                    ExposedJsApi實際就是個Java interface,上面聲明了一個exec方法:

                    JavaScript到Java的執行通過prompt調用完成:

                    Java類SystemExposedJsApi實現了這個interface,再將執行流轉交給類CordovaBridge的實例.

                    CordovaBridge再調用PluginManager:

                    PluginManager首先根據名字找到負責處理該請求的Java plugin的實現類,再調用該實現類的方法:

                    以OData離線存儲的實現類為例,我們在其實現代碼里能發現有大量的IF-ELSE分支,每個分支處理不同的離線存儲操作請求。

                    關聯標簽:
                    无码精品人妻一区二区三区软件