杰瑞科技汇

PhoneGap中Java如何调用JS?

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

PhoneGap中Java如何调用JS?-图1
(图片来源网络,侵删)

核心概念

  1. WebView: Android 应用中用于显示网页内容的组件,你的 Cordova 应用就是在一个全屏的 WebView 中运行的。
  2. WebView.addJavascriptInterface(): 这是实现 Java 调用 JS 的核心方法,它允许你将一个 Java 对象“注入”到 WebView 的 JavaScript 上下文中,这样你的 JS 代码就可以像调用普通 JS 对象一样调用这个 Java 对象的方法。
  3. 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 函数。

PhoneGap中Java如何调用JS?-图2
(图片来源网络,侵删)

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,在 onCreateonResume 方法中,将 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
分享:
扫描分享到社交APP
上一篇
下一篇