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");
}
});
有興趣的建議跟着代碼弄個項目出來,自己點點思路會很清晰
本來還想解釋的,發現沒啥好說的,注釋寫的挺清楚了,就這樣吧,溜了!~