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
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
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() {return _HomePageState();}
}class _HomePageState extends State<HomePage> {String deviceTypeName = "";String receiveData = "xxxxxx";void initState() {super.initState();Get.parameters.forEach((key, value) {if (key == "receiveData") {setState(() {receiveData = value!;});}});}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
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 的调用。
- 创建项目默认创建
EntryAbility
类
在EntryAbility
类中初始化Flutter管理部分:
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 {}
}
- 实现FlutterPage页面 负责承载FLutter模块的Harmony页面
@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?: UIContextconstructor(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.cxtthis.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)}
}
- 实现Flutter引擎
export default class FlutterHomeAbility extends FlutterEntry {configureFlutterEngine(flutterEngine: FlutterEngine): void {super.configureFlutterEngine(flutterEngine);GeneratedPluginRegistrant.registerWith(flutterEngine);}
}
交互过程
-
Flutter 调用 HarmonyOS 方法
- Flutter 通过
MethodChannel
调用finishPage
方法。 - HarmonyOS 收到请求后处理信息。
- Flutter 通过
-
Flutter 向 HarmonyOS 传递参数
- Flutter 调用
sendData
方法并传递data
参数。 - HarmonyOS 解析参数并显示 Toast。
- Flutter 调用
-
通信流程
- Flutter 发送方法名和参数到 HarmonyOS。
- HarmonyOS 根据方法名执行对应逻辑并返回结果。
注意事项
- 插件打包
将 Flutter 代码打包为 Harmony可用的 har 插件,方便调用。
Flutter打包 har 命令:
flutter build har --release
//构建结果在 项目根目录/build/ohos/har/release
-
性能优化
频繁通信建议使用EventChannel
替代MethodChannel
以减少开销。 -
HarmonyOS侧导入har
1、项目根目录下oh-package.json5
文件
{"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
文件
{"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,并调用原生功能。