android phonegap js <-> java交互原理

项目里 用了一下 phonegap来 包装我们的client java jar, 已提供js接口. 其中 从js到java 的调用还是颇有点神秘感. 就顺便看了看phonegap的实现. 

cordova5.1.1:

https://github.com/apache/cordova-android/archive/5.1.1.zip

 

在android上, phonegap使用了WebView. 

http://developer.android.com/guide/webapps/webview.html

WebView提供addJavascriptInterface来 把一个Java object映射为JS object, 官网上有如下示例:

 class JsObject {
    @JavascriptInterface
    public String toString() { return "injectedObject"; }
 }
 webView.addJavascriptInterface(new JsObject(), "injectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");

 

在phonegap-android中, 

SystemWebViewEngine.java, init() -> exposeJsInterface():

SystemExposedJsApi exposedJsApi = new SystemExposedJsApi(bridge);
webView.addJavascriptInterface(exposedJsApi, "_cordovaNative");

cordova-js-src/exec.js: 

function androidExec(success, fail, service, action, args) {
    // ...
    var msgs = nativeApiProvider.get().exec(bridgeSecret, service, action, callbackId, argsJson);

cordova-js-src/android/nativeapiprovider.js:

var nativeApi = this._cordovaNative || require('cordova/android/promptbasednativeapi');
var currentApi = nativeApi;

module.exports = {
    get: function() { return currentApi; }, // ...

JS端 可以同步 从 cordova.exec()直接返回结果; 也可以异步polling的方式, 调用 _cordovaNative对象的retrieveJsMessages方法取结果. 

注: js端也可以不通过 addJavascriptInterface, 而通过 promt() -> 触发 WebView中WebChromeClient的onJsPrompt来做. 这是android4.1之前的做法. 算一个hack.

 

回到java端,  上面已经 提供了 名为"_cordovaNative"的 js对象映射到 一个 java CordovaBridge对象. 

CordovaBridge.java, jsExec() 对应了 cordova.exec(). 其中调用了 PluginManager.exec():

    public void exec(final String service, final String action, final String callbackId, final String rawArgs) {
        // 根据service 做java 反射 生成对应的 CordovaPlugin对象
        // 调用此对象的 exec()

返回结果 放入一个 NativeToJsMessageQueue中, js端通过同步或异步方式 取回结果. NativeToJsMessageQueue中通过synchronized (this) 来同步 进出queue的操作.

 

posted @ 2016-03-01 15:05  brayden  阅读(608)  评论(0编辑  收藏  举报