参考
Android:你要的WebView与 JS 交互方式 都在这里了
代码
一.交互方式总起
1.1 Android调用js
+ WebView.loadUrl(“javascript:js方法名”)
+ WebView.evaluateJavascript("javascript:js方法名")
1.2 js调用Android
+ 通过WebView的addJavascriptInterface()进行对象映射
+ 通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url
+ 通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息
二.Android调用js
2.1 WebView.loadUrl
如果js中有一个方法名为 callByAndroidLoadUrl
function callByAndroidLoadUrl(){
document.getElementById("demo").innerHTML = "109876"
}
则在android中使用如下代码调用
web_view.loadUrl("javascript:callByAndroidLoadUrl()")
2.2 WebView.evaluateJavascript
如果js中有一个名为callByAndroidEvaluateJavascript
function callByAndroidEvaluateJavascript(){
document.getElementById("demo").innerHTML = "678910"
return "hahaha"
}
则在android中使用如下代码调用
/**
* 使用WebView.evaluateJavascript调用js
*/
fun androidInvokeJsByEvaluateJavascript(view: View) {
web_view.evaluateJavascript("javascript:callByAndroidEvaluateJavascript()") {
Log.i("MainActivity", it)
}
}
2.3 总结
调用方法 | 有点 | 缺点 | 使用场景 |
---|---|---|---|
使用loadUrl() | 方便简洁 | 效率低;调用的方法不能有返回值,如果方法有返回值,则webview会显示返回的内容 | 不需要返回值 |
使用WebView.evaluateJavascript | 效率高 | 仅支持4.4以上 | android4.4以上 |
三.js调用android代码
3.1 WebView的addJavascriptInterface()对象映射
比如 android有一个类InvokeByJs这个类,其中showMsg需要被js调用,则
inner class InvokeByJS {
// 被JS调用的方法必须加入@JavascriptInterface注解
@JavascriptInterface
fun showMsg(msg: String) {
Toast.makeText(this@MainActivity, msg, Toast.LENGTH_LONG).show()
}
}
//将InvokeByJS类对象映射到js的invokeByJS对象
web_view.addJavascriptInterface(InvokeByJS(), "invokeByJS")
js中
3.2 通过 WebViewClient 的shouldOverrideUrlLoading ()方法回调拦截 url
js代码
function callAndroidByLoadUrl(){
document.location = "js://tosat?msg=需要android处理的url";
}
android代码
//拦截url
web_view.webViewClient = object : WebViewClient() {
@RequiresApi(Build.VERSION_CODES.LOLLIPOP)
override fun shouldOverrideUrlLoading(
view: WebView?,
request: WebResourceRequest?
): Boolean {
val url = request?.url.toString()
if (url.startsWith("js://tosat")) {
//得到的url是通过url编码的,所以这里需要url解码
val msg =URLDecoder.decode(url).split("msg=")[1]
Toast.makeText(this@MainActivity, (msg), Toast.LENGTH_LONG).show()
return true
}
return false
}
}
3.3 通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息
以prompt为例
prompt为一个输入框。
我们可以通过拦截对话框,进行处理。
html中
function clickPrompt(){
var result=prompt("js://tosat?msg=通过prompt调用android");
}
android代码
web_view.webChromeClient = object :WebChromeClient(){
override fun onJsPrompt(
view: WebView?,
url: String,
message: String,
defaultValue: String?,
result: JsPromptResult
): Boolean {
if(message.startsWith("js://tosat")){
val msg =message.split("msg=")[1]
Toast.makeText(this@MainActivity, (msg), Toast.LENGTH_LONG).show()
//result.confirm必须要赋值,表示prompt的返回值
result.confirm("js调用了Android的方法成功啦")
//返回true,表示WebChromeClient会处理prompt,WebView不需要弹出输入框
return true
}
return super.onJsPrompt(view, url, message, defaultValue, result)
}
}
3.4总结
调用方法 | 有点 | 缺点 | 使用场景 |
---|---|---|---|
addJavascriptInterface() | 方便简洁;有返回值 | Android4.2存在漏洞 | Android4.2以上 |
WebViewClient 的shouldOverrideUrlLoading () | 无漏洞 | 需要自定定义协议;无返回值 | 不需要返回值 |
通过 WebChromeClient 的onJsAlert()、onJsConfirm()、onJsPrompt()方法回调拦截JS对话框alert()、confirm()、prompt() 消息 | 无漏洞;有返回值 | 需要自定定义协议 | 大多数情况下 |