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,并調用原生功能。