杰瑞科技汇

PhoneGap 如何调用 Java 代码?

  1. Cordova WebView: 你的应用本质上是一个包装在原生 Android WebView 组件中的网页。
  2. JavaScript 接口: Cordova 提供了一个 JavaScript 接口,允许你的网页代码(JS)调用原生功能。
  3. 原生桥接: 当 JS 调用一个特定功能时,Cordova 的桥接机制会捕获这个调用,并将其转发给你编写的原生 Java 代码。
  4. Java 实现: 你在 Android 项目中编写 Java 类,实现具体的功能,并将结果返回给 JavaScript。

下面我将通过一个详细的、分步的示例来演示如何创建一个简单的 Cordova 插件,用于在 Android 上显示一个原生 Toast 消息。

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

核心概念

  • cordova.exec: 这是 JavaScript 端用来调用原生代码的核心函数。

    • cordova.exec(function(winParam) { ... }, function(error) { ... }, "service", "action", ["arg1", "arg2"]);
    • function(winParam): 成功回调函数,接收来自 Java 端的数据。
    • function(error): 失败回调函数,接收错误信息。
    • "service": Java 类的名称(不包含包名)。
    • "action": 你想在 Java 类中调用的方法名。
    • ["arg1", "arg2"]: 传递给 Java 方法的参数数组。
  • CordovaPlugin: 所有 Cordova 插件都必须继承的 Java 基类,它提供了与 Cordova 桥接通信的核心方法。


完整示例:创建一个显示 Toast 的插件

我们将创建一个名为 ToastPlugin 的插件,它允许 JavaScript 调用 showToast(message) 方法,在屏幕上显示一个原生的 Android Toast。

第 1 步:创建 Cordova 项目

如果你还没有项目,请先创建一个。

PhoneGap 如何调用 Java 代码?-图2
(图片来源网络,侵删)
# 创建一个名为 MyToastApp 的 Cordova 项目
cordova create MyToastApp com.example.mytoastapp MyToastApp
# 进入项目目录
cd MyToastApp
# 添加 Android 平台
cordova platform add android

第 2 步:创建插件目录结构

在你的 Cordova 项目根目录下,创建一个 src 文件夹,用于存放插件源代码,然后在 src 下创建 Android 平台特定的目录结构。

MyToastApp/
├── src/
│   └── android/
│       └── com/
│           └── example/
│               └── mytoastapp/
│                   └── ToastPlugin.java  <-- 我们将创建的 Java 文件
├── platforms/
├── plugins/
└── www/

第 3 步:编写 Java 插件代码 (ToastPlugin.java)

src/android/com/example/mytoastapp/ 目录下创建 ToastPlugin.java 文件。

package com.example.mytoastapp;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import android.widget.Toast;
import android.content.Context;
// 1. 继承 CordovaPlugin
public class ToastPlugin extends CordovaPlugin {
    // 2. 重写 execute 方法,这是 JS 调用入口
    @Override
    public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
        // 3. 判断 JS 调用的是哪个 action
        if ("showToast".equals(action)) {
            try {
                // 从 args 数组中获取第一个参数,即要显示的消息
                String message = args.getString(0);
                // 获取 Android 的上下文
                Context context = this.cordova.getActivity().getApplicationContext();
                // 创建并显示 Toast
                Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
                // 调用成功回调,可以传递一个结果(这里是字符串)
                callbackContext.success("Toast shown successfully: " + message);
                return true; // 表示 action 已被成功处理
            } catch (Exception e) {
                // 调用失败回调,传递错误信息
                callbackContext.error("Error showing toast: " + e.getMessage());
                return false;
            }
        }
        // action 不支持,返回 false
        return false;
    }
}

代码解释:

  1. extends CordovaPlugin: 声明这是一个 Cordova 插件。
  2. execute(String action, ...): 这是核心方法,当 JS 通过 cordova.exec 调用时,这个方法会被触发。
    • action: 对应 JS 中指定的 "action" 字符串,这里是 "showToast"
    • args: 对应 JS 中传递的参数数组,这里是 ["Hello from Java!"]
    • callbackContext: 用于将结果或错误返回给 JavaScript。
  3. 我们检查 action 是否为 "showToast",如果是,则执行相应逻辑。
  4. 使用 args.getString(0) 获取第一个参数。
  5. 通过 this.cordova.getActivity().getApplicationContext() 获取应用的 Context,这是显示 Toast 所必需的。
  6. Toast.makeText(...).show(); 是标准的 Android 显示 Toast 的代码。
  7. callbackContext.success(...)callbackContext.error(...) 分别用于通知 JS 调用成功或失败。

第 4 步:注册插件 (plugin.xml)

在项目根目录下创建一个 plugin.xml 文件,这个文件告诉 Cordova 如何安装和使用你的插件。

MyToastApp/
├── plugin.xml  <-- 创建这个文件
├── src/
└── ...

plugin.xml 文件内容:

