HarmonyOS鸿蒙Next中Flutter调用鸿蒙的方法简单,鸿蒙调用Flutter的方法该怎么写?

HarmonyOS鸿蒙Next中Flutter调用鸿蒙的方法简单,鸿蒙调用Flutter的方法该怎么写? 鸿蒙调用flutter端的方法该怎么写?最好给个demo,谢谢各位大佬

5 回复

【背景知识】

  • MethodChannel:Flutter中用于实现与HarmonyOS平台之间跨平台通信的机制。
  • OhosView:PlatformView组件在HarmonyOS平台上的具体实现,用于在Flutter应用中嵌入ArkTS组件和调用ArkTS能力。

【解决方案】

与其它平台类似,可以参考文档:如何使用Flutter与OpenHarmony通信 FlutterChannel

具体使用可以参考以下示例代码:

main.dart:

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Channel Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const Scaffold(
        body: PluginPage(),
      ),
    );
  }
}

class PluginPage extends StatefulWidget {
  const PluginPage({super.key});

  @override
  State<PluginPage> createState() => _PluginPageState();
}

class _PluginPageState extends State<PluginPage> {
  String message = "";
  final _channelFlutter = const MethodChannel('samples.flutter.dev/arktsflutterchannel');
  final _platform = const MethodChannel('samples.flutter.dev/battery');
  final _eventChannel = const EventChannel('samples.flutter.dev/event_channel');
      
  int count = 0;

  @override
  void initState() {
    _channelFlutter.setMethodCallHandler(flutterMethod);
    super.initState();
    _initListener();
  }

  _initListener() {
    _eventChannel.receiveBroadcastStream().listen((event) {
      setState(() {
        message = "EventChannel event=$event";
      });
    });
  }
  

  Future<void> _getBatteryLevel() async {
    String batteryLevel;
    try {
      // 调用需要在平台中实现的方法
      final result = await _platform.invokeMethod<int>('getBatteryLevel');
      batteryLevel = 'Battery level at $result % .';
    } on PlatformException catch (e) {
      batteryLevel = "Failed to get battery level: '${e.message}'.";
    }

    setState(() {
      message = batteryLevel;
    });
  }

  Future<void> flutterMethod(MethodCall methodCall) async {
    switch (methodCall.method) {
      case 'seedMessage':
        setState(() {
          message = methodCall.arguments as String;
        });
        break;
      default:  
    } 
  }

  _testStreamCall() async {
    try {
      await _platform.invokeMethod('callEvent');
    } on PlatformException catch (e) {
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(message),
          ElevatedButton(
            onPressed: () => _getBatteryLevel(),
            child: const Text("getBatteryLevel1"),
          ),
          ElevatedButton(
            onPressed: () => _testStreamCall(),
            child: const Text("_testStreamCall"),
          ),
        ],
      ),
    );
  }
}

EntryAbility.ets:

import { FlutterAbility, FlutterEngine } from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';
import { FlutterChannelPlugin } from './FlutterChannelPlugin';

export default class EntryAbility extends FlutterAbility {
  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    GeneratedPluginRegistrant.registerWith(flutterEngine)
    this.addPlugin(new FlutterChannelPlugin())
  }
}

FlutterChannelPlugin.ets:

import {
  Any,
  EventChannel,
  FlutterPlugin,
  FlutterPluginBinding,
  MethodCall,
  MethodChannel,
  MethodResult
} from "@ohos/flutter_ohos";
import { EventSink } from '@ohos/flutter_ohos/src/main/ets/plugin/common/EventChannel';
import { batteryInfo } from "@kit.BasicServicesKit";

export class FlutterChannelPlugin implements FlutterPlugin {
  private methodChannel?: MethodChannel;
  private channel?: MethodChannel;
  private eventChannel?: EventChannel;
  private eventSink?: EventSink;
  private api = new BatteryApi();

  getUniqueClassName(): string {
    return 'FlutterChannelPlugin';
  }

  onAttachedToEngine(binding: FlutterPluginBinding): void {
    // 创建MethodChannel实例
    this.channel = new MethodChannel(binding.getBinaryMessenger(), "samples.flutter.dev/battery");
    // 通过AppStorage保存BinaryMessenger
    AppStorage.setOrCreate('binding', binding.getBinaryMessenger())
    let that = this;
    this.channel.setMethodCallHandler({
      onMethodCall(call: MethodCall, result: MethodResult) {
        switch (call.method) {
          case "getBatteryLevel":
            that.api.getBatteryLevel(result);
            break;
          case "callEvent":
            that.eventSink?.success("Success at " + new Date());
            break;
          default:
            result.notImplemented();
            break;
        }
      }
    })
    this.eventChannel = new EventChannel(binding.getBinaryMessenger(), "samples.flutter.dev/event_channel");
    this.eventChannel.setStreamHandler({
      onListen(args: Any, events: EventSink): void {
        that.eventSink = events;
      },
      onCancel(args: Any): void {
        that.eventSink = undefined;
      }
    });
  }

