在 Android 应用中,可以通过 WebView
和 JavaScript 的双向通信实现 Android 和 Web 内容的互动。
通信方法:
以下代码示例展示了
如何使用 @JavascriptInterface
注解来实现从 JavaScript 到 Android 的同步调用
如何使用 evaluateJavascript
来实现从 Android 到 JavaScript 的同步调用
在 Android 应用中,如果你想从 Android 端调用 JavaScript 方法并传递数据给 WebView 中的 JavaScript,可以使用 evaluateJavascript
方法。以下是一个详细的示例,展示了如何实现这一点。
Android 端代码
-
创建
JavaScriptInterface
类:用来接收来自 js 的回调
class MyJavaScriptInterface {
@JavascriptInterface
fun callFunctionSync(funcName: String, dataFromJs: String): String {
Log.d("MyJavaScriptInterface", "callFunctionSync: 方法名=$funcName, dataFromJs=$dataFromJs")
var handleResult = ""
// Convert async process to synchronous
runBlocking {
handleResult = handleRequestSync(funcName, dataFromJs)
}
return handleResult
}
private suspend fun handleRequestSync(funcName: String, dataFromJs: String): String {
val handleResult = suspendCoroutine<String> { continuation ->
mCommunicator?.handleJsRequest(funcName, dataFromJs) { callbackResult ->
continuation.resume(callbackResult)
}
}
return handleResult
}
private var mCommunicator: Communicator? = null
interface Communicator {
fun handleJsRequest(funcName: String, data: String, callback: (String) -> Unit)
}
fun setCommunicator(communicator: Communicator) {
mCommunicator = communicator
}
}
-
在 Activity 或 Fragment 中设置
Communicator
并调用 JavaScript 方法:设置
WebView
并启用 JavaScript:
class WebviewActivity : AppCompatActivity(), MyJavaScriptInterface.Communicator {
private lateinit var binding: ActivityWebviewBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityWebviewBinding.inflate(layoutInflater)
setContentView(binding.root)
val webView = binding.webView
webView.settings.javaScriptEnabled = true
val jsInterface = MyJavaScriptInterface()
jsInterface.setCommunicator(this)
webView.addJavascriptInterface(jsInterface, "AndroidFunction")
webView.loadUrl("file:///android_asset/index.html")
// 从Android调用JavaScript函数的例子
binding.button.setOnClickListener {
webView.evaluateJavascript("javascript:showMessageFromAndroid('Hello from Android')", null)
}
}
override fun handleJsRequest(funcName: String, data: String, callback: (String) -> Unit) {
// Handle the JS request and call the callback with the result
val result = "Result: 666"
callback(result)
// 也可以从Android调用JavaScript函数把结果回调
runBlocking(Dispatchers.Main) {
// val webView = binding.webView
// val jsCode = "javascript:handleResponseFromAndroid('$result')"
// webView.evaluateJavascript(jsCode, null)
}
}
}
- 布局文件 res/layout/activity_webview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:gravity="center"
android:orientation="vertical"
tools:context=".WebsocketActivity">
<WebView
android:layout_margin="24dp"
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="400dp"/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="调用 webview 的方法" />
</LinearLayout>
HTML 和 JavaScript 端代码
创建 assets/index.html
在 HTML 文件中,定义 JavaScript 方法以便 Android 调用:
<!DOCTYPE html>
<html>
<head>
<title>WebView Communication</title>
</head>
<body>
<h1>WebView Communication</h1>
<button onclick="callAndroidFunction()">Call Android Function</button>
<textarea id="textArea" style="width: 100%; height: 200px;">Text~~~</textarea>
<script type="text/javascript">
function callAndroidFunction() {
var result = AndroidFunction.callFunctionSync("someFunction", "data from JS");
setTextAreaContent("Result from Android: " + result);
}
function showMessageFromAndroid(message) {
setTextAreaContent("Message from Android: " + message);
}
function handleResponseFromAndroid(response) {
setTextAreaContent("Response from Android: " + response);
}
function setTextAreaContent(content) {
var textarea = document.getElementById('textArea');
textarea.value = content;
}
</script>
</body>
</html>
说明
- JavaScript 调用 Android 方法:通过
AndroidFunction.callFunctionSync
调用 Android 方法,并传递函数名称和数据。返回结果可以同步接收。 - Android 调用 JavaScript 方法:通过
evaluateJavascript
方法调用 JavaScript 代码,例如showMessageFromAndroid
和handleResponseFromAndroid
。 - 通信接口:
Communicator
接口用于处理 JavaScript 请求,并通过回调返回结果。调用evaluateJavascript
实现从 Android 到 JavaScript 的调用。