Open libin1991 opened 6 years ago
预先定义好schema,如myapp://... 通过前端发送伪连接请求iframe.src
var iframe = document.createElement('iframe') iframe.style.display = 'none' iframe.src = schema var body = document.body body.appendChild(iframe) setTimeout(function () { body.removeChild(iframe) iframe = null })
可以看到,在某个按钮或者行为需要与原生端通信时创建一个iframe然后再移除,如果不移除iframe,则会在body里出现大量无用的iframe标签,这里简单说一下Native怎么去拦截这个伪链接请求。 在WebviewClient里override一个方法:
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(SCHEMA)) { ... return true; } }
实际项目中,肯定是要传递参数给Native接收的,可以对这样封装
for (key in data) { if (data.hasOwnProperty(key)) { schema += '&' + key + data[key] } }
这样就可以拼接出&key=value这种形式,Native端可以写一个方法获取到key和value的值然后去做相应的处理。
有的时候bridge事件处理完之后需要告诉前端一些消息回馈,那么前端需要封装一个callbackName传给Native端
var callbackName = '' if (typeof callback === 'string') { callbackName = callback } else { callbackName = action + Date.now() console.log('callbackName: ' + callbackName) window[callbackName] = callback } schema += 'callback=' + callbackName
特别注意:这里有一个Date.now(),作用是为了避免回调方法重复,且避免在ios手机上不断点击造成界面阻塞UI失去响应。
Native端执行回调写法:
public static void call(WebView webview, String js) { if (webview != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { webview.evaluateJavascript(js, null); } else { webview.loadUrl("javacript:" + js); } } }
jsbrige封装完毕后,可以测试,以分享为例:
window.bridge.share({ title: '...', content: '...' }, function (result) { if (result.success) { alert('分享成功') } })
只需载入brige.js即可
import './bridge' import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App) }).$mount('#app')
时下app分以下几种技术选型
通信原理
预先定义好schema,如myapp://... 通过前端发送伪连接请求iframe.src
var iframe = document.createElement('iframe') iframe.style.display = 'none' iframe.src = schema var body = document.body body.appendChild(iframe) setTimeout(function () { body.removeChild(iframe) iframe = null })
可以看到,在某个按钮或者行为需要与原生端通信时创建一个iframe然后再移除,如果不移除iframe,则会在body里出现大量无用的iframe标签,这里简单说一下Native怎么去拦截这个伪链接请求。 在WebviewClient里override一个方法:
@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith(SCHEMA)) { ... return true; } }
参数传递
实际项目中,肯定是要传递参数给Native接收的,可以对这样封装
for (key in data) { if (data.hasOwnProperty(key)) { schema += '&' + key + data[key] } }
这样就可以拼接出&key=value这种形式,Native端可以写一个方法获取到key和value的值然后去做相应的处理。
方法回调
有的时候bridge事件处理完之后需要告诉前端一些消息回馈,那么前端需要封装一个callbackName传给Native端
var callbackName = '' if (typeof callback === 'string') { callbackName = callback } else { callbackName = action + Date.now() console.log('callbackName: ' + callbackName) window[callbackName] = callback } schema += 'callback=' + callbackName
特别注意:这里有一个Date.now(),作用是为了避免回调方法重复,且避免在ios手机上不断点击造成界面阻塞UI失去响应。
Native端执行回调写法:
public static void call(WebView webview, String js) { if (webview != null) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { webview.evaluateJavascript(js, null); } else { webview.loadUrl("javacript:" + js); } } }
用法举例
jsbrige封装完毕后,可以测试,以分享为例:
window.bridge.share({ title: '...', content: '...' }, function (result) { if (result.success) { alert('分享成功') } })
基于vue的封装
只需载入brige.js即可
import './bridge' import Vue from 'vue' import App from './App.vue' Vue.config.productionTip = false new Vue({ render: h => h(App) }).$mount('#app')
总结