在 Android WebView 中,JavaScript 和原生 Android 代码可以通过以下几种方式进行通信:
1. 通过 addJavascriptInterface
实现双向通信
Android 提供了 addJavascriptInterface
方法,可以将 Java 对象注入到 WebView 中,供 JavaScript 调用。
步骤:
-
在 Android 中创建 Java 对象:
创建一个 Java 类,定义需要暴露给 JavaScript 的方法,并使用@JavascriptInterface
注解标记这些方法。public class WebAppInterface { Context mContext; WebAppInterface(Context context) { mContext = context; } @JavascriptInterface public void showToast(String message) { Toast.makeText(mContext, message, Toast.LENGTH_SHORT).show(); } }
-
将 Java 对象注入 WebView:
在 WebView 中调用addJavascriptInterface
方法,将 Java 对象注入到 JavaScript 环境中。WebView webView = findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new WebAppInterface(this), "Android");
-
在 JavaScript 中调用 Android 方法:
在 JavaScript 中,可以通过注入的对象名(如Android
)调用 Java 方法。// 调用 Android 的 showToast 方法 Android.showToast("Hello from JavaScript!");
2. 通过 evaluateJavascript
实现 Android 调用 JavaScript
Android 可以通过 evaluateJavascript
方法调用 WebView 中的 JavaScript 函数。
步骤:
-
在 JavaScript 中定义函数:
在 HTML 页面中定义一个 JavaScript 函数。<script> function showMessage(message) { alert("Message from Android: " + message); } </script>
-
在 Android 中调用 JavaScript 函数:
使用evaluateJavascript
方法调用 JavaScript 函数。webView.evaluateJavascript("javascript:showMessage('Hello from Android!')", null);
3. 通过 WebViewClient
拦截 URL 实现通信
可以通过自定义 WebViewClient
拦截特定的 URL 来实现通信。
步骤:
-
在 JavaScript 中触发 URL 跳转:
在 JavaScript 中通过window.location.href
或iframe
跳转到一个特定的 URL。function sendMessageToAndroid(message) { window.location.href = "js://webview?message=" + encodeURIComponent(message); }
-
在 Android 中拦截 URL:
在WebViewClient
中重写shouldOverrideUrlLoading
方法,解析 URL 并处理消息。webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { if (url.startsWith("js://webview")) { // 解析 URL 中的消息 String message = url.split("message=")[1]; Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show(); return true; // 拦截 URL } return super.shouldOverrideUrlLoading(view, url); } });
4. 通过 WebChromeClient
拦截 JavaScript 弹窗
可以通过 WebChromeClient
拦截 JavaScript 的 alert
、confirm
和 prompt
弹窗,实现通信。
步骤:
-
在 JavaScript 中触发弹窗:
在 JavaScript 中调用alert
、confirm
或prompt
。alert("Hello from JavaScript!");
-
在 Android 中拦截弹窗:
在WebChromeClient
中重写onJsAlert
、onJsConfirm
或onJsPrompt
方法。webView.setWebChromeClient(new WebChromeClient() { @Override public boolean onJsAlert(WebView view, String url, String message, JsResult result) { Toast.makeText(MainActivity.this, message, Toast.LENGTH_SHORT).show(); result.confirm(); // 处理弹窗 return true; // 拦截弹窗 } });
5. 通过 postMessage
实现双向通信
Android WebView 支持 HTML5 的 postMessage
API,可以实现更安全的双向通信。
步骤:
-
在 JavaScript 中发送消息:
使用postMessage
向 Android 发送消息。window.postMessage("Hello from JavaScript!", "*");
-
在 Android 中接收消息:
在 Android 中通过evaluateJavascript
监听message
事件。webView.setWebViewClient(new WebViewClient() { @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); // 注入 JavaScript 代码以监听消息 webView.evaluateJavascript( "window.addEventListener('message', function(event) { " + " Android.onMessage(event.data); " + "});", null); } });
-
在 Android 中处理消息:
在 Java 中定义onMessage
方法。@JavascriptInterface public void onMessage(String message) { Toast.makeText(this, message, Toast.LENGTH_SHORT).show(); }
总结
方法 | 优点 | 缺点 |
---|---|---|
addJavascriptInterface | 简单易用,支持双向通信 | 安全性较低(需注意漏洞) |
evaluateJavascript | Android 调用 JavaScript 方便 | 仅支持单向通信 |
拦截 URL | 兼容性好,适合简单场景 | URL 长度有限,不适合复杂数据 |
拦截弹窗 | 兼容性好,适合简单场景 | 仅支持单向通信 |
postMessage | 安全性高,支持复杂数据 | 实现稍复杂 |
根据具体需求选择合适的方式实现通信!