将 Java 对象或方法“注入”到 JavaScript 的全局作用域中,这样 JS 就可以通过一个约定的名字来访问并调用 Java 代码。

我们将分步进行讲解,从最基础到更高级的用法。
第一步:准备工作 - 添加 WebView
你需要在你的 Activity 或 Fragment 中添加一个 WebView 控件,并加载一个 HTML 页面,这个页面将包含你的 JavaScript 代码。
布局文件 (activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Java/Kotlin 代码 (MainActivity.java 或 MainActivity.kt)
// MainActivity.java
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebView;
import android.webkit.WebViewClient;
public class MainActivity extends AppCompatActivity {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
// 启用 JavaScript
webView.getSettings().setJavaScriptEnabled(true);
// 设置 WebViewClient,确保页面在 WebView 内部加载,而不是跳转到外部浏览器
webView.setWebViewClient(new WebViewClient());
// 加载本地 HTML 文件
// 假设你的 html 文件放在 assets 文件夹下
webView.loadUrl("file:///android_asset/my_page.html");
}
}
重要: 为了让 WebView 能够正常工作,你还需要在 AndroidManifest.xml 中添加网络权限(即使加载本地文件,有时也需要)。
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application ...>
...
</application>
</manifest>
第二步:基础用法 - JS 调用 Java 无参方法
这是最简单的场景,JS 调用一个不需要参数的 Java 方法。

创建一个 Java 接口
这个接口将作为 JS 和 Java 之间的桥梁,接口中的方法就是 JS 可以调用的方法。
// JsInterface.java
package com.example.webviewdemo;
public interface JsInterface {
void showToastFromJava();
}
在 Activity 中实现接口并注入
我们将上面的接口在 MainActivity 中实现,并将其注入到 WebView 的 JavaScript 环境中。
// MainActivity.java (修改后)
public class MainActivity extends AppCompatActivity implements JsInterface {
private WebView webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient());
// 关键步骤:将实现了 JsInterface 的对象注入到 WebView 中
// 参数1: 对象的引用 (this)
// 参数2: 在 JavaScript 中可以调用的对象名称 ( android)
webView.addJavascriptInterface(this, "android");
webView.loadUrl("file:///android_asset/my_page.html");
}
@Override
public void showToastFromJava() {
// 这个方法将在 JS 被调用时执行
Toast.makeText(this, "Hello from Java!", Toast.LENGTH_SHORT).show();
}
}
注意: 从 Android 4.2 (API 17) 开始,为了安全,所有被注入的接口都必须被 @JavascriptInterface 注解标记,如果你不使用接口,而是直接注入一个类,那么需要注解类中的公共方法。
// 另一种方式:直接注入一个类 (不推荐,但常见于旧代码)
// 从 API 17 开始,方法必须有 @JavascriptInterface 注解
public class JsInterfaceClass {
@JavascriptInterface
public void showToastFromJava() {
// ...
}
}
// 在 Activity 中使用
// webView.addJavascriptInterface(new JsInterfaceClass(), "android");
编写 HTML 和 JavaScript 代码
在你的 assets 文件夹下创建 my_page.html 文件。

