
作者:晚霞的不甘 日期:2025年12月5日 标签:Flutter · OpenHarmony · 插件开发 · MethodChannel · ArkTS · 原生集成 · 鸿蒙生态

Flutter 虽能跨平台,但无法直接调用 OpenHarmony 特有功能:
若强行用通用 API 替代,将导致:
插件(Plugin)是桥梁——让 Dart 代码安全、高效地调用 ArkTS/C++ 原生能力。
本文将手把手教你从零开发一个 oh_health_sensor 插件,覆盖架构设计、双向通信、异步处理、错误传递、发布上架全流程,助你构建高性能、可复用、合规安全的 OpenHarmony 原生扩展。
┌───────────────────────┐
│ Dart (Flutter) │ ← 调用 oh_health_sensor.readHeartRate()
├───────────┬───────────┤
│ MethodChannel │ ← 双向通信通道(JSON 编解码)
├───────────┴───────────┤
│ ArkTS (OpenHarmony)│ ← 实现传感器监听逻辑
├───────────────────────┤
│ System APIs │ ← 调用 @ohos.sensor / @ohos.hiSysEvent
└───────────────────────┘✅ 核心原则:
flutter create --org com.example --platforms=openharmony -t plugin oh_health_sensor生成结构:
oh_health_sensor/
├── lib/ # Dart 接口
│ └── oh_health_sensor.dart
├── openharmony/ # OpenHarmony 原生实现
│ ├── src/main/ets/ # ArkTS 代码
│ │ └── OhHealthSensorPlugin.ets
│ └── module.json5 # 声明权限与能力
└── example/ # 示例 App// lib/oh_health_sensor.dart
class OhHealthSensor {
static const _channel = MethodChannel('com.example/oh_health_sensor');
/// 获取当前心率(单次读取)
static Future<int?> readHeartRate() async {
try {
final result = await _channel.invokeMethod('readHeartRate');
return result as int?;
} on PlatformException catch (e) {
// 统一错误处理
throw HealthSensorException(e.code, e.message);
}
}
/// 监听实时心率(流式回调)
static Stream<int> streamHeartRate({required Duration interval}) {
return EventChannel('com.example/oh_health_sensor/heartRateStream')
.receiveBroadcastStream(interval.inMilliseconds.toString())
.map((event) => event as int);
}
}💡 最佳实践:
Future 处理一次性操作Stream 处理持续数据(如传感器)PlatformException 为业务异常// openharmony/src/main/ets/OhHealthSensorPlugin.ets
import { MethodChannel, EventChannel } from '@ohos/flutter';
import sensor from '@ohos:sensor';
export default class OhHealthSensorPlugin {
private heartRateListener?: number;
constructor(private channel: MethodChannel) {
// 注册方法处理器
channel.setMethodCallHandler(this.handleMethodCall.bind(this));
}
private async handleMethodCall(call: any, result: any): Promise<void> {
try {
switch (call.method) {
case 'readHeartRate':
const rate = await this.getCurrentHeartRate();
result.success(rate);
break;
default:
result.notImplemented();
}
} catch (error) {
result.error('SENSOR_ERROR', error.message, null);
}
}
private async getCurrentHeartRate(): Promise<number> {
// 1. 检查权限
if (!await this.checkPermission('ohos.permission.HEALTH_DATA')) {
throw new Error('Permission denied');
}
// 2. 读取传感器
return new Promise((resolve, reject) => {
sensor.once(sensor.SensorId.HEART_RATE, (data) => {
resolve(data.heartRate);
}, (error) => {
reject(error);
});
});
}
// 事件通道:用于 Stream
registerHeartRateStream(eventChannel: EventChannel) {
eventChannel.setStreamHandler({
onListen: (arguments, eventSink) => {
this.heartRateListener = sensor.on(sensor.SensorId.HEART_RATE, (data) => {
eventSink.success(data.heartRate);
});
},
onCancel: () => {
if (this.heartRateListener) {
sensor.off(sensor.SensorId.HEART_RATE, this.heartRateListener);
this.heartRateListener = undefined;
}
}
});
}
}// openharmony/module.json5
{
"module": {
"requestPermissions": [
{ "name": "ohos.permission.HEALTH_DATA" },
{ "name": "ohos.permission.BODY_SENSORS" }
],
"deviceTypes": ["wearable"] // 仅手表支持
}
}通信方式 | 适用场景 | 实现方式 |
|---|---|---|
MethodChannel | 一次性调用(如获取位置) | invokeMethod() + 回调 |
EventChannel | 持续数据流(如传感器) | receiveBroadcastStream() |
Callback | 原生主动通知 Dart | 通过 BinaryMessenger 发送 |
⚠️ 注意:
错误码 | 含义 | Dart 端处理 |
|---|---|---|
PERMISSION_DENIED | 权限未授予 | 引导用户开启 |
SENSOR_UNAVAILABLE | 设备无传感器 | 降级提示 |
TIMEOUT | 读取超时 | 重试或取消 |
日志输出:
// ArkTS
console.log('[OhHealthSensor] Reading heart rate...');// Dart
debugPrint('[oh_health_sensor] Received: $rate');真机调试:
hdc shell hilog -t flutter | grep OhHealthSensoronCancel 中调用 sensor.off()interval > 0)在 example/ 中验证:
// example/lib/main.dart
final rate = await OhHealthSensor.readHeartRate();
print('Current heart rate: $rate');cd oh_health_sensor
flutter pub publish.har 文件供其他项目引用pubspec.yaml 中指定 path)若需支持跨设备传感器数据同步:
@ohos:distributedHardwareEventChannel 推送给 Dart// 伪代码:订阅远程手表
distributedHardware.subscribe('remote_watch', 'heart_rate', (data) => {
eventSink.success(data); // 推送给 Flutter
});优秀的插件应做到:
🔌 行动建议:
hello_oh 插件练手因为真正的跨端,不是回避原生,而是优雅融合。
附录:常用 OpenHarmony API 对应表
功能 | ArkTS 模块 | 权限 |
|---|---|---|
传感器 | @ohos:sensor | BODY_SENSORS |
分布式 | @ohos:distributedHardware | DISTRIBUTED_DATASYNC |
安全存储 | @ohos:security.huks | 无需声明 |
系统事件 | @ohos:hiSysEvent | SYS_EVENT_COLLECTOR |
插件的价值,不在于它多复杂,而在于它让开发者少写多少重复代码。