关注公众号 前端界,回复“加群”
加入我们一起学习,天天进步
面试的时候经常会问到手机端应用 App 怎么跟 h5 通信的问题,什么是 JSBridge?说实话,之前没有认真研究过,最近入职了新公司正好是 App 和 h5 混合开发模式,周末有时间,研究了一番。
App 和 H5 通信
App 和 H5 通信和 JSBridge 其实是两个概念,不要混淆。App 和 H5 通信有多种,而 JSBridge 只是其中能实现 App 和 H5 通信的一种方式。
常见的 App 和 H5 通信方式:
URL Scheme
URL Scheme 是一种自定义的URL协议,允许 H5 页面通过链接到特定的格式触发 APP 内部的操作。例如,当H5页面中的链接被点击时,可以利用URL Scheme 唤起 APP 并执行预定义的动作,或者传递参数给 APP。这种方式适用于简单的跳转和数据传递,但功能有限,且用户体验可能因需要先打开系统浏览器再跳转至 APP 而受到影响。developer.baidu.com/article/det…[1]postMessage
是HTML5引入的一个API,它允许来自不同源的脚本在浏览器环境中进行异步通信。在原生APP嵌入H5页面的场景下,可以利用postMessage
来实现两者间的双向通信。juejin.cn/post/729442…[2]APP与H5之间可以通过WebSocket进行通信。WebSocket是一种在单个TCP连接上进行全双工通信的协议,它提供了浏览器和服务器之间的低延迟、持久化的连接,非常适合实时数据传输场景。 JSBridge:JSBridge 的核心目的就是搭建一个桥梁,让运行在 WebView 中的 JavaScript 代码能够与宿主的原生应用程序(比如 Android 或 iOS 应用)互相通讯。
本文的重点在于介绍第4种 App 和 H5 的通信方式即 JSBridge。为了彻底搞懂大家说的 JSBridge 是什么,我在网上翻阅了很多博客,然后自己摸摸索索,把实现 JSBridge 的代码写了一遍,这样直接看代码解释起来会更清晰。
Android 开发环境配置
以 Android 为例,来看下 JSBridge 的实现,先配置 Android 的开发环境:
Java环境配置: blog.csdn.net/u014454538/…[3]
android: blog.csdn.net/a910247/art…[4]
配置腾讯云 gradle 镜像,解决下载Gradle文件慢问题:www.cnblogs.com/tc310/p/180…[5]
传统做法
传统做法利用的是 Android 系统提供的android.webkit.WebView 初始化一个 WebView,通过 addJavascriptInterface
方法绑定方法到JavaScript环境,实现JavaScript与Android原生代码的交互,这是实现 JSBridge 机制的基础。
路径:MyApplication2\app\src\main\AndroidManifest.xml
<!-- 添加网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
android 端关键代码:通过 addJavascriptInterface
方法在 window
上添加 JsBridge
对象,并将 sendDataToApp
方法绑定到 JsBridge
对象上,这样 h5 就可以通过 window
上JsBridge
对象的 sendDataToApp
跟 App 发送数据了。
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview_layout);
webView = findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
// window 上添加 JsBridge 对象
webView.addJavascriptInterface(new JsBridge(), "JsBridge");
webView.loadUrl("http://10.168.2.149:5500/h5-test.html");
}
public class JsBridge {
// 添加 sendDataToApp 到 window.JsBridge 上
@JavascriptInterface
public void sendDataToApp(String value) {
// 获取数据
sendResponseToH5(value);
}
// 执行 JS 的方法
public void sendResponseToH5(final String data) {
runOnUiThread(() -> {
webView.evaluateJavascript("javascript:window.JsBridge.receiveDataFromApp('" + data + "')", null);
});
}
}
}
html5 的代码:页面点击按钮,触发 h5 的 sendDataToApp
方法,接着触发 window.JsBridge.sendDataToApp
方法向 App 发送数据,同时,h5 代码增加了 window.JsBridge.receiveDataFromApp
,那么在 App 中就可以触发window.JsBridge.receiveDataFromApp
方法,从而实现 App 和 h5 的双向通信。
<button onClick="sendDataToApp()">Send Data to App</button>
<div id="log"></div>
<div>我是app触发的:</div>
<div id="app"></div>
<script>
function sendDataToApp(){
if (window.JsBridge && typeof window.JsBridge.sendDataToApp === 'function') {
window.JsBridge.sendDataToApp('Hello from Web');
document.getElementById('log').innerHTML = 'Data sent to App';
} else {
document.getElementById('log').innerHTML = 'sent data failed';
}
}
window.JsBridge.receiveDataFromApp = function(data) {
document.getElementById('app').innerHTML = 'Received data from App: ' + data;
}
</script>
利用第三方包
除了上面介绍的传统的方式,还可以借助更安全可靠的第三方包来实现:
android jsbridge: github.com/uknownothin…[6]
ios jsbridge: github.com/marcuswesti…[7]
这里讲的是 android 的 jsbridge:
第一步.Android Studio 导包
第二步.在布局文件中添加
MyApplication2\app\src\main\res\layout\webview_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.lzyzsd.jsbridge.BridgeWebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
第三步.android 端代码
private BridgeWebView webView;
private static final String TAG="JSBridge";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.webview_layout);
webView = findViewById(R.id.webview);
WebSettings webSettings = webView.getSettings();
webSettings.setJavaScriptEnabled(true);
webView.loadUrl("http://10.168.2.149:5500/jsbridge.html");
webView.registerHandler("submitFromWeb", new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
Log.i(TAG, "handler = submitFromWeb, data from web = " + data);
function.onCallBack("submitFromWeb exe, response data from Java");
}
});
}
第四步.h5 端代码
<button onclick="handleClick()">调用 Android 方法</button>
<div id="show"></div>
<script>
function handleClick(){
if (window.WebViewJavascriptBridge) {
WebViewJavascriptBridge.callHandler(
'submitFromWeb'
, {'param': '参数测试'}
, function(responseData) {
document.getElementById("show").innerHTML = "send get responseData from java, data = " + responseData
}
);
} else {
document.getElementById("show").innerHTML = "WebViewJavascriptBridge is not loaded"
}
}
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function () {
callback(WebViewJavascriptBridge)
},
false
);
}
}
connectWebViewJavascriptBridge(function (bridge) {
//===1===在JS中注册默认的Handler,以方便Java调用,java通过send方法发送数据
bridge.init(function (message, responseCallback) {
console.log('JS got a message', message);
var data = {
'json': 'JS返回任意数据!'
};
console.log('JS responding with', data);/*打印信息*/
document.getElementById("init").innerHTML = "data = " + message;
responseCallback(data);
});
//===2===注册functionJs方法供java调用
bridge.registerHandler("functionJs", function (data, responseCallback) {
document.getElementById("show").innerHTML = ("Android端: = " + data);
var responseData = "Javascript 数据";
responseCallback(responseData);
});
})
</script>
源码
github.com/YY88Xu/MyAp…[8]
本文转载于稀土掘金技术社区,作者:许多金
原文链接:https://juejin.cn/post/7382892371225362472
最后
关注福利,关注公众号后,在首页:
回复「简历」获取精选的简历模板
回复「思维图」获取完整 JavaScript 相关思维图
回复「电子书」可下载我整理的大量前端资源,包含面试、Vue实战项目、CSS和JavaScript电子书等。
回复「Node」获取简历制作建议
最后不要忘了点个赞再走噢