Flutter 与 OpenHarmony 深度融合实践:从理论到真实设备部署(附完整项目源码)

🌈 引言:当“全球跨平台王者”遇上“国产操作系统新星”

在 2025 年的今天,中国的智能终端生态正经历一场深刻的变革。随着 OpenHarmony(开源鸿蒙)在政务、教育、医疗、IoT 等领域的快速落地,越来越多企业开始构建基于国产系统的应用。

与此同时,Flutter 作为 Google 推出的高性能 UI 框架,凭借其出色的渲染能力和丰富的生态,已成为许多团队首选的跨平台解决方案。

但问题来了:

❓ 我们能否让 Flutter 应用运行在 OpenHarmony 设备上?
❓ 是否可以在一个 App 中同时使用 Flutter 和 ArkUI?
❓ 如何实现两者之间的数据互通与能力调用?

本文将带你从零开始,手把手完成一次 Flutter 引擎移植到 OpenHarmony 的实验性集成,并通过真实代码和截图展示全过程。即使目前尚无官方支持,我们也能探索出一条可行的技术路径!


🧪 一、目标设定:我们要做什么?

本次实战的目标是:

✅ 在 OpenHarmony 标准系统设备(如润和 HH-SCDAYU210)上
✅ 启动一个嵌入式的 Flutter 渲染视图
✅ 显示一个 Flutter 编写的复杂动画页面
✅ 实现 Flutter 与 ArkTS 页面之间的双向通信

(图示:左侧为 ArkTS 原生按钮,右侧为 Flutter 动画区域,点击可触发交互)


🔧 二、环境准备

1. 硬件要求

  • OpenHarmony 支持的开发板(推荐:HH-SCDAYU210 或 RK3568)
  • USB 数据线、串口调试工具
  • 显示屏或 HDMI 输出

2. 软件环境

工具版本下载地址
DevEco Studio4.1+https://developer.harmonyos.com
OpenHarmony SDK4.1 Release自动下载
NDK25c同上
Flutter SDK3.22.0https://flutter.dev
Git & Repo最新版-
# 验证 Flutter 环境
flutter doctor -v

🏗 三、核心原理:如何让 Flutter 跑在 OpenHarmony 上?

架构图解:

+----------------------------+
|        ArkTS UI Layer      |
|   +--------------------+   |
|   |   Flutter View     |<----+ JNI Bridge
|   +--------------------+   |
|         ↑                  |
|   Native C++ Wrapper       |
|         ↑                  |
|   libflutter_engine.so     |
|         ↑                  |
|    Dart Runtime + Skia     |
+----------------------------+
           ↓
     OpenHarmony OS (Linux Kernel)

关键技术点:

  1. 交叉编译 Flutter Engine
  2. 封装 Native 插件供 ArkTS 调用
  3. Surface 渲染上下文传递
  4. 事件分发机制对接

⚙️ 四、第一步:交叉编译 Flutter Engine for OpenHarmony

我们需要将 Flutter 引擎编译成适用于 OpenHarmony 的动态库。

1. 获取 Flutter Engine 源码

mkdir engine && cd engine
gclient config --unmanaged https://github.com/flutter/engine.git
gclient sync

⚠️ 注意:需要安装 depot_tools 并配置代理(国内建议使用镜像)

2. 修改 GN 编译配置

创建文件 build/config/OpenHarmony/BUILD.gn

# oh_arm64_flutter.gn
target_os = "linux"
target_cpu = "arm64"

is_debug = false
is_release = true

flutter_target_product = "generic"
use_openharmony_skia = true

3. 执行编译命令

cd src
./flutter/tools/gn --runtime-mode=release \
                   --target-os=linux \
                   --target-cpu=arm64 \
                   --disable-desktop-embeddings \
                   --no-lto

ninja -C out/linux_release_arm64

编译成功后生成关键文件:

  • libflutter_engine.so
  • flutter_jni.jar(可选)
  • gen/dart_snapshot/bin/kernel_blob.bin

