如何为Windows/macOS平台的Flutter桌面应用添加Java库(.jar文件)
在Flutter桌面(Windows/macOS)中集成Java编写的库
Java库无法直接被Flutter桌面应用调用,核心思路是通过中间桥接层实现Dart与Java代码的通信,以下是针对Windows和macOS平台的具体实现流程:
Windows平台实现步骤
打包Java库为可执行JAR
用Maven Shade或Gradle Shadow插件将Java库及其依赖打包成独立运行的JAR包,确保能通过java -jar your-library.jar直接执行。编写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)); }); }
- 配置项目依赖:添加JDK的头文件路径(
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平台实现步骤
打包Java库为可执行JAR(同Windows步骤)
编写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项目的资源目录中,确保打包时能包含进去。
- 在Flutter的macOS项目中添加Swift代码:
Dart层调用(同Windows的Dart代码)
关键注意事项
- JAR打包需包含所有依赖,避免运行时类缺失;
- Windows平台需保证JVM位数(32/64位)与Flutter编译目标一致;
- 嵌入JVM时需注意内存管理,避免泄漏;
- 跨进程通信建议用JSON序列化复杂参数,确保数据传递一致性;
- macOS若选择嵌入JVM,需处理系统Java版本兼容性问题,推荐用进程调用方式降低复杂度。
内容的提问来源于stack exchange,提问作者Yves Khalil
相关产品推荐
相关产品推荐

