用 jsBridge 可以使用一套 h5 页面兼容 iOS / android 的写法,在实际开发项目中,起到降低开发成本的作用
添加依赖
com.github.lzyzsd:jsbridge:1.0.4
android 代码写法
我这里为了省事,用 compose 来写界面了
package com.lujianfei.kotlindemo.ui.jsbridge
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.speech.tts.TextToSpeech
import android.util.Log
import android.webkit.JsResult
import android.webkit.WebChromeClient
import android.webkit.WebView
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.viewinterop.AndroidView
import com.github.lzyzsd.jsbridge.BridgeWebView
import com.lujianfei.kotlindemo.R
import com.lujianfei.kotlindemo.base.Page
import org.json.JSONObject
import java.util.Locale
/**
* Author: lujianfei
* Date: 2023/12/29 13:50
* Description:
*/
@ExperimentalUnitApi
class JsBridgeActivity:AppCompatActivity() {
companion object {
const val tag = "JsBridgeActivity="
fun start(context: Context) {
context.startActivity(Intent(context, JsBridgeActivity::class.java))
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Page(
leftIcon = R.drawable.ic_back,
onLeftClick = {
onBackPressed()
},
title = "JsBridge 用法",
onRightClick = {
},
rightText = null
) {
Content()
}
}
}
@ExperimentalUnitApi
@Composable
@Preview(showSystemUi = true)
fun Content() {
AndroidView(factory = {
context->
BridgeWebView(context).apply {
settings.javaScriptEnabled = true
settings.domStorageEnabled = true
webChromeClient = object: WebChromeClient() {
override fun onJsAlert(
view: WebView?,
url: String?,
message: String?,
result: JsResult?
): Boolean {
AlertDialog.Builder(this@JsBridgeActivity)
.setTitle("提示")
.setMessage(message)
.setPositiveButton(android.R.string.ok) {_,_->
result?.confirm()
}.create()
.show()
return true
}
}
registerHandler("showToast") { data, response->
val jsonObject = JSONObject(data)
Toast.makeText(this@JsBridgeActivity, jsonObject.optString("content"), Toast.LENGTH_SHORT).show()
response.onCallBack("Called from Android")
}
loadUrl("file:///android_asset/jsbridge.html")
}
}, modifier = Modifier.fillMaxSize())
}
}
但是安卓原生有个注意事项, 假如你需要自己实现 webViewClient,就需要使用 BridgeWebViewClient ,否则在 h5 端会出现 window.WebViewJavascriptBridge 对象 undefined 的情况
mWebView.webViewClient = object : BridgeWebViewClient(mWebView) {
override fun onPageFinished(view: WebView?, url: String?) {
if (splashView != null) Animation().fadeOut(splashView as View, 1000)
super.onPageFinished(view, url)
}
override fun onReceivedError(
view: WebView?,
request: WebResourceRequest?,
error: WebResourceError?
) {
Log.i(tag, "onReceivedError")
view?.loadUrl("file:///android_asset/error.html")
super.onReceivedError(view, request, error)
}
override fun onReceivedHttpError(
view: WebView?,
request: WebResourceRequest?,
errorResponse: WebResourceResponse?
) {
Log.i(tag, "onReceivedHttpError")
view?.loadUrl("file:///android_asset/error.html")
super.onReceivedHttpError(view, request, errorResponse)
}
}
html 文件
<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<title>js 调用 java</title>
</head>
<body>
<p>
<input type="button" value="调用安卓的 Toast 方法" onclick="testToastClick()"/>
</p>
<script>
//发送消息给安卓
function testToastClick() {
//调用java中的方法 submitFromWeb是方法名
window.WebViewJavascriptBridge.callHandler(
'showToast'
, {'content': 'Call from H5'}
, function(responseData) {
alert(responseData)
}
);
}
//注册事件监听
function connectWebViewJavascriptBridge(callback) {
if (window.WebViewJavascriptBridge) {
callback(WebViewJavascriptBridge)
} else {
document.addEventListener(
'WebViewJavascriptBridgeReady'
, function() {
callback(WebViewJavascriptBridge)
},
false
);
}
}
//注册回调函数,第一次连接时调用 初始化函数
connectWebViewJavascriptBridge(function(bridge) {
//初始化
bridge.init(function(message, responseCallback) {
var data = {
'Javascript Responds': 'Wee!'
};
responseCallback(data);
});
//接收安卓发来的消息 并返回给安卓通知
bridge.registerHandler("functionInJs", function(data, responseCallback) {
alert(data);
var responseData = "我接受到了安卓的调用";
responseCallback(responseData);
});
})
</script>
</body>
</html>