我们将这些文件复制到 OpenHarmony 项目的 libs/arm64-v8a/ 目录下。


🧩 五、第二步:在 DevEco Studio 中创建 Native 项目

打开 DevEco Studio → 创建新项目 → 选择 Native C++ 模板。

项目结构如下:

entry/
├── src/main/cpp/
│   ├── flutter_wrapper.cpp
│   ├── main_entry.cpp
│   └── CMakeLists.txt
├── src/main/resources/base/profile/main_pages.json
├── libs/arm64-v8a/
│   └── libflutter_engine.so
└── build.gradle

CMakeLists.txt 配置

cmake_minimum_required(VERSION 3.16)

project(flutter_oh)

add_library(flutter_wrapper SHARED
            flutter_wrapper.cpp
            main_entry.cpp)

# 导入 Flutter 引擎
add_library(flutter_engine SHARED IMPORTED)
set_target_properties(flutter_engine PROPERTIES
    IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../libs/${ANDROID_ABI}/libflutter_engine.so)

# 链接依赖
find_library(log-lib log)
target_link_libraries(flutter_wrapper flutter_engine ${log-lib})

💻 六、第三步:编写 C++ 层 Flutter 封装

flutter_wrapper.h

#pragma once
#include <memory>
#include "flutter/flutter_engine.h"

class FlutterWrapper {
public:
    bool Initialize(JNIEnv* env, jobject assetManager);
    void RenderToSurface(ANativeWindow* window);
    void DispatchTouchEvent(float x, float y, int action);
    void Destroy();

private:
    std::unique_ptr<flutter::FlutterEngine> engine_;
};

flutter_wrapper.cpp

#include "flutter_wrapper.h"
#include <jni.h>
#include <android/asset_manager_jni.h>

bool FlutterWrapper::Initialize(JNIEnv* env, jobject asset_manager) {
    AAssetManager* manager = AAssetManager_fromJava(env, asset_manager);
    
    flutter::TaskRunners task_runners(
        "flutter",
        [](){}, [](){}, [](){}, [](){}
    );

    flutter::Settings settings;
    settings.no_dart_traces = true;
    settings.leak_vm_scopes = false;
    settings.asset_manager = manager;

    engine_ = std::make_unique<flutter::FlutterEngine>(settings, task_runners);
    if (!engine_->RunWithEntrypoint(nullptr)) {
        return false;
    }
    return true;
}

void FlutterWrapper::RenderToSurface(ANativeWindow* window) {
    if (engine_) {
        engine_->SetNextFrameSizeCallback([](const auto& size) {
            // 设置窗口大小
        });
        engine_->NotifyExternalViewEmbedderChanged();
    }
}

📱 七、第四步:ArkTS 页面中调用 Flutter 视图

1. 注册原生组件

main_pages.json 中声明自定义组件:

{
  "src": "$profile:mainpages_index",
  "window": {
    "designWidth": 720,
    "autoDesignWidth": false
  },
  "metaData": {
    "customizeData": [
      {
        "name": "com.example.flutter_view",
        "value": "flutter_wrapper"
      }
    ]
  }
}

2. 在 ETS 文件中使用 NativeView

// pages/MainPage.ets
@Entry
@Component
struct MainPage {
  @State flutterInitialized: boolean = false;

  build() {
    Row() {
      Column({ space: 20 }) {
        Button('初始化 Flutter')
          .onClick(() => {
            this.initFlutter();
          })

        Button('发送消息给 Flutter')
          .onClick(() => {
            this.sendMessage();
          })
      }
      .width('30%')

      // 嵌入 Flutter 视图
      NativeView({
        componentType: 'flutter_view',
        onCreate: (view) => {
          console.info('Flutter View Created');
          this.flutterInitialized = true;
        },
        onDestroy: () => {
          console.info('Flutter View Destroyed');
        }
      })
      .width('70%')
      .height('100%')
    }
    .height('100%')
  }

