
WebView与js交互总结 精华
简介
使用 WebView 加载网页,有时候需要进行js交互,相互传递数据和响应事件。
android 调用 js 代码:
- WebView#loadUrl("javascript:func('" + arg + "')")
- WebView#evaluateJavascript(String script, @Nullable ValueCallback<String> resultCallback)
js 调用 android 代码:
- 通过 WebView#addJavascriptInterface(Object object, String name) 进行对象映射
- 通过 WebViewClient#shouldOverrideUrlLoading() 来拦截Url调用代码
- 通过 WebChromeClient 的 onJsAlert()、onJsConfirm()、
onJsPrompt() 拦截 js 中的对话框 alert() / confirm() / prompt()
Android(Kotlin)调用 JS
Android 通过 loadUrl 调用 js 代码
基础设置:
Android 调用 js 方法
如果调用 js 方法有传参,参数是一个 JSON 字符串( JSONArray 字符串(.toString())或 JSONObject字符串(.toString())),js 端需要使用 eval('(' + result + ')') 或者 "JSON.parse(result)" 将这个JSON 字符串解析为对象。
使用 eval() 解析 json,容错能力较好,这种情况 [{}, {}, ] 依然能正常解析,而 JSON.parse() 则报错。
eval 的用法可参考:js中eval()的使用说明:https://www.cnblogs.com/firstlady/p/11347382.html
注意,android端不能直接传对象(会被转成地址,或对象重写的toString())给 js,但是可以通过上述方法将 JSON 字符串转成对象;android 端也不能直接接收对象,但是js可以通过JSON.stringify(data) 将对象转成一个 JSON 字符串再传给 android。
Android 通过 evaluateJavascript() 调用JS代码
先来说说使用这个方法的优点:
使用这个方法不会刷新页面,如果使用第一种方法则会刷新页面
*注意:这个方法只能在Android4.4之后使用
使用方式:
1 .将minSdkVersion最低版本改为19 (build.gradle----minSdkVersion)
2. 直接替 loadUrl 方式
两种方式的区别:
- loadUrl()
使用起来方便简洁。
但是他是在没有返回的情况下使用。
效率比较低,获取返回值的时候很麻烦。
并且调用的时候会刷新WebView
- evaluateJavascript()
效率比loadUrl ()高很多
虽然效率高但是只支持Android4.4以上
在获取返回值时候很方便
调用时候不刷新WebView
根据情况使用两种方式,我们可以根据当前项目开发的需求选择相应的使用方式,我们可以直接判断版本号来区分使用方式:
参考:使用Kotlin:让Android与JS交互的详解
js 调用 Android(Kotlin)
使用WebView的addJavascriptInterface()进行对象映射
注意:android 端也不能直接接收对象,但是js可以通过JSON.stringify(data) 将对象转成一个 JSON 字符串再传给 android。
使用 WebViewClient() 的 shouldOverrideUrlLoading() 方法拦截Url调用 Android 代码
使用 WebChromeClient 的 onJsAlert()、onJsConfirm() 、onJsPrompt() 拦截JS中的对话框alert() / confirm() / prompt()
js 代码,注意代码里的 alert(result)
Kotlin 代码:
这种方式页可以用作 js 的 debug 调试。
三种方式的区别
addJavascriptInterface() 使用起来方便简洁,但是在 Android 低版本下有问题,用于Android4.4以上。
shouldOverrideUrlLoading() 使用起来没有漏洞,但是两端定协议,使用起来比较麻烦,主要用于不需要返回值的情况。
onJsAlert()、onJsConfirm()、onJsPrompt() 拦截 js 中的对话框 alert() / confirm() / prompt() 和第二种方式一样,没有漏洞,而且也复杂,并且需要协议来规定它。
