最近接到个需求,需要在WebView中通过JS交互将Json数据传给Web端,碰到了一个问题,记录一下。
接到需求的时候跟Web端的同事沟通了一下,他说传Json字符串就可以,于是我按照之前传字符串的方式传参发现html页面无法接收到参数,示例如下:
// 示例html
<!DOCTYPE html>
<html lang=zh-CN>
<head>
<meta charset=utf-8>
<title>test</title>
<script>
function getPersonJsonArray(){
JsInteractive.getPersonJsonArray()
}
function getPersonJsonArrayResult(personJsonArray){
document.getElementById("message").innerHTML = 'receive: getPersonJsonArrayResult personJsonArray:'+(personJsonArray)+' , parse:'+ (JSON.stringify(personJsonArray));
}
</script>
</head>
<body>
<div style="position:relative;left:40px;top:150px">
<p id='message' style="font-size:24px">receive:</p>
<button type="button" style="width:280px;height:88px;font-size:24px;position:relative;left:20px"
onclick="getPersonJsonArray()">
getPersonJsonArray
</button>
</div>
</body>
</html>
// 实体类
@Parcelize
data class PersonEntity(
val name: String,
val age: Int,
val gender: Int,
val weight: Float,
val height: Float
) : Parcelable {
override fun toString(): String {
return "PersonEntity(name='$name', age=$age, gender=$gender, weight=$weight, height=$height)"
}
}
// 测试页面
class WebViewActivity : Activity() {
private lateinit var layoutWebViewActivityBinding: LayoutWebViewActivityBinding
private val gson = Gson()
private var mainWebView: WebView? = null
/**
* JavaScript interface
*/
private val jsInteractive: JsInteractive = object : JsInteractive {
@JavascriptInterface
override fun getPersonJsonArray() {
// 填充10个数据
val personList = ArrayList<PersonEntity>()
for (index in 0 until 10) {
personList.add(PersonEntity("测试$index", 20 + index, if (index % 2 == 0) 0 else 1, 160f, 175f))
}
invokeJsCallback("javascript:getPersonJsonArrayResult(\"${gson.toJson(personList)}\")")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
layoutWebViewActivityBinding = DataBindingUtil.setContentView(this, R.layout.layout_web_view_activity)
layoutWebViewActivityBinding.ivBack.setOnClickListener { onBackPressed() }
mainWebView = WebView(this)
mainWebView?.let {
it.layoutParams = FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)
initWebViewSetting(it)
layoutWebViewActivityBinding.webViewContainer.addView(it)
}
mainWebView?.addJavascriptInterface(jsInteractive, "JsInteractive")
mainWebView?.loadUrl("file:///android_asset/index.html")
}
private fun invokeJsCallback(script: String) {
mainWebView?.run { runOnUiThread { loadUrl(script) } }
}
}
看了日志发现WebView给了异常信息,如下:
chromium: [INFO:CONSOLE(1)] "Uncaught SyntaxError: missing ) after argument list", source: file:///android_asset/index.html (1)
根据异常信息查询了一下,将"修改为'后,html可以接收到参数并解析出来。
//修改前
"javascript:getPersonJsonArrayResult(\"${gson.toJson(personList)}\""
//修改后
"javascript:getPersonJsonArrayResult(\'${gson.toJson(personList)}\'"
效果如图:
之后我又尝试去掉',发现html也能接收到参数并解析出来。
//修改前
function getPersonJsonArrayResult(personJsonArray){
document.getElementById("message").innerHTML = 'receive: getPersonJsonArrayResult personJsonArray:'+(personJsonArray)+' , parse:'+ (JSON.parse(personJsonArray));
}
"javascript:getPersonJsonArrayResult(\'${gson.toJson(personList)}\'"
//修改后
function getPersonJsonArrayResult(personJsonArray){
document.getElementById("message").innerHTML = 'receive: getPersonJsonArrayResult personJsonArray:'+(personJsonArray)+' , stringify:'+ (JSON.stringify(personJsonArray));
}
"javascript:getPersonJsonArrayResult(${gson.toJson(personList)}"
效果如图: