我正在使用kotlin开发本机应用程序,该应用程序具有一个webview和一些用于webview javascript的功能。
用户可以单击页面上的按钮,然后调用本机吐司或警报对话框
我完成了功能并使其正常工作,现在我想在对话框中添加callback function
,当用户单击“确定”按钮(正按钮)时,它将在网页上运行javascript,
网页上的Javascript
Android.showAlert("Title","Message",function(){alert(123)});
JavascriptInterface
@JavascriptInterface
fun showAlert(title:String,msg: String, callBack: Any?) {
val alertDialog = AlertDialog.Builder(mContext)
alertDialog.setTitle(title).setMessage(msg)
alertDialog.setPositiveButton("OK") { _, _->callBack())}
alertDialog.show()
Log.d('check',callBack) // Logged callback is null
}
代码似乎无法接收回调函数,我该如何解决并运行回调?
谢谢
答案 0 :(得分:0)
您不能只记录一个函数,因为在JavaScript函数中,没有其他语言上的ID或地址或类似的名称。要记录它,您必须使用函数ID或文本名称显式设置一个属性或字符串,然后使用它。最好的方法可能是通过文本名称传递回调-然后可以将其记录下来,然后实际进行回调,请参见下文。
此网站上的人们建议使用这种方法从Android调用WebView中的JavaScript:
mWebView.loadUrl("javascript:someFuncInJS();");
但是,有更好,更清洁的方法可以做到这一点,看起来更正确:使用 EvaluationJavascript()方法。这是使用它的参考习语:
mWebView.evaluateJavascript("""
(your javascript code goes here)
""".trimIndent()) { retv ->
(and here in Kotlin you can handle return value after the code above will be executed)
}
您可以这样写:
var myCB = "myCallbackFunc1" // you can get it from previous call from JS
Log.d("check, ${myCB}")
mWebView.evaluateJavascript("""
${myCB}();
""".trimIndent()) { retv ->
}
也请查看以下内容:Kotlin use Java callback interface
编辑: 就是这样, if 是您从Android程序的UI线程(主线程)进行调用。但是,如果尝试从运行在不同线程上的JavascriptInterface调用中执行此操作,则它将失败。解决方案是始终将评估Javascript()放在UI线程上,如果需要从另一个线程进行操作,请使用View.post {}。这是一个示例:
class WebAppInterface(private val mContext: Context, val mAct: MainActivity) {
/** Show a toast from the web page */
@JavascriptInterface
fun showToast(toast: String) {
Toast.makeText(mContext, toast, Toast.LENGTH_SHORT).show()
mAct.mWebView?.post {
mAct.mWebView?.evaluateJavascript("f1();") { retv ->
Toast.makeText(mContext, retv, Toast.LENGTH_LONG).show()
}
}
}
}
有关如何执行此操作的完整示例,请查看https://github.com/latitov/Android_WebViewApp_FullScreen
希望有帮助。