PhoneGap/Cordova 的本质是一个原生应用(Android 是 Java,iOS 是 Objective-C/Swift),它内嵌了一个 WebView 组件,并加载了你的 web 应用(HTML, CSS, JS),原生代码与 web 代码的通信,就是原生代码与 WebView 的通信。

核心概念
- WebView: Android 应用中用于显示网页内容的组件,你的 Cordova 应用就是在一个全屏的 WebView 中运行的。
WebView.addJavascriptInterface(): 这是实现 Java 调用 JS 的核心方法,它允许你将一个 Java 对象“注入”到 WebView 的 JavaScript 上下文中,这样你的 JS 代码就可以像调用普通 JS 对象一样调用这个 Java 对象的方法。WebView.loadUrl(): 这是实现 JS 调用 Java 的核心方法,你可以让 JS 执行一段任意的 JavaScript 代码字符串,最常用的就是调用一个全局的 JS 函数。
第一部分:Java 调用 JavaScript (Java → JS)
这是你问题的核心,我们通过一个完整的示例来演示。
场景:在 Android Activity 中,当用户点击一个按钮时,调用 JS 中的一个名为 showAlert 的函数,并传递一个参数。
步骤 1:准备你的 Web 代码 (HTML/JS)
在你的 assets/www 目录下,创建一个 index.html 文件,其中包含一个将被 Java 调用的 JS 函数。
assets/www/index.html
<!DOCTYPE html>
<html>
<head>Java Call JS Demo</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
</head>
<body>
<h1>Hello from Web View!</h1>
<p>Check the Android log for messages from Java.</p>
<script type="text/javascript">
// 这是一个全局函数,将被 Java 代码调用
function showAlert(message) {
alert('Message from Java: ' + message);
console.log('Java called showAlert with message: ' + message);
}
// 另一个带返回值的函数
function getGreeting(name) {
return 'Hello, ' + name + ' from JS!';
}
</script>
</body>
</html>
步骤 2:修改你的 Cordova Activity (Java 代码)
我们需要在你的主 Activity(通常是 MainActivity.java)中编写 Java 代码来调用这个 JS 函数。

app/src/main/java/com/yourpackage/MainActivity.java
package com.yourpackage;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import org.apache.cordova.CordovaActivity;
public class MainActivity extends CordovaActivity {
private static final String TAG = "MainActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 加载 cordovaWebView,这是 Cordova 的标准设置
loadUrl(launchUrl);
// 获取布局中的按钮并设置点击事件
// 注意:你需要先在 activity_main.xml 中添加一个按钮
Button callJsButton = findViewById(R.id.call_js_button);
if (callJsButton != null) {
callJsButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callJavaScriptFunction();
}
});
}
}
private void callJavaScriptFunction() {
// 方法一:调用一个无返回值的JS函数
// 使用 loadUrl 执行一段 JS 代码
// "javascript:" 是必须的前缀
String jsFunctionToCall = "javascript:showAlert('Hello from Java!')";
cordova.getWebView().loadUrl(jsFunctionToCall);
Log.d(TAG, "Called showAlert JS function.");
// 方法二:调用一个有返回值的JS函数
// 注意:loadUrl 是异步的,不能直接获取返回值。
// 如果需要返回值,通常需要通过 addJavascriptInterface 注入一个回调接口。
// 这里我们只是演示调用,不处理返回值。
String jsFunctionWithReturn = "javascript:getGreeting('Cordova')";
cordova.getWebView().loadUrl(jsFunctionWithReturn);
Log.d(TAG, "Called getGreeting JS function.");
}
}
重要提示:
cordova.getWebView(): 这是获取 Cordova 内部使用的 WebView 实例的正确方式。javascript:: 在调用loadUrl时,这个前缀是必须的,它告诉 WebView 这不是要加载的 URL,而是要执行的 JavaScript 代码。- 异步性:
loadUrl是异步执行的,你不能在callJavaScriptFunction()方法中立即获取getGreeting的返回值,如果需要处理返回值,需要更复杂的机制,例如通过addJavascriptInterface注入一个回调对象。
第二部分:JavaScript 调用 Java (JS → Java)
虽然你的问题是 Java 调 JS,但理解 JS 如何调 Java 对于完整的双向通信至关重要,这通常是通过 addJavascriptInterface 实现的。
场景:在 Web 页面中点击一个按钮,调用 Android 的原生代码来震动手机。
步骤 1:创建一个 Java 接口类
这个类定义了可以被 JS 调用的方法。
app/src/main/java/com/yourpackage/WebAppInterface.java
package com.yourpackage;
import android.content.Context;
import android.os.Vibrator;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginManager;
import android.util.Log;
// 注意:从 Android 4.2 (API 17) 开始,必须为被注入的类添加 @JavascriptInterface 注解
public class WebAppInterface {
private Context mContext;
private static final String TAG = "WebAppInterface";
public WebAppInterface(Context c) {
mContext = c;
}
// @JavascriptInterface 注解是必须的!
@JavascriptInterface
public void vibrate(long milliseconds) {
Log.d(TAG, "JS is requesting vibrate for " + milliseconds + "ms.");
Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
if (v != null && v.hasVibrator()) {
v.vibrate(milliseconds);
}
}
}
步骤 2:在 Activity 中注入这个接口
修改你的 MainActivity.java,在 onCreate 或 onResume 方法中,将 WebAppInterface 实例注入到 WebView 中。
app/src/main/java/com/yourpackage/MainActivity.java (修改部分)
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadUrl(launchUrl);
// ... 按钮的代码 ...
// 将 WebAppInterface 注入到 WebView 中
// 参数1: 我们的接口对象实例
// 参数2: 在JS中可以访问的对象名称,这里是 "Android"
cordova.getWebView().addJavascriptInterface(new WebAppInterface(this), "Android");
}
步骤 3:在 Web 代码中调用 Java 方法
你可以在 JavaScript 中通过 Android 这个对象来调用 vibrate 方法了。
assets/www/index.html (修改部分)
<!DOCTYPE html>
<html>
<head>
<!-- ... head 内容 ... -->
<style>
button { padding: 10px; font-size: 16px; }
</style>
</head>
<body>
<h1>Hello from Web View!</h1>
<p>Check the Android log for messages from Java.</p>
<button id="java-call-js-btn">Call JS from Java</button>
<br /><br />
<button id="js-call-java-btn">Call Java (Vibrate) from JS</button>
<script type="text/javascript">
function showAlert(message) {
alert('Message from Java: ' + message);
console.log('Java called showAlert with message: ' + message);
}
function getGreeting(name) {
return 'Hello, ' + name + ' from JS!';
}
// 等待 DOM 加载完成
document.addEventListener('DOMContentLoaded', function() {
// 绑定按钮点击事件
document.getElementById('java-call-js-btn').addEventListener('click', function() {
// 这个按钮是用来测试 Java 调 JS 的,所以这里我们直接调用 JS 函数
showAlert('Button clicked in JS!');
});
document.getElementById('js-call-java-btn').addEventListener('click', function() {
// 通过 "Android" 这个对象名调用 Java 的 vibrate 方法
// 这个 "Android" 是我们在 addJavascriptInterface 中设置的
if (typeof Android !== 'undefined' && Android.vibrate) {
Android.vibrate(200); // 震动200毫秒
console.log('Called Android.vibrate(200) from JS.');
} else {
console.error('Android interface 