Flutter跨平台FlutterChannel鸿蒙化通信指南
·

一、FlutterChannel介绍
FlutterChannel是Flutter与OpenHarmony原生层之间进行通信的核心机制,它提供了三种不同类型的通信通道,满足各种跨平台通信需求。通过FlutterChannel,开发者可以在Flutter代码中调用OpenHarmony原生API,也可以在原生代码中触发Flutter端的回调。
三种通信通道
- MethodChannel:用于方法调用,支持Flutter和原生之间的双向方法调用
- BasicMessageChannel:用于基本消息传递,支持字符串、二进制等数据的双向传递
- EventChannel:用于事件流通信,支持原生向Flutter发送事件通知
二、环境准备
在开始使用FlutterChannel前,请确保已完成以下环境配置:
1. 基础开发环境
- DevEco Studio:4.0及以上版本
- JDK:17.0及以上版本
- Flutter SDK:OpenHarmony适配版本
- Node.js:16.0及以上版本
2. 环境变量配置
# 设置Flutter包管理镜像
export PUB_HOSTED_URL=https://mirrors.huaweicloud.com/repository/flutter/
export FLUTTER_STORAGE_BASE_URL=https://mirrors.huaweicloud.com/repository/flutter/
# 添加Flutter和OpenHarmony工具到PATH
export PATH=/path/to/flutter_flutter/bin:$PATH
export PATH=/path/to/ohos/tools:$PATH
3. 验证环境
# 验证Flutter版本
flutter --version
# 验证OpenHarmony环境
hdc version
三、MethodChannel使用方法
MethodChannel用于Flutter与OpenHarmony之间的方法调用,支持双向通信。
1. Flutter端实现
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class BatteryLevelPage extends StatefulWidget {
const BatteryLevelPage({Key? key}) : super(key: key);
State<BatteryLevelPage> createState() => _BatteryLevelPageState();
}
class _BatteryLevelPageState extends State<BatteryLevelPage> {
// 创建MethodChannel实例,指定通道名称
final _methodChannel = const MethodChannel('samples.flutter.dev/battery');
int? _batteryLevel;
String _error = '';
// 调用原生方法获取电池电量
Future<void> _getBatteryLevel() async {
try {
final int result = await _methodChannel.invokeMethod<int>('getBatteryLevel') ?? 0;
setState(() {
_batteryLevel = result;
_error = '';
});
} on PlatformException catch (e) {
setState(() {
_error = 'Failed to get battery level: ${e.message}';
});
}
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Battery Level'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _getBatteryLevel,
child: const Text('Get Battery Level'),
),
const SizedBox(height: 20),
if (_batteryLevel != null)
Text('Battery Level: $_batteryLevel%'),
if (_error.isNotEmpty)
Text('Error: $_error', style: const TextStyle(color: Colors.red)),
],
),
),
);
}
}
2. OpenHarmony端实现
import { FlutterPlugin, FlutterPluginBinding, MethodChannel, MethodCall, MethodResult } from '@ohos/flutter_ohos';
import batteryInfo from '@ohos.batteryInfo';
export default class BatteryPlugin extends FlutterPlugin {
private channel: MethodChannel | null = null;
onAttachedToEngine(binding: FlutterPluginBinding): void {
// 创建MethodChannel实例,通道名称必须与Flutter端一致
this.channel = new MethodChannel(binding.getBinaryMessenger(), "samples.flutter.dev/battery");
// 设置方法调用处理器
this.channel.setMethodCallHandler({
onMethodCall: (call: MethodCall, result: MethodResult) => {
switch (call.method) {
case 'getBatteryLevel':
this.getBatteryLevel(result);
break;
default:
result.notImplemented();
break;
}
}
});
}
private getBatteryLevel(result: MethodResult): void {
try {
// 获取电池电量
const batteryLevel = batteryInfo.batterySOC;
result.success(batteryLevel);
} catch (error) {
result.error('UNAVAILABLE', 'Battery level not available', null);
}
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
// 清理资源
this.channel?.dispose();
this.channel = null;
}
}
四、BasicMessageChannel使用方法
BasicMessageChannel用于Flutter与OpenHarmony之间的基本消息传递,支持字符串、二进制等数据类型。
1. Flutter端实现
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class MessageChannelPage extends StatefulWidget {
const MessageChannelPage({Key? key}) : super(key: key);
State<MessageChannelPage> createState() => _MessageChannelPageState();
}
class _MessageChannelPageState extends State<MessageChannelPage> {
// 创建BasicMessageChannel实例,指定通道名称和消息编解码器
final _basicChannel = BasicMessageChannel<String>(
'samples.flutter.dev/message',
StringCodec(),
);
String _message = 'No message received';
int _count = 0;
void initState() {
super.initState();
// 设置消息接收器
_basicChannel.setMessageHandler((String? message) async {
setState(() {
_message = 'Received: $message';
});
return 'Message received';
});
}
// 发送消息到原生端
Future<void> _sendMessage() async {
_count++;
final String response = await _basicChannel.send('Hello from Flutter: $_count');
setState(() {
_message = 'Response: $response';
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Message Channel'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _sendMessage,
child: const Text('Send Message'),
),
const SizedBox(height: 20),
Text(_message),
],
),
),
);
}
}
2. OpenHarmony端实现
import { FlutterPlugin, FlutterPluginBinding, BasicMessageChannel, Any, Reply, StringCodec } from '@ohos/flutter_ohos';
import { Log } from '@kit.PerformanceAnalysisKit';
const TAG = 'BasicMessageChannelPlugin';
export default class BasicMessageChannelPlugin extends FlutterPlugin {
private basicChannel: BasicMessageChannel | null = null;
onAttachedToEngine(binding: FlutterPluginBinding): void {
// 创建BasicMessageChannel实例
this.basicChannel = new BasicMessageChannel(
binding.getBinaryMessenger(),
"samples.flutter.dev/message",
new StringCodec()
);
// 设置消息处理器
this.basicChannel.setMessageHandler({
onMessage: (message: Any, reply: Reply<Any>) => {
Log.i(TAG, "Received message: " + message);
// 根据消息内容处理
const msgStr = message as string;
if (msgStr.contains('Hello')) {
reply.reply('Hello from OpenHarmony! You said: ' + msgStr);
} else {
reply.reply('Received: ' + msgStr);
}
}
});
}
// 发送消息到Flutter端
sendMessage(message: string): void {
if (this.basicChannel) {
this.basicChannel.send(message, {
onReply: (reply: Any) => {
Log.i(TAG, "Reply received: " + reply);
}
});
}
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
// 清理资源
this.basicChannel = null;
}
}
五、EventChannel使用方法
EventChannel用于OpenHarmony向Flutter发送事件通知,实现单向的事件流通信。
1. Flutter端实现
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class EventChannelPage extends StatefulWidget {
const EventChannelPage({Key? key}) : super(key: key);
State<EventChannelPage> createState() => _EventChannelPageState();
}
class _EventChannelPageState extends State<EventChannelPage> {
// 创建EventChannel实例
final _eventChannel = const EventChannel('samples.flutter.dev/event_channel');
String _eventMessage = 'No event received';
StreamSubscription? _eventSubscription;
void initState() {
super.initState();
// 订阅事件流
_eventSubscription = _eventChannel.receiveBroadcastStream().listen(
(event) {
setState(() {
_eventMessage = 'Event received: $event';
});
},
onError: (error) {
setState(() {
_eventMessage = 'Error: $error';
});
},
);
}
void dispose() {
// 取消订阅
_eventSubscription?.cancel();
super.dispose();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Event Channel'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Listening for events...'),
const SizedBox(height: 20),
Text(_eventMessage),
],
),
),
);
}
}
2. OpenHarmony端实现
import { FlutterPlugin, FlutterPluginBinding, EventChannel, Any, EventSink } from '@ohos/flutter_ohos';
import { Log } from '@kit.PerformanceAnalysisKit';
const TAG = 'EventChannelPlugin';
export default class EventChannelPlugin extends FlutterPlugin {
private eventChannel: EventChannel | null = null;
private eventSink: EventSink | undefined = undefined;
private timerId: number | undefined = undefined;
onAttachedToEngine(binding: FlutterPluginBinding): void {
// 创建EventChannel实例
this.eventChannel = new EventChannel(
binding.getBinaryMessenger(),
"samples.flutter.dev/event_channel"
);
// 设置流处理器
this.eventChannel.setStreamHandler({
onListen: (args: Any, events: EventSink): void => {
Log.i(TAG, "EventChannel onListen: " + args);
this.eventSink = events;
// 每秒发送一次事件
this.timerId = setInterval(() => {
if (this.eventSink) {
// 发送成功事件
this.eventSink.success("Current time: " + new Date().toISOString());
}
}, 1000);
},
onCancel: (args: Any): void => {
Log.i(TAG, "EventChannel onCancel: " + args);
this.eventSink = undefined;
// 清理定时器
if (this.timerId) {
clearInterval(this.timerId);
this.timerId = undefined;
}
}
});
}
// 手动发送事件
sendEvent(data: Any): void {
if (this.eventSink) {
this.eventSink.success(data);
}
}
// 发送错误事件
sendError(code: string, message: string, details: Any): void {
if (this.eventSink) {
this.eventSink.error(code, message, details);
}
}
onDetachedFromEngine(binding: FlutterPluginBinding): void {
// 清理资源
this.eventSink = undefined;
if (this.timerId) {
clearInterval(this.timerId);
this.timerId = undefined;
}
this.eventChannel = null;
}
}
六、通过AtomGit引入依赖
在Flutter工程中,可以通过AtomGit引入FlutterChannel相关依赖:
1. 在pubspec.yaml中添加依赖
dependencies:
flutter:
sdk: flutter
# 通过AtomGit引入flutter_ohos包
flutter_ohos:
git:
url: "https://atomgit.com/flutter-openharmony/flutter_ohos"
path: "packages/flutter_ohos/flutter_ohos"
# 通过AtomGit引入其他Flutter插件
battery_plugin:
git:
url: "https://atomgit.com/flutter-openharmony/plugins"
path: "packages/battery_plugin/battery_plugin"
2. 更新依赖
执行以下命令更新依赖:
flutter pub get
七、完整应用集成示例
1. Flutter应用主入口
import 'package:flutter/material.dart';
import 'battery_level_page.dart';
import 'message_channel_page.dart';
import 'event_channel_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Channel Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Channel Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const BatteryLevelPage()),
);
},
child: const Text('MethodChannel Demo'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const MessageChannelPage()),
);
},
child: const Text('BasicMessageChannel Demo'),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const EventChannelPage()),
);
},
child: const Text('EventChannel Demo'),
),
],
),
),
);
}
}
2. OpenHarmony插件注册
import { GeneratedPluginRegistrant } from '@ohos/flutter_ohos/src/main/ets/plugins/GeneratedPluginRegistrant';
import BatteryPlugin from './BatteryPlugin';
import BasicMessageChannelPlugin from './BasicMessageChannelPlugin';
import EventChannelPlugin from './EventChannelPlugin';
// 注册所有插件
export function registerPlugins() {
GeneratedPluginRegistrant.registerWith();
// 注册自定义插件
const binding = getFlutterPluginBinding();
if (binding) {
binding.addPlugin(new BatteryPlugin());
binding.addPlugin(new BasicMessageChannelPlugin());
binding.addPlugin(new EventChannelPlugin());
}
}
八、总结
FlutterChannel提供了强大的跨平台通信能力,通过三种不同类型的通道满足各种通信需求:
- MethodChannel:适用于需要双向方法调用的场景,如获取设备信息、调用原生API等
- BasicMessageChannel:适用于需要频繁传递数据的场景,如字符串、二进制数据等
- EventChannel:适用于需要原生向Flutter发送事件通知的场景,如传感器数据、状态变化等
使用FlutterChannel的基本步骤:
- 在Flutter和OpenHarmony两端创建相同名称的Channel实例
- 在两端分别设置消息/方法处理器
- 通过Channel发送消息或调用方法
- 处理接收到的消息或方法调用
通过AtomGit引入依赖,可以方便地使用自定义修改版本的Flutter包,避免使用GitCode品牌名称。
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net
更多推荐


所有评论(0)