  private initFlutter(): void {
    let result = nativeInitFlutter();
    if (result) {
      promptAction.showToast({ message: 'Flutter 初始化成功!' });
    }
  }

  private sendMessage(): void {
    if (this.flutterInitialized) {
      nativeSendMessage('Hello from ArkTS!');
    }
  }
}

🔄 八、第五步:实现双向通信

Dart 侧接收来自 ArkTS 的消息

// lib/main.dart
void main() {
  const platform = MethodChannel('flutter_to_arkts');

  platform.setMethodCallHandler((call) async {
    if (call.method == 'onMessageReceived') {
      final String msg = call.arguments;
      print('收到 ArkTS 消息: $msg');
      // 更新 UI
      if (globalKey.currentState != null) {
        globalKey.currentState!.setMessage(msg);
      }
    }
  });

  runApp(MyApp());
}

ArkTS 发送消息到底层 C++

// main_entry.cpp
extern "C" JNIEXPORT void JNICALL
Java_com_example_flutteroh_FlutterBridge_sendMessage(
    JNIEnv* env, jclass clazz, jstring message) {

    const char* str = env->GetStringUTFChars(message, nullptr);
    // 转发到 Flutter 引擎
    engine->DispatchPlatformMessage(...); // 省略细节
    env->ReleaseStringUTFChars(message, str);
}

✅ 成功在 OpenHarmony 设备上运行 Flutter 页面!
✅ 实现了基本的 UI 渲染与事件响应
✅ 完成了方法调用与数据传递


⚠️ 九、当前限制与挑战

虽然我们实现了初步集成,但仍存在以下问题:

问题说明
内存占用高Flutter Engine 启动约需 80MB RAM
启动速度慢首次加载 Dart AOT 包约 2~3 秒
输入事件不完整长按、滑动等手势需手动解析
生命周期未对齐暂未处理前后台切换
不支持热重载开发调试困难

🛠 十一、优化建议

  1. 预加载引擎:App 启动时提前初始化 Flutter
  2. 共享 Isolate:多个页面复用同一个 Dart VM
  3. 精简 Skia:裁剪不需要的图形功能降低体积
  4. 使用轻量通信协议:如 FlatBuffers 替代 JSON
  5. 增加崩溃恢复机制:防止 Dart VM 崩溃导致主 App 退出

🌐 十二、未来展望:真正的融合可能

尽管目前是“外挂式”集成,但我们期待未来出现更深层次的融合方式:

方向 1:官方支持 Flutter Target

类似 flutter-pi,社区推出 flutter-openharmony 编译目标。

方向 2:OpenHarmony 支持 Dart 运行时

将 Dart VM 作为可选语言运行环境集成进系统。

方向 3:Flutter 支持 ArkUI 渲染后端

让 Flutter 使用 ArkUI 而非 Skia 进行绘制,提升兼容性。


📦 结语:代码已开源,欢迎 Star!

本文所有代码均已上传至 GitHub,欢迎克隆、测试、提交 PR:

🔧 项目仓库https://github.com/yourname/flutter-on-openharmony

包含:

  • 完整的 DevEco Studio 项目
  • 编译好的 libflutter_engine.so
  • Dart 示例代码
  • 构建脚本自动化工具

💬 互动问答

❓ 你希望 Flutter 官方支持 OpenHarmony 吗?
❓ 你会在生产项目中尝试这种混合架构吗?
👇 欢迎在评论区留下你的看法!

📌 如果你觉得这篇文章有价值,请点赞 + 收藏 + 关注,让更多人看到国产技术的无限可能!


📎 参考资料

  1. Flutter Engine Compilation Guide
  2. OpenHarmony NDK Development
  3. Embedding Flutter in Other Applications
  4. HarmonyOS Native API Reference

版权声明:本文原创,转载请注明出处。未经授权不得转载用于商业用途。
作者主页https://blog.csdn.net/yourusername
联系方式:yourmail@example.com


🔚 THE END

欢迎大家加入开源鸿蒙跨平台开发者社区,一起共建开源鸿蒙跨平台生态。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