<!-- assets/my_page.html -->
<!DOCTYPE html>
<html>
<head>JS Call Java Demo</title>
<script type="text/javascript">
function callJavaMethod() {
// 通过我们注入的名称 "android" 调用 Java 方法
// android.showToastFromJava();
if (window.android) {
android.showToastFromJava();
} else {
alert("Android interface not found!");
}
}
</script>
</head>
<body>
<h1>WebView JS to Java Demo</h1>
<button onclick="callJavaMethod()">Call Java showToast()</button>
</body>
</html>
运行 App,点击按钮,你就能看到一个 Toast 提示了。
第三步:进阶用法 - JS 调用 Java 带参方法
JS 可以向 Java 方法传递基本数据类型(如 String, int, double, boolean)和一些 Android 支持的类型(如 JSONObject)。
修改 Java 接口
// JsInterface.java
public interface JsInterface {
void showToastFromJava();
void sendValueToJava(String value, int number);
}
在 Activity 中实现新方法
// MainActivity.java
@Override
public void sendValueToJava(String value, int number) {
String message = "Received from JS: Value = " + value + ", Number = " + number;
Toast.makeText(this, message, Toast.LENGTH_LONG).show();
}
修改 HTML 代码
<!-- assets/my_page.html (修改后) -->
<script type="text/javascript">
function callJavaMethod() {
android.showToastFromJava();
}
function sendValueToJava() {
var myText = "Hello WebView";
var myNumber = 2025;
// 调用带参方法,并传递参数
android.sendValueToJava(myText, myNumber);
}
</script>
...
<body>
...
<button onclick="callJavaMethod()">Call Java showToast()</button>
<button onclick="sendValueToJava()">Send Value to Java</button>
</body>
第四步:安全警告与最佳实践
直接使用 addJavascriptInterface 存在严重的安全风险,主要针对 Android 4.1.1 (API 16) 及更低的版本,这个漏洞被称为 JavaScript Interface Injection,恶意网站可以通过反射调用你注入的任何 Java 对象的公共方法,可能导致敏感信息泄露或执行恶意代码。
如何安全地使用 addJavascriptInterface?
- 最低 SDK 版本:如果你的
minSdkVersion大于等于 17 (Android 4.2),那么你只需要给要暴露的方法加上@JavascriptInterface注解即可,风险大大降低。 - 最低 SDK 版本 < 17:如果你必须支持低于 API 17 的系统,强烈建议不要使用
addJavascriptInterface,你应该采用更安全的替代方案。
安全的替代方案:@JavascriptInterface + 限制 URL
这是目前最推荐的通用安全做法,即使在高版本上也是良好实践。
核心思想: 只在 WebView 完全加载了受信任的 URL 之后,才将接口注入进去。
// MainActivity.java
public class MainActivity extends AppCompatActivity implements JsInterface {
private WebView webView;
private static final String TRUSTED_URL = "file:///android_asset/my_page.html"; // 或者你自己的域名
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
webView = findViewById(R.id.webview);
webView.getSettings().setJavaScriptEnabled(true);
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// 只在页面加载完成,URL 是我们信任的 URL 时,才注入接口
if (url.equals(TRUSTED_URL)) {
view.addJavascriptInterface(MainActivity.this, "android");
}
}
});
// 加载页面
webView.loadUrl(TRUSTED_URL);
}
// ... 其他方法
}
通过这种方式,即使你的 App 加载了恶意网页,由于 onPageFinished 中的 URL 检查,恶意网页也无法获取到 android 这个接口对象,从而避免了安全漏洞。
第五步:Java 调用 JavaScript (反向调用)
虽然你的问题只问了 JS 调用 Java,但了解反向调用也非常有用。
Java 调用 JS 非常直接,使用 WebView 的 evaluateJavascript() 方法。
// 在 MainActivity 的某个方法中,例如在按钮点击事件里
public void callJavaScriptMethod() {
webView.evaluateJavascript("showAlertFromJS('Message from Java!')", new ValueCallback<String>() {
@Override
public void onReceiveValue(String value) {
// value 是 JS 方法的返回值,这里我们不需要,所以可以为空
// JS 方法有返回值,value 就是那个返回值
}
});
}
对应的 HTML 中的 JS 方法:
// assets/my_page.html
function showAlertFromJS(message) {
alert(message);
// 也可以返回一个值
// return "JS received: " + message;
}
| 场景 | 步骤 | 关键代码/说明 |
|---|---|---|
| JS 调 Java | 创建接口 | public interface JsInterface { ... } |
| 实现接口 | public class MainActivity implements JsInterface |
|
| 注入接口 | webView.addJavascriptInterface(this, "android"); |
|
| JS 调用 | android.javaMethodName(); |
|
| 安全 | 限制注入时机 | 在 WebViewClient.onPageFinished() 中检查 URL 后再注入。 |
| Java 调 JS | 执行 JS 代码 | webView.evaluateJavascript("jsFunctionName(args)", callback); |
在处理 WebView 和 JavaScript 交互时,安全永远是第一位的,始终采用 @JavascriptInterface 并限制注入 URL 的策略。
