顺应大前端的潮流,Hybrid APP越来越重要,学习一波Android与JavaScript的交互方式。
原理:通过WebView这个中间组件来相互调用
一些基础的配置:
val webSetting = webView.settings
// 允许与JS交互
webSetting.javaScriptEnabled = true
// 允许弹窗
webSetting.javaScriptCanOpenWindowsAutomatically = true
// loadUrl会使页面刷新
// 先载入JS代码
// 格式规定为:file:///android_asset/文件名.html
webView.loadUrl("file:///android_asset/javascript.html")
1.Android调用JavaScript
- 通过
WebView.loadUrl("javascript:callJSByLoadUrl()")
: javascript为文件名,callJSByLoadUrl为对应文件下的对应方法名 - 通过
WebView.evaluateJavascript("javascript:callJSByLoadUrl()")
: javascript为文件名,callJSByLoadUrl为对应文件下的对应方法名
方式一:
webView.post {
// 调用javascript的callJS()方法
webView.loadUrl("javascript:callJSByLoadUrl()")
}
方式二:
webView.post {
// 方式二: 4.4以上才可使用
webView.evaluateJavascript(
"javascript:callJSByEvaluate()"
) { value ->
Log.e("wdl", "evaluateJavascript $value")
}
}
对应的JS文件如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Wdl</title>
<script>
function callJSByLoadUrl(){
alert("Android调用了JS的callJSByLoadUrl方法");
}
function callJSByEvaluate(){
alert("Android调用了JS的callJSByEvaluate方法");
}
</script>
</head>
</html>
两种方式的不同点:
1.通过loadUrl方法,会导致整个页面刷新(4.4以下使用)
2.通过evaluateJavascript方法(4.4以上使用)
2.JavaScript调用Android
- 通过
webView.addJavascriptInterface(JS2Android(), "test")
: JS2Android()为JS与Android的映射类,test为映射对象的名称 - 通过
WebViewClient.shouldOverrideUrlLoading拦截url,解析url调用相对应的方法
- 通过
WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息
方式一:
对应的映射类:加上 @JavascriptInterface 注解,方法名即JS中使用的方法名
class JS2Android {
@JavascriptInterface
public fun hello(msg: String) {
Log.e("wdl", "hello $msg")
}
}
// 方式一:addJavascriptInterface()
// 将Java对象映射到JS对象
// 参数一:JS2Android
// 参数二:对象名
// 存在严重的漏洞问题
webView.addJavascriptInterface(JS2Android(), "test")
方式二:
// 方式二:通过WebViewClient.shouldOverrideUrlLoading拦截url,解析url调用相对应的方法
// 复写WebViewClient类的shouldOverrideUrlLoading方法
// 获取Android 返回的参数比较复杂
// 如果JS想要得到Android方法的返回值,只能通过 WebView 的 loadUrl ()去执行 JS 方法把返回值传递回去,相关的代码如下:
// // Android:MainActivity.java
//mWebView.loadUrl("javascript:returnResult(" + result + ")");
//
JS:javascript.html
//function returnResult(result){
// alert("result is" + result);
//}
webView.webViewClient = object : WebViewClient() {
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
val uri = request?.url
// js://webview?arg1=111&arg2=222 示例uri
// 获取 uri 并进行解析
if (uri?.scheme.equals("js")) {
if (uri?.authority.equals("webview")) {
// 获取参数
val params = uri?.queryParameterNames
// 调用相对应的Android 方法
Log.e("wdl", "shouldOverrideUrlLoading拦截url ${params?.size}")
}
return true
}
return super.shouldOverrideUrlLoading(view, request)
}
}
方式三:
// 方式三:通过WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息
webView.webChromeClient = object : WebChromeClient() {
// 输入框
override fun onJsPrompt(
view: WebView?,
url: String?, // file:///android_asset/javascript1.html,不是我们所需的
message: String?,
defaultValue: String?,
result: JsPromptResult?
): Boolean {
val uri = Uri.parse(message)
if (uri?.scheme.equals("js")) {
if (uri?.authority.equals("webview")) {
// 获取参数
//val params = uri?.queryParameterNames
// 调用相对应的Android 方法
//Log.e("wdl", "通过WebChromeClient ${params?.size}")
// result?.confirm("JS通过WebChromeClient调用Android方法成功了!!")
result?.confirm("调用Android方法成功了")
}
return true
}
return super.onJsPrompt(view, url, message, defaultValue, result)
}
// 确认框
override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
return super.onJsConfirm(view, url, message, result)
}
// 警告框
override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
return super.onJsAlert(view, url, message, result)
}
}
}
对应的JS文件:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Wdl</title>
<script>
function callAndroidByAddJavascriptInterface(){
// 由于对象映射,所以调用test对象等于调用Android映射的对象
test.hello("AddJavascriptInterface js调用了android中的hello方法");
}
function callAndroidByShouldOverrideUrlLoading(){
// 拦截url。。解析并调用对应的方法
/*约定的url协议为:js://webview?arg1=111&arg2=222*/
document.location = "js://webview?arg1=111&arg2=222";
}
function callAndroidByWebChromeClient(){
// 通过WebChromeClient
/*约定的url协议为:js://webview?arg1=111&arg2=222*/
var result = prompt("js://webview?arg1=111&arg2=222")
alert("返回值"+result)
}
</script>
</head>
<body>
<button type="button" id="button1" onclick="callAndroidByAddJavascriptInterface()">callAndroidByAddJavascriptInterface
</button>
<button type="button" id="button2" onclick="callAndroidByShouldOverrideUrlLoading()">
callAndroidByShouldOverrideUrlLoading
</button>
<button type="button" id="button3" onclick="callAndroidByWebChromeClient()">callAndroidByWebChromeClient
</button>
</body>
</html>
本篇文章相对来说比较简单…,…!!!
参考自:https://blog.csdn.net/carson_ho/article/details/64904691