根据IOS marcuswestin/WebViewJavascriptBridge 编写而来的JavascriptBridge。
相比同类库的优点:
- 和IOS marcuswestin/WebViewJavascriptBridge 一样的使用方法,可共用一套JS代码。
- 同时也在此之上做了加强,参考了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.)
repositories {
jcenter()
}
compile 'com.luffyjet:webviewjavascriptbridge:1.0'
See the app/
folder.
- 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
- 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();
}
});
- 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);
}
- 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/
目录下的示例代码。
marcuswestin/WebViewJavascriptBridge & lzyzsd/JsBridge & cordova-android
Copyright 2017 luffyjet.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.