1.背景
之前只是用webview展示网页,和前端小伙伴没怎么联调过,传uid和token也是直接在链接后面拼,但实际复杂些项目中不可避免要和前端进行互相调用,今天重新看了一遍大佬写的JsBridge,写一个使用的小笔记
前排放入github传送门,星星最多的jsbridge! 7.4k ,同时感谢大佬
lzyzsd/JsBridge
2.开发工具
AndroidStudio
3.js_native_contact_demo
1.创建一个android项目,常规操作~ (ps:项目能跑起来没问题吧…)

2.新建一个assets文件夹,如上图所示,里面创建一个叫demo.html的文件,代码直接贴进去,复制粘贴才是王道,手敲都是异类(不接受反驳,小声xx~+邪笑.png)
<html xmlns:white-space="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<!-- 网页适配手机页面-->
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no">
<title>
js调用java
</title>
</head>
<body bgcolor="#f0ffff">
<div>
<p id="show" style="background-color:white">
</p>
<pre id="init">
</pre>
<p>
<input type="text" id="text1" value="username"/>
</p>
<p>
<input type="text" id="text2" value="address"/>
</p>
<p>
<input type="button" id="enter" value="无需分配handle方法名(默认的),直接发消息给native"
onclick="jsToNativeDefault();"
/>
</p>
<p>
<input type="button" id="enter1" value="通过submitFromWeb的handle方法名,调用native的同名方法"
onclick="jsToNativeCustom();"
/>
</p>
<p>
<input type="button" id="enter2" value="显示html" onclick="testDiv();"/>
</p>
<p>
<input type="file" value="默认为type的input输入框,手机上没什么反应,在pc端会自动打开选择文件的窗口,点击文件会将文件名输入"/>
</p>
<xmp id='showHtml' style='background-color:white'/>
</div>
</body>
<script>
// js发送native默认的消息
function jsToNativeDefault() {
var str1 = document.getElementById("text1").value;
var str2 = document.getElementById("text2").value;
//send message to native
var data = {id: 1, content: "通过js页面点击,调用默认方法,发送该信息到手机端"};
window.WebViewJavascriptBridge.send(
data
, function (responseData) {
document.getElementById("show").innerHTML = "发消息给native,并收到了native的反馈如下\n" + responseData
}
);
}
// js发送native自定义名字的消息
function jsToNativeCustom() {
var str1 = document.getElementById("text1").value;
var str2 = document.getElementById("text2").value;
//call native method
window.WebViewJavascriptBridge.callHandler(
'submitFromWeb'
, {'param': '通过js页面点击,调用submitFromWeb方法,发送该信息到手机端'}
, function (responseData) {
document.getElementById("show").innerHTML = "发消息给native,并收到了native的反馈如下\n" + responseData
}
);
}
// 将html标签下的所有代码贴入xmp标签里
function testDiv() {
document.getElementById("showHtml").innerHTML = document.getElementsByTagName("html")[0].innerHTML;
}
// 设置向native发送的回调
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function () {
callback(WebViewJavascriptBridge)
},
false
);
}
}
// 获取native发送的消息
connectWebViewJavascriptBridge(function (bridge) {
bridge.init(function (message, responseCallback) {
alert(message);
document.getElementById("show").innerHTML = ("native通过默认方法给js发来的信息如下\n" + message);
var data = {
'JS Responds': 'js已经收到默认方法发送来的消息,native请知悉!'
};
if (responseCallback) {
responseCallback(data);
}
});
bridge.registerHandler("functionInJs", function (data, responseCallback) {
alert(data); // typeof data 是 string
document.getElementById("show").innerHTML = ("native通过functionInJs方法给js发来的信息如下\n" + data);
var str1 = JSON.parse(data);
document.getElementById("text1").value = str1.name;
document.getElementById("text2").value = str1.location.address;
if (responseCallback) {
var responseData = "js已经收到functionInJs方法发送来的消息,native请知悉!";
responseCallback(responseData);
}
});
})
</script>
</html>
3.引入jsbridge
project级build.gradle中加入jitpack的maven库
allprojects {
repositories {
google()
jcenter()
// jitpack
maven { url "https://jitpack.io" }
}
}
app级build.gradle中加入dependencies依赖项
dependencies {
...
implementation 'com.google.code.gson:gson:2.8.6'
}
4.Android的xml页面代码,贴就完了
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/colorPrimary"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:gravity="center"
android:text="这里是原生⬇️"
android:textStyle="bold" />
<Button
android:id="@+id/btnDefaultTest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="向js发送默认handleName的消息"
android:textAllCaps="false" />
<Button
android:id="@+id/btnCustomTest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="向js发送定制handleName=functionInJs的消息"
android:textAllCaps="false" />
<TextView
android:id="@+id/tvTextInfo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text=""
android:textColor="#ffffff" />
</LinearLayout>
<TextView
android:id="@+id/tvReloadUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#f0ffff"
android:gravity="center"
android:text="这里是网页⬇️"
android:textStyle="bold" />
<com.github.lzyzsd.jsbridge.BridgeWebView
android:id="@+id/testWebView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
布局截图
运行截图
5.activity中的代码,贯彻一直的“优良作风”粘代码(findById自己写- -)
static class Location {
String address;
public Location(String address) {
this.address = address;
}
}
static class User {
String name;
Location location;
String testStr;
public User(String name, Location location, String testStr) {
this.name = name;
this.location = location;
this.testStr = testStr;
}
}
// 设置浏览器链接
webView.setWebChromeClient(new WebChromeClient());
// 加载url
webView.loadUrl("file:///android_asset/demo.html");
// 注册js监听回调,js通过默认方法发送消息给native时,可以在此处接收到
webView.setDefaultHandler(new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
new AlertDialog.Builder(MainActivity.this).setMessage(data.toString()).show();
tvTextInfo.setText(data.toString());
function.onCallBack("Native已经收到了默认方法的消息,Js请知悉!");
}
});
// 注册js监听回调,js通过 submitFromWeb 方法发送消息给native时,可以在此处接收到
webView.registerHandler("submitFromWeb", new BridgeHandler() {
@Override
public void handler(String data, CallBackFunction function) {
new AlertDialog.Builder(MainActivity.this).setMessage(data.toString()).show();
tvTextInfo.setText(data.toString());
function.onCallBack("Native已经收到了名为submitFromWeb方法的消息,Js请知悉!");
}
});
// native主动发消息给js(默认handleName方法)
btnDefaultTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.send("这里是native向js发送的默认消息!", new CallBackFunction() {
@Override
public void onCallBack(String data) {
tvTextInfo.setText(data.toString());
new AlertDialog.Builder(MainActivity.this).setMessage("通过默认方法发消息给js,并收到了js的反馈如下\n" + data).show();
}
});
}
});
// native主动发消息给js(handleName = "functionInJs" 的方法)
btnCustomTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.callHandler("functionInJs", new Gson().toJson(new User("小白兔", new Location("大兴安岭"), "这里是native向js发送的名字叫做'functionInJs'消息!")), new CallBackFunction() {
@Override
public void onCallBack(String data) {
tvTextInfo.setText(data.toString());
new AlertDialog.Builder(MainActivity.this).setMessage("通过functionInJs方法发消息给js,并收到了js的反馈如下\n" + data).show();
}
});
}
});
// 重新加载网页
tvReloadUrl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
webView.loadUrl("file:///android_asset/demo.html");
}
});
有兴趣的建议跟着代码弄个项目出来,自己点点思路会很清晰
本来还想解释的,发现没啥好说的,注释写的挺清楚了,就这样吧,溜了!~