<?xml version="1.0" encoding="UTF-8"?>
<plugin xmlns="http://www.apache.org/cordova/ns/plugins/1.0"
        id="com.example.mytoastapp.toast-plugin"
        version="1.0.0">
    <!-- 插件的元数据 -->
    <name>Toast Plugin</name>
    <description>A simple plugin to show a native Android Toast from JavaScript.</description>
    <license>MIT</license>
    <keywords>cordova,android,toast</keywords>
    <!-- 定义 JS 模块 -->
    <js-module src="www/toastplugin.js" name="ToastPlugin">
        <merges target="cordova.plugins" />
    </js-module>
    <!-- 定义 Android 平台特定的配置 -->
    <platform name="android">
        <!-- 将 Java 源文件复制到 Android 平台 -->
        <source-file src="src/android/com/example/mytoastapp/ToastPlugin.java" />
        <!-- (可选) 将插件添加到 Android 项目的 build.gradle 依赖中 -->
        <!-- <framework src="src/android/build.gradle" custom="true" type="gradleReference" /> -->
    </platform>
</plugin>

代码解释:

  • <js-module>: 定义了 JavaScript 接口。src 指向 JS 文件(我们下一步创建),name 是 JS 中引用插件的名称。
  • <merges target="cordova.plugins">: 将 JS 模块合并到 cordova.plugins 命名空间下,这样我们就可以通过 cordova.plugins.ToastPlugin 来访问它。
  • <platform name="android">: 指定这是针对 Android 平台的配置。
  • <source-file>: 告诉 Cordova 在安装插件时,将我们的 Java 源文件复制到 Android 项目的 src 目录下。

第 5 步:编写 JavaScript 接口 (www/toastplugin.js)

www 目录下创建 toastplugin.js 文件。

// 将模块挂载到 cordova.plugins 命名空间下
var exec = require('cordova/exec');
var ToastPlugin = {
    /**
     * 显示一个原生 Toast 消息
     * @param {string} message - 要显示的消息
     * @param {function} successCallback - 成功回调
     * @param {function} errorCallback - 失败回调
     */
    showToast: function(message, successCallback, errorCallback) {
        // 调用 cordova.exec
        // 第一个参数是成功回调
        // 第二个参数是失败回调
        // "ToastPlugin" 是 Java 类的名称 (不包含包名)
        // "showToast" 是 Java 类中要调用的方法名
        // [message] 是传递给 Java 方法的参数数组
        exec(successCallback, errorCallback, "ToastPlugin", "showToast", [message]);
    }
};
// 将模块导出
module.exports = ToastPlugin;

第 6 步:在 HTML 中使用插件

我们可以在 www/index.html 中调用我们的插件了。

打开 www/index.html,在 <body> 标签内添加一个按钮和一些用于显示回调信息的元素。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, minimal-ui">
        <title>My Toast App</title>
        <script type="text/javascript" src="cordova.js"></script>
        <script type="text/javascript" src="js/index.js"></script>
    </head>
    <body>
        <h1>Hello World</h1>
        <button id="showToastBtn">Show Toast</button>
        <p id="result"></p>
        <script type="text/javascript">
            document.addEventListener('deviceready', onDeviceReady, false);
            function onDeviceReady() {
                console.log("Device is ready!");
                // 获取按钮元素
                var showToastBtn = document.getElementById('showToastBtn');
                var resultP = document.getElementById('result');
                // 添加点击事件监听器
                showToastBtn.addEventListener('click', function() {
                    // 调用我们编写的插件
                    cordova.plugins.ToastPlugin.showToast(
                        'This is a native Toast from JavaScript!', // 消息内容
                        function(success) { // 成功回调
                            resultP.textContent = "Success: " + success;
                            console.log("Toast success:", success);
                        },
                        function(error) { // 失败回调
                            resultP.textContent = "Error: " + error;
                            console.error("Toast error:", error);
                        }
                    );
                });
            }
        </script>
    </body>
</html>

第 7 步:添加并构建插件

  1. 将插件添加到项目中:在你的项目根目录下运行以下命令,这会读取 plugin.xml 并将插件文件复制到正确的位置。

    cordova plugin add .
  2. 构建项目:将所有文件(包括插件)编译成 Android APK。

    cordova build android
  3. 在模拟器或真机上运行

    cordova run android

当你运行应用并点击 "Show Toast" 按钮时,你应该能看到屏幕上弹出一个原生的 Android Toast 消息,并且页面上会显示 "Success: Toast shown successfully: This is a native Toast from JavaScript!"。


总结与进阶

这个例子涵盖了从零开始创建一个 Cordova 插件的完整流程,关键点在于:

  1. Java 端: 创建一个继承自 CordovaPlugin 的类,在 execute 方法中处理来自 JS 的调用。
  2. JS 端: 使用 cordova.exec 来调用 Java 代码,并定义成功/失败的回调。
  3. plugin.xml: 作为插件的“说明书”,定义了插件的元数据和在不同平台上的文件部署规则。

进阶功能:

  • 传递复杂数据: 你可以在 args 中传递 JSON 对象,Java 端使用 JSONArrayJSONObject 来解析。
  • 异步操作: 如果你的 Java 方法需要执行耗时操作(如网络请求),你应该在后台线程(如 AsyncTaskThread)中执行,并在操作完成后通过 callbackContext 返回结果,而不是阻塞 UI 线程。
  • 处理生命周期: 在 CordovaPlugin 中,你还可以重写 onResume(), onPause(), onDestroy() 等方法来处理应用的生命周期事件。
  • 使用 Gradle 依赖: 如果你的插件需要引入第三方 Android 库,你可以在 plugin.xml 中使用 <framework> 标签来添加 Gradle 依赖。

通过这种方式,你可以将几乎任何 Android 原生功能集成到你的 Cordova 应用中,极大地扩展了 Web 应用的能力边界。

分享:
扫描分享到社交APP
上一篇
下一篇