  onDetachedFromEngine(binding: FlutterPluginBinding): void {
    this.channel?.setMethodCallHandler(null);
    this.methodChannel?.setMethodCallHandler(null);
    this.eventChannel?.setStreamHandler(null);
  }
}

class BatteryApi {
  getBatteryLevel(result: MethodResult) {
    let level: number = batteryInfo.batterySOC;
    let wrapped: Map<String, Any> = new Map<String, Any>();
    if (level >= 0) {
      result.success(level);
    } else {
      wrapped.set("UNAVAILABLE", "Battery level not available.");
      result.error("UNAVAILABLE", "Battery level not available.", null)
    }
  }
}

Index.ets:

import common from '@ohos.app.ability.common';
import { BinaryMessenger, FlutterPage, MethodChannel } from '@ohos/flutter_ohos'

let storage = LocalStorage.getShared()
const EVENT_BACK_PRESS = 'EVENT_BACK_PRESS'

@Entry(storage)
@Component
struct Index {
  private context = this.getUIContext().getHostContext() as common.UIAbilityContext
  @LocalStorageLink('viewId') viewId: string = "";

  build() {
    Column() {
      Button('测试ArkTS侧发送数据给Flutter')
        .onClick(() => {
          let binding: BinaryMessenger = AppStorage.get('binding') as BinaryMessenger
          if (binding) {
            let methodChannel = new MethodChannel(binding, `samples.flutter.dev/arktsflutterchannel`);
            // 向Dart侧发送消息
            if (methodChannel) {
              methodChannel.invokeMethod('seedMessage', '测试发送信息');
            }
          }
        })
        .margin({
          top: '50vp'
        })
      FlutterPage({ viewId: this.viewId })
        .height('80%')
    }
  }

  onBackPress(): boolean {
    this.context.eventHub.emit(EVENT_BACK_PRESS)
    return true
  }
}

更多关于HarmonyOS鸿蒙Next中Flutter调用鸿蒙的方法简单,鸿蒙调用Flutter的方法该怎么写?的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


一样的methodChannel 啊

能写个demo么?

在HarmonyOS Next中,鸿蒙调用Flutter可通过ArkTS的FFI机制实现。具体步骤为:在ArkTS侧使用import引入Flutter模块的Native API接口,通过NativeAPI对象直接调用Flutter层暴露的方法。Flutter侧需通过MethodChannelFFI绑定对应的Native函数,确保方法签名与鸿蒙端一致。调用过程无需额外桥接层,直接通过系统级交互完成通信。

在HarmonyOS Next中,鸿蒙调用Flutter方法可通过MethodChannel实现反向通信。以下是实现步骤和示例:

1. Flutter端设置MethodChannel:

// 在Flutter中创建MethodChannel并设置方法处理器
MethodChannel _channel = MethodChannel('com.example/bridge');

// 设置方法调用处理器
_channel.setMethodCallHandler((MethodCall call) async {
  switch (call.method) {
    case 'getDataFromHarmony':
      return 'Data from Flutter';
    default:
      throw MissingPluginException();
  }
});

2. HarmonyOS端调用Flutter方法:

// 创建MethodChannel
MethodChannel channel = new MethodChannel(ability, "com.example/bridge");

// 调用Flutter方法
channel.invokeMethod("getDataFromHarmony", null, new MethodChannel.Result() {
  @Override
  public void success(Object data) {
    // 处理Flutter返回的数据
    HiLog.info(LABEL, "Received: %{public}s", data.toString());
  }
  
  @Override
  public void error(String errorCode, String errorMsg, Object data) {
    // 错误处理
  }
  
  @Override
  public void notImplemented() {
    // 方法未实现
  }
});

关键点说明:

  • 两端Channel名称必须一致(示例中为com.example/bridge
  • Flutter端通过setMethodCallHandler注册方法
  • HarmonyOS端使用invokeMethod调用对应方法
  • 支持参数传递和返回值处理

这种方式实现了鸿蒙原生代码对Flutter功能的调用,可用于数据获取、状态通知等场景。

回到顶部