You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Windows/macOS平台的Flutter桌面应用添加Java库(.jar文件)

在Flutter桌面(Windows/macOS)中集成Java编写的库

Java库无法直接被Flutter桌面应用调用,核心思路是通过中间桥接层实现Dart与Java代码的通信,以下是针对Windows和macOS平台的具体实现流程:

Windows平台实现步骤

  1. 打包Java库为可执行JAR
    用Maven Shade或Gradle Shadow插件将Java库及其依赖打包成独立运行的JAR包,确保能通过java -jar your-library.jar直接执行。

  2. 编写Windows端桥接代码(嵌入JVM方式)
    在Flutter的Windows项目中,通过C++嵌入JVM来调用Java方法,再通过MethodChannel与Dart层通信:

    • 配置项目依赖:添加JDK的头文件路径(%JAVA_HOME%\include、%JAVA_HOME%\include\win32)和库文件路径(%JAVA_HOME%\lib)
    • 初始化JVM并调用Java方法,示例代码片段:
      #include <jni.h>
      #include <flutter/method_channel.h>
      #include <flutter/plugin_registrar_windows.h>
      
      JavaVM* jvm;
      JNIEnv* env;
      
      // 初始化JVM
      bool InitJVM() {
          JavaVMInitArgs args;
          JavaVMOption options[1];
          options[0].optionString = "-Djava.class.path=./your-library.jar"; // JAR路径
          args.version = JNI_VERSION_1_8;
          args.nOptions = 1;
          args.options = options;
          args.ignoreUnrecognized = JNI_FALSE;
          return JNI_CreateJavaVM(&jvm, (void**)&env, &args) == JNI_OK;
      }
      
      // 处理Dart调用
      void HandleMethodCall(const flutter::MethodCall<>& call,
                            std::unique_ptr<flutter::MethodResult<>> result) {
          if (call.method_name() == "callJavaMethod") {
              if (!InitJVM()) {
                  result->Error("JVM_INIT_FAILED", "Failed to initialize JVM");
                  return;
              }
              // 加载Java类并调用方法
              jclass cls = env->FindClass("com/your/package/YourClass");
              jmethodID method = env->GetStaticMethodID(cls, "yourMethod", "(Ljava/lang/String;)Ljava/lang/String;");
              auto input = std::get<std::string>(*call.arguments());
              jstring jInput = env->NewStringUTF(input.c_str());
              jstring jOutput = (jstring)env->CallStaticObjectMethod(cls, method, jInput);
              const char* output = env->GetStringUTFChars(jOutput, nullptr);
              result->Success(output);
              env->ReleaseStringUTFChars(jOutput, output);
          } else {
              result->NotImplemented();
          }
      }
      
      // 注册MethodChannel
      void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar) {
          auto channel =
              std::make_unique<flutter::MethodChannel<>>(
                  registrar->messenger(), "java_library_channel",
                  &flutter::StandardMethodCodec::GetInstance());
          channel->SetMethodCallHandler(
              [](const auto& call, auto result) {
                  HandleMethodCall(call, std::move(result));
              });
      }
      
  3. Dart层调用
    在Dart中通过MethodChannel发送指令并接收结果:

    import 'package:flutter/services.dart';
    
    class JavaLibrary {
      static const MethodChannel _channel = MethodChannel('java_library_channel');
    
      static Future<String?> callMethod(String input) async {
        try {
          return await _channel.invokeMethod('callJavaMethod', input);
        } on PlatformException catch (e) {
          print('Error: ${e.message}');
          return null;
        }
      }
    }
    

macOS平台实现步骤

  1. 打包Java库为可执行JAR(同Windows步骤)

  2. 编写macOS端桥接代码(进程调用方式,更简单)
    通过Swift启动Java进程,利用标准输入输出传递数据,再通过MethodChannel对接Dart:

    • 在Flutter的macOS项目中添加Swift代码:
      import Flutter
      import Foundation
      
      public class JavaLibraryPlugin: NSObject, FlutterPlugin {
        public static func register(with registrar: FlutterPluginRegistrar) {
          let channel = FlutterMethodChannel(name: "java_library_channel", binaryMessenger: registrar.messenger())
          let instance = JavaLibraryPlugin()
          registrar.addMethodCallDelegate(instance, channel: channel)
        }
      
        public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
          if call.method == "callJavaMethod" {
            guard let input = call.arguments as? String else {
              result(FlutterError(code: "INVALID_ARG", message: "Invalid input", details: nil))
              return
            }
            self.callJavaJar(input: input) { output in
              result(output)
            }
          } else {
            result(FlutterMethodNotImplemented)
          }
        }
      
        private func callJavaJar(input: String, completion: @escaping (String?) -> Void) {
          let process = Process()
          process.executableURL = URL(fileURLWithPath: "/usr/bin/java")
          process.arguments = ["-jar", Bundle.main.path(forResource: "your-library", ofType: "jar")!, input]
      
          let pipe = Pipe()
          process.standardOutput = pipe
          process.standardError = pipe
      
          let fileHandle = pipe.fileHandleForReading
          fileHandle.readabilityHandler = { handle in
            let data = handle.availableData
            if let output = String(data: data, encoding: .utf8) {
              completion(output.trimmingCharacters(in: .whitespacesAndNewlines))
            } else {
              completion(nil)
            }
            handle.readabilityHandler = nil
          }
      
          do {
            try process.run()
          } catch {
            completion(nil)
          }
        }
      }
      
    • 将打包好的JAR文件添加到macOS项目的资源目录中,确保打包时能包含进去。
  3. Dart层调用(同Windows的Dart代码)

关键注意事项

  • JAR打包需包含所有依赖,避免运行时类缺失;
  • Windows平台需保证JVM位数(32/64位)与Flutter编译目标一致;
  • 嵌入JVM时需注意内存管理,避免泄漏;
  • 跨进程通信建议用JSON序列化复杂参数,确保数据传递一致性;
  • macOS若选择嵌入JVM,需处理系统Java版本兼容性问题,推荐用进程调用方式降低复杂度。

内容的提问来源于stack exchange,提问作者Yves Khalil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 01:15:33