WebViewJavaScriptBridge

Introduction: 根据 IOS marcuswestin/WebViewJavascriptBridge 编写而来的 JavascriptBridge。和 IOS marcuswestin/WebViewJavascriptBridge 一样的使用方法,共用一套 JS 代码。同时也在此之上做了加强,方便把各种不同的原生功能封装成独立的模块,类似 Cordova 的模块管理。
More: Author   ReportBugs   DemoAPK   
Tags:
JavaScriptBridge-JSBridge-jsbridege-

根据IOS marcuswestin/WebViewJavascriptBridge 编写而来的 JavascriptBridge。

相比同类库的优点:

  1. IOS marcuswestin/WebViewJavascriptBridge 一样的使用方法,可共用一套 JS 代码。
  2. 同时也在此之上做了加强,参考了 Cordova 源码的模块管理,方便把各种不同的原生功能封装成独立的模块并统一管理。具体请看下面的 模块管理功能一栏。

规定 JS 和 Java 之间用标准 JSON 格式字符串交互,JS 传给 Java 的数据会封装成 org.json.JSONObject。

(An Android bridge for sending messages between Java and JavaScript in WebViews. Based on IOS marcuswestin/WebViewJavascriptBridge.)

Gradle

repositories {
    jcenter()
}

compile 'com.luffyjet:webviewjavascriptbridge:1.0'

Examples

See the app/ folder.

Usage

1) Init WebViewJavaScriptBridge

WebSettings settings = webView.getSettings();
settings.setJavaScriptEnabled(true);//很关键
WebViewJavaScriptBridge mBridge = WebViewJavaScriptBridge.bridgeForWebView(this, webView);
mBridge.setWebViewDelegate(new MyWebViewClient());//设置 WebViewClient
webView.setWebChromeClient(new MyChromeClient());//设置 ChromeClient

2) Register a handler in Java, and call a JS handler:

 //注册一个 处理 js 端发来消息的 handler
mBridge.registerHandler("abs", new WebViewJavaScriptBridgeBase.WVJBHandler() {
    @Override
    public void handle(JSONObject data, WebViewJavaScriptBridgeBase.WVJBResponseCallback responseCallback) {
        Log.d(TAG, "from JS req: " + data.toString());
        responseCallback.callback(new JSResult("i like milk from native").toJson());
    }
});

mBridge.callHandler("NativeCallJS", model.toJSON(), new WebViewJavaScriptBridgeBase.WVJBResponseCallback() {
    @Override
    public void callback(String responseData) {
        Log.d(TAG, "JS responded:" + responseData);
        Toast.makeText(MainActivity.this, "JS responded:" + responseData , Toast.LENGTH_SHORT).show();
    }
});

3) Copy and paste setupWebViewJavascriptBridge into your JS:

function setupWebViewJavascriptBridge(callback) {
    if(window.WebViewJavascriptBridge) {
        return callback(WebViewJavascriptBridge);
    }
    if(window.WVJBCallbacks) {
        return window.WVJBCallbacks.push(callback);
    }
    window.WVJBCallbacks = [callback];
    var WVJBIframe = document.createElement('iframe');
    WVJBIframe.style.display = 'none';
    //这里最新 IOS 版是 https 的 scheme,真实环境下 需要判断 iOS 和 Android,做下区分。
    WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__';
    document.documentElement.appendChild(WVJBIframe);
    setTimeout(function() {
        document.documentElement.removeChild(WVJBIframe)
    }, 0);
}

5) Finally, call setupWebViewJavascriptBridge and then use the bridge to register handlers and call Java handlers:

setupWebViewJavascriptBridge(function(bridge) {
    /* Initialize your app here */

    bridge.registerHandler('NativeCallJS', function(data, responseCallback) {
        var responseData = {
            'Javascript Says': 'Right back atcha!'
        };

        log('Native call JS with ', data);
        responseCallback(responseData);
    });

    var doc = document;
    var readyEvent = doc.createEvent('Events');
    readyEvent.initEvent('WebViewJavascriptBridgeReady');
    readyEvent.bridge = WebViewJavascriptBridge;
    doc.dispatchEvent(readyEvent);
});

模块管理功能

可以和 Cordova 一样进行模块管理,同一种类型的消息(handler name 相同)都由一个模块处理。 模块类需要继承 RequestHandler ,包含 WebView 的 Activity 要实现 BridgeInterface 接口。插件类由 XML 文件进行配置,请在项目中新建 res/xml/wjbconfig.xml 文件。

<?xml version="1.0" encoding="utf-8"?>
<widget>
    <feature name="chooseImage">
        <param
            name="android-package"
            value="com.luffyjet.jsbridgeexample.handlers.ImageChooseHandler"/>
        <param
            name="onload"
            value="true"/>
    </feature>

    <feature name="deviceInfo">
        <param
            name="android-package"
            value="com.luffyjet.jsbridgeexample.handlers.DeviceInfoHandler"/>
        <param
            name="onload"
            value="true"/>
    </feature>

</widget>


//一个简单的选图模块示例
public class ImageChooseHandler extends RequestHandler {
    private static final String TAG = "ImageChooseHandler";
    private static final int REQUEST_CODE_IMAGES = 100;
    private WebViewJavaScriptBridgeBase.WVJBResponseCallback mResponseCallback;

    @Override
    public void handle(JSONObject data, WebViewJavaScriptBridgeBase.WVJBResponseCallback responseCallback) {

        mResponseCallback = responseCallback;
        ...
        mBridgeInterface.startActivityForResult(this, Intent.createChooser(i, "选取图片"), REQUEST_CODE_IMAGES);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_IMAGES) {
            try {
                ...
                mResponseCallback.callback(result.toJSON());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}


// 包含 webview 的 WebActivity
public class WebActivity extends AppCompatActivity implements BridgeInterface{

    RequestHandler mRequestHandler;

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (null != mRequestHandler) {
            RequestHandler callback = mRequestHandler;
            mRequestHandler = null;
            callback.onActivityResult(requestCode, resultCode, data);
            return;
        }

        //other code
    }

    @Override
    public void startActivityForResult(RequestHandler command, Intent intent, int requestCode) {
        setActivityResultCallback(command);
        startActivityForResult(intent, requestCode);
    }

    @Override
    public void setActivityResultCallback(RequestHandler plugin) {
        mRequestHandler = plugin;
    }

    @Override
    public Activity getActivity() {
        return this;
    }

    @Override
    public ExecutorService getThreadPool() {
        return Executors.newCachedThreadPool(new ThreadFactory() {
            @Override
            public Thread newThread(final Runnable r) {
                return  new Thread(new Runnable() {
                    @Override
                    public void run() {
                        android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
                        r.run();
                    }
                },"Test");
            }
        });
    }
}

一个功能模块对应一个 feature,feature name 就是 handle name。 onload 属性为 true 代表模块(插件)会在 webview 初始化时一同初始化,false 则是在需要该模块(插件)的时候通过反射加载。

具体使用方法请查看 app/ 目录下的示例代码。

Thanks

marcuswestin/WebViewJavascriptBridge & lzyzsd/JsBridge & cordova-android

License

See the LICENSE file for license rights and limitations.

Apps
About Me
GitHub: Trinea
Facebook: Dev Tools