Flutter以模块化适配 HarmonyOS方案的实现步骤

Flutter 以模块化方案 适配 HarmonyOS 的实现方法

Flutter的SDK: https://gitcode.com/openharmony-tpc/flutter_flutter

分支Tag:3.27.5-ohos-0.1.0-beta

DevecoStudio:DevEco Studio 5.1.1 Release

HarmonyOS版本:API18

本文使用的Mac,环境配置步骤不再赘述,参考社区文档!!!

Flutter 应用可以通过与 HarmonyOS 原生代码交互来适配 HarmonyOS 平台。主要涉及 Flutter 端的插件开发和 HarmonyOS 端的原生能力实现。

Flutter 侧代码实现

在 Flutter 中,通过 MethodChannel 与 HarmonyOS 原生代码通信。以下是一个示例:

main.dart

dart 复制代码
void main() => runApp(GetMaterialApp(
      // home: const HomePage(),
      title: "Flutter侧",
      getPages: [
        GetPage(name: "/home", page: () => const HomePage()),
        GetPage(name: "/first", page: () => const FirstPage()), //空页面
      ],
    ));

home_page.dart

dart 复制代码
class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() {
    return _HomePageState();
  }
}

class _HomePageState extends State<HomePage> {
  String deviceTypeName = "";
  String receiveData = "xxxxxx";

  @override
  void initState() {
    super.initState();
    Get.parameters.forEach((key, value) {
      if (key == "receiveData") {
        setState(() {
          receiveData = value!;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    deviceTypeName = Platform.operatingSystem;
    return Scaffold(
      appBar: AppBar(
        title: const Text(
          '适配Android/iOS/HarmonyOS',
          style: TextStyle(fontSize: 20),
        ),
      ),
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            deviceTypeName,
            style: const TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
          ),
          const SizedBox(
            width: double.infinity,
            height: 20,
          ),
          Text('接收来自原生的数据:$receiveData'),
          const SizedBox(
            width: double.infinity,
            height: 20,
          ),
          GestureDetector(
            onTap: () {
              ToastUtil.showToastCenter("Send Native");
              NativeChannel.sendData();
            },
            child: Container(
              width: 120,
              height: 40,
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  color: const Color(0xff08b326),
                  borderRadius: BorderRadius.circular(10)),
              child: const Text(
                "Send Native",
                style: TextStyle(color: Colors.white),
              ),
            ),
          ),
          GestureDetector(
            onTap: () {
              ToastUtil.showToastCenter("Finish Page");
              NativeChannel.finishPage();
            },
            child: Container(
              width: 120,
              height: 40,
              margin: const EdgeInsets.only(top: 10),
              alignment: Alignment.center,
              decoration: BoxDecoration(
                  color: const Color(0xff08b326),
                  borderRadius: BorderRadius.circular(10)),
              child: const Text(
                "Finish Page",
                style: TextStyle(color: Colors.white),
              ),
            ),
          )
        ],
      ),
    );
  }
}

native_channel.dart

dart 复制代码
class NativeChannel {

  //创建通道
  static const _channel = MethodChannel('com.flutter/native_channel');

  ///调用原生方法,关闭原生页面
  static Future<void> finishPage() async {
    await _channel.invokeMethod('finishPage');
  }

  ///调用原生方法,发送flutter数据
  static Future<void> sendData() async {
    await _channel.invokeMethod('sendData', {'data': '我是FLutter传到原生客户端的数据'});
  }
}

HarmonyOS 侧代码实现

在 HarmonyOS 中,需要实现 Ability 来处理 Flutter 的调用。

  1. 创建项目默认创建 EntryAbility
    EntryAbility 类中初始化Flutter管理部分:
java 复制代码
export default class EntryAbility extends UIAbility {

  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
    this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET);
    FlutterManager.getInstance().pushUIAbility(this)
  }

  onDestroy(): void {
    FlutterManager.getInstance().popUIAbility(this)
  }

  onWindowStageCreate(windowStage: window.WindowStage): void {
    hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
    FlutterManager.getInstance().pushWindowStage(this, windowStage);
    windowStage.loadContent('pages/Index', (err) => {
      if (err.code) {
        hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err));
        return;
      }
      hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.');

      let windowClass: window.Window = windowStage.getMainWindowSync(); // 获取应用主窗口
      // 1. 设置窗口全屏
      windowClass.setWindowLayoutFullScreen(true)
      // 2. 设置状态栏和导航条隐藏
      windowClass.setSpecificSystemBarEnabled('status', true)
      let sysBarProps: window.SystemBarProperties = {
        statusBarContentColor: '#000000'  //全局设置状态栏文字颜色
      };
      windowClass.setWindowSystemBarProperties(sysBarProps);

    });
  }

  onWindowStageDestroy(): void {
    FlutterManager.getInstance().popWindowStage(this);
  }

  onForeground(): void {
  }

  onBackground(): void {
  }
}
  1. 实现FlutterPage页面 负责承载FLutter模块的Harmony页面
java 复制代码
@Entry
@Component
struct FlutterViewPage {
  private flutterEntry?: FlutterEntry | null = null;
  private flutterView?: FlutterView;

  aboutToAppear() {
    //跳转至指定路由 ?后面为参数
    let params: Record<string, Object> = {
      "route": "/home?receiveData=HarmonyOS已经诞生5年了"
    }
    this.flutterEntry = new FlutterHomeAbility(getContext(this) as common.UIAbilityContext, params);
    this.flutterEntry.aboutToAppear();
    this.flutterView = this.flutterEntry.getFlutterView();
    this.flutterEntry.addPlugin(new HomePlugin(this.getUIContext()));
  }

  aboutToDisappear() {
    this.flutterEntry?.aboutToDisappear();
  }

  onPageShow() {
    this.flutterEntry?.onPageShow();
  }

  onPageHide() {
    this.flutterEntry?.onPageHide();
  }

  build() {
    RelativeContainer() {
      FlutterPage({ viewId: this.flutterView?.getId() })
        .width('100%')
        .height('100%')
    }
  }
}

class HomePlugin implements FlutterPlugin {
  private channel?: MethodChannel;	//交互通道
  private cxt?: UIContext

  constructor(context: UIContext) {
    this.cxt = context
  }

  getUniqueClassName(): string {
    return HomePlugin.name;
  }
  
  //交互过程
  onAttachedToEngine(binding: FlutterPluginBinding): void {
    this.channel = new MethodChannel(binding.getBinaryMessenger(), "com.flutter/native_channel");
    let context = this.cxt
    this.channel.setMethodCallHandler({
      onMethodCall(call: MethodCall, result: MethodResult) {
        switch (call.method) {
          case "finishPage":
            ToastUtil.showToast("页面关闭");
            context?.getRouter().back()
            break;
          case "sendData":
            ToastUtil.showToast("发送flutter数据:" + call.argument("data"));
            break;
          default:
            result.notImplemented();
            break;
        }
      }
    })
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    this.channel?.setMethodCallHandler(null)
  }
}
  1. 实现Flutter引擎
java 复制代码
export default class FlutterHomeAbility extends FlutterEntry {
  configureFlutterEngine(flutterEngine: FlutterEngine): void {
    super.configureFlutterEngine(flutterEngine);
    GeneratedPluginRegistrant.registerWith(flutterEngine);
  }
}

交互过程

  1. Flutter 调用 HarmonyOS 方法

    • Flutter 通过 MethodChannel 调用 finishPage 方法。
    • HarmonyOS 收到请求后处理信息。
  2. Flutter 向 HarmonyOS 传递参数

    • Flutter 调用 sendData 方法并传递 data 参数。
    • HarmonyOS 解析参数并显示 Toast。
  3. 通信流程

    • Flutter 发送方法名和参数到 HarmonyOS。
    • HarmonyOS 根据方法名执行对应逻辑并返回结果。

注意事项

  • 插件打包
    将 Flutter 代码打包为 Harmony可用的 har 插件,方便调用。
    Flutter打包 har 命令:
java 复制代码
flutter build har --release
//构建结果在 项目根目录/build/ohos/har/release
  • 性能优化

    频繁通信建议使用 EventChannel 替代 MethodChannel 以减少开销。

  • HarmonyOS侧导入har 1、项目根目录下oh-package.json5文件

java 复制代码
{
  "modelVersion": "5.1.1",
  "description": "Please describe the basic information.",
  "dependencies": {

  },
  "overrides": {//导入har包
    "@ohos/flutter_ohos": "file:../../FlutterProject/mobile_flutter_ohos/build/ohos/har/release/flutter_embedding_release.har",
    "flutter_native_arm64_v8a": "file:../../FlutterProject/mobile_flutter_ohos/build/ohos/har/release/arm64_v8a_release.har",
    "@ohos/flutter_module": "file:../../FlutterProject/mobile_flutter_ohos/build/ohos/har/release/flutter_module.har"
  },
  "devDependencies": {
    "@ohos/hypium": "1.0.21",
    "@ohos/hamock": "1.0.0"
  }
}

2、模块entry根目录下oh-package.json5文件

java 复制代码
{
  "name": "entry",
  "version": "1.0.0",
  "description": "Please describe the basic information.",
  "main": "",
  "author": "",
  "license": "",
  "dependencies": {//新增
    "@ohos/flutter_ohos": "file:../../../FlutterProject/mobile_flutter_ohos/build/ohos/har/release/flutter_embedding_release.har",
    "flutter_native_arm64_v8a": "file:../../../FlutterProject/mobile_flutter_ohos/build/ohos/har/release/arm64_v8a_release.har",
    "@ohos/flutter_module": "file:../../../FlutterProject/mobile_flutter_ohos/build/ohos/har/release/flutter_module.har"
  }
}

通过以上方法,Flutter 应用可以无缝适配 HarmonyOS,并调用原生功能。

相关推荐
liulian09166 小时前
Flutter for OpenHarmony 跨平台开发:单位转换功能实战指南
flutter
千码君20167 小时前
Trae:一些关于flutter和 go前后端开发构建的分享
android·flutter·gradle·android-studio·trae·vibe code
maaath8 小时前
【maaath】Flutter for OpenHarmony 手表配饰应用实战开发
flutter·华为·harmonyos
maaath9 小时前
【maaath】Flutter for OpenHarmony 跨平台计算器应用开发实践
flutter·华为·harmonyos
maaath14 小时前
【maaath】Flutter for OpenHarmony 闹钟时钟应用开发实战
flutter·华为·harmonyos
maaath14 小时前
【maaath】Flutter for OpenHarmony 短信管理应用实战
flutter·华为·harmonyos
maaath15 小时前
【maaath】Flutter for OpenHarmony打造跨平台便签备忘录应用
flutter·华为·harmonyos
千码君201615 小时前
flutter:与Android Studio模拟器的调试分享
android·flutter
xmdy586616 小时前
Flutter+开源鸿蒙实战|智联邻里Day8 Lottie动画集成+url_launcher跳转拨号+个人中心完善+全局UI统一
flutter·开源·harmonyos
liulian09161 天前
Flutter for OpenHarmony 跨平台开发:颜色选择器功能实战指南
flutter