现在开发移动端应用,方案有很多, 比如native(IOS和Android)、 hybrid和react native等。其中hybrid、react native等方案对前端很友好,毕竟是用我们熟悉的JavaScript开发,但JavaScript无法直接调用native本身提供的能力,比如获取相册信息。所以就需要通过一种方式将native能力提供给JavaScript,同时native也可能需要调用JavaScript的一些功能,而JSBridge就是JavaScript和native之间的桥梁,提供两者相互调用的能力。
依然有很多坑
使用方式:
一、添加依赖(或者导入aar)
implementation 'com.github.lzyzsd:jsbridge:1.0.4'
二、使用 BridgeWebView对象,内部是对webview的封装直接使用就可以
android:id="@+id/webView" android:layout_width="match_parent" android:layout_height="match_parent" /> 三、声明bridgeWebView实例 初始化 private BridgeWebView bridgeWebView; bridgeWebView = findViewById(R.id.webView); 四、初始化 - 并且加载url bridgeWebView.getSettings().setAllowFileAccess(true); bridgeWebView.getSettings().setAppCacheEnabled(true); bridgeWebView.getSettings().setDatabaseEnabled(true); // 允许网页定位 bridgeWebView.getSettings().setGeolocationEnabled(true); // 允许网页弹对话框 bridgeWebView.getSettings().setJavaScriptCanOpenWindowsAutomatically(true); // 加快网页加载完成的速度,等页面完成再加载图片 bridgeWebView.getSettings().setLoadsImagesAutomatically(true); // 开启 localStorage bridgeWebView.getSettings().setDomStorageEnabled(true); // 设置支持javascript// 本地 DOM 存储(解决加载某些网页出现白板现象) bridgeWebView.getSettings().setJavaScriptEnabled(true); // 进行缩放 bridgeWebView.getSettings().setBuiltInZoomControls(true); // 设置UserAgent bridgeWebView.getSettings().setUserAgentString(bridgeWebView.getSettings().getUserAgentString() + "app"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // 解决 Android 5.0 上 WebView 默认不允许加载 Http 与 Https 混合内容 bridgeWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } bridgeWebView.setWebViewClient(new MyWebViewClient(bridgeWebView)); bridgeWebView.setWebChromeClient(new WebChromeClient()); bridgeWebView.loadUrl("https://xxx.xxx.xxx:8080/h5/"); 五、MyWebViewClient类 public class MyWebViewClient extends BridgeWebViewClient { public MyWebViewClient(BridgeWebView webView) { super(webView); } @SuppressLint("WebViewClientOnReceivedSslError") @Override public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) { //super.onReceivedSslError(view, handler, error); // 如何处理应用中的 WebView SSL 错误处理程序提醒 handler.proceed(); } /** * 同名 API 兼容 */ @TargetApi(Build.VERSION_CODES.M) @Override public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) { if (request.isForMainFrame()) { onReceivedError(view, error.getErrorCode(), error.getDescription().toString(), request.getUrl().toString()); } } /** * 加载错误 */ @Override public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { super.onReceivedError(view, errorCode, description, failingUrl); } /** * 同名 API 兼容 */ @TargetApi(Build.VERSION_CODES.N) @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { return shouldOverrideUrlLoading(view, request.getUrl().toString()); } /** * 跳转到其他链接 */ // @Override // public boolean shouldOverrideUrlLoading(WebView view, String url) { // Log.i("WebView shouldOverrideUrlLoading:%s", url); // String scheme = Uri.parse(url).getScheme(); // if (scheme == null) { // return false; // } // switch (scheme) { // // 如果这是跳链接操作 // case "http": // case "https": // view.loadUrl(url); // break; // // 如果这是打电话操作 // case "tel": dialing(view, url); // break; // default: // break; // } // return true; // } } 六、初始化Android接收Hanlers // 设置默认接收函数 并返回数据 bridgeWebView.setDefaultHandler(new BridgeHandler() { @Override public void handler(String data, CallBackFunction function) { function.onCallBack("返回给H5的数据"); } }); 七、H5(uniappVue)端代码 在utils目录下新建js,名字叫 jsBridge /** * 使用 JSBridge 总结: * 1、跟 IOS 交互的时候,只需要且必须注册 iosFuntion 方法即可, * 不能在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则 IOS 无法调用到 H5 的注册函数; * 2、与安卓进行交互的时候 * ①、使用 iosFuntion,就可以实现 H5 调用 安卓的注册函数,但是安卓无法调用 H5 的注册函数, * 并且 H5 调用安卓成功后的回调函数也无法执行 * ②、使用 andoirFunction 并且要在 setupWebViewJavascriptBridge 中执行 bridge.init 方法, * 安卓才可以正常调用 H5 的回调函数,并且 H5 调用安卓成功后的回调函数也可以正常执行了 */ const u = navigator.userAgent; // Android终端 const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1; // IOS 终端 const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); /** * Android 与安卓交互时: * 1、不调用这个函数安卓无法调用 H5 注册的事件函数; * 2、但是 H5 可以正常调用安卓注册的事件函数; * 3、还必须在 setupWebViewJavascriptBridge 中执行 bridge.init 方法,否则: * ①、安卓依然无法调用 H5 注册的事件函数 * ①、H5 正常调用安卓事件函数后的回调函数无法正常执行 * * @param {*} callback */ const andoirFunction = (callback) => { if (window.WebViewJavascriptBridge) { callback(window.WebViewJavascriptBridge); } else { document.addEventListener('WebViewJavascriptBridgeReady', function () { callback(window.WebViewJavascriptBridge); }, false) } } /** * IOS 与 IOS 交互时,使用这个函数即可,别的操作都不需要执行 * @param {*} callback */ const iosFuntion = (callback) => { if (window.WebViewJavascriptBridge) { return callback(window.WebViewJavascriptBridge) } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback) } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function(){ document.documentElement.removeChild(WVJBIframe); }, 0); } /** * 注册 setupWebViewJavascriptBridge 方法 * 之所以不将上面两个方法融合成一个方法,是因为放在一起,那么就只有 iosFuntion 中相关的方法体生效 */ window.setupWebViewJavascriptBridge = isAndroid ? andoirFunction : iosFuntion; /** * 这里如果不做判断是不是安卓,而是直接就执行下面的方法,就会导致 * 1、IOS 无法调用 H5 这边注册的事件函数 * 2、H5 可以正常调用 IOS 这边的事件函数,并且 H5 的回调函数可以正常执行 */ if (isAndroid) { /** * 与安卓交互时,不调用这个函数会导致: * 1、H5 可以正常调用 安卓这边的事件函数,但是无法再调用到 H5 的回调函数 * * 前提 setupWebViewJavascriptBridge 这个函数使用的是 andoirFunction 这个,否则还是会导致上面 1 的现象出现 */ window.setupWebViewJavascriptBridge(function (bridge) { // 注册 H5 界面的默认接收函数(与安卓交互时,不注册这个事件无法接收回调函数) bridge.init(function (msg, responseCallback) { message.success(msg); responseCallback("JS 返回给原生的消息内容"); }) }) }; 八、main.js 加入 import jsBridge from './utils/jsBridge' Vue.prototype.$jsBridge = jsBridge 九、H5页面调用 methods: { /** * jsbridge监听native传递数据 */ aaa() { // window.setupWebViewJavascriptBridge(bridge => { // bridge.callHandler('changeUser', 'H5修改appUser值', () => { // app.globalData.toast('修改好了') // setUser('bbb'); // }); // }) window.setupWebViewJavascriptBridge(bridge => { bridge.send("JS 测试传递给原生的消息", (data) => { app.globalData.toast(data) console.log(data) }) }) }, } 十、Android 发送数据给 H5页面 callHandler mWebView.callHandler("getMessage", "我是android的数据666", new CallBackFunction() { @Override public void onCallBack(String data) { ToastUtils.showShort("我是回掉"+data); } }); 参考链接
发表评论