欢迎大家加入开源鸿蒙跨平台社区

Flutter-OH 向鸿蒙发送数据完整实现指南

一、实现原理

Flutter 与鸿蒙原生之间的数据通信通过 MethodChannel 实现双向数据传输:

  • Flutter 端:通过 MethodChannel 发送数据(Map、List、基本类型等)
  • 鸿蒙端:接收数据,处理后将结果返回给 Flutter
┌─────────────┐     MethodChannel      ┌─────────────┐
│  Flutter    │ ─────────────────────> │   鸿蒙原生   │
│  发送数据   │   sendDataToHarmony    │  EntryAbility│
│  (Map类型)  │ ─────────────────────> │  处理数据    │
└─────────────┘                        └──────┬──────┘
       ↑                                      │
       └────────── 返回处理结果 <─────────────┘

二、完整代码实现

1. Flutter 端 - 平台通道封装

文件: lib/harmony_channel.dart

import 'package:flutter/services.dart';

/// 鸿蒙平台通道 - 用于 Flutter 与鸿蒙原生通信
class HarmonyChannel {
  static const MethodChannel _channel = 
      MethodChannel('com.example.test1/harmony');

  /// 向鸿蒙发送数据
  /// [data] 要发送的数据,可以是 Map、List、String、int、double、bool 等
  /// 返回鸿蒙端的处理结果
  static Future<dynamic> sendDataToHarmony(dynamic data) async {
    try {
      final result = await _channel.invokeMethod('sendDataToHarmony', data);
      print('数据发送成功,鸿蒙返回: $result');
      return result;
    } on PlatformException catch (e) {
      print('向鸿蒙发送数据失败: ${e.message}');
      rethrow;
    }
  }
}

代码解读:

代码段 说明
invokeMethod('sendDataToHarmony', data) 调用鸿蒙端方法,并传递数据参数
dynamic data 支持任意类型的数据:Map、List、String、int、double、bool 等
Future<dynamic> 异步返回鸿蒙端的处理结果
PlatformException 处理平台调用异常

数据类型支持:

  • 基本类型:Stringintdoublebool
  • 集合类型:ListMap
  • 嵌套结构:Map 中可以包含 List 或其他 Map

2. Flutter 端 - UI 界面

文件: lib/main.dart

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

// ... 其他代码 ...

children: <Widget>[
  const Text('You have pushed the button this many times:'),
  Text(
    '$_counter',
    style: Theme.of(context).textTheme.headlineMedium,
  ),
  const SizedBox(height: 30),
  // 发送数据到鸿蒙的按钮
  ElevatedButton.icon(
    onPressed: () async {
      // 构造要发送的数据
      final data = {
        'title': '来自 Flutter 的数据',
        'message': '你好,鸿蒙!',
        'timestamp': DateTime.now().toIso8601String(),
        'counter': _counter,
        'items': ['item1', 'item2', 'item3'],
      };
      final result = await HarmonyChannel.sendDataToHarmony(data);
      // 显示返回结果
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(content: Text('鸿蒙返回: $result')),
        );
      }
    },
    icon: const Icon(Icons.send),
    label: const Text('发送数据到鸿蒙'),
    style: ElevatedButton.styleFrom(
      padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
      backgroundColor: Colors.green,
    ),
  ),
],

代码解读:

代码段 说明
final data = {...} 构造要发送的数据 Map,包含多种类型的字段
DateTime.now().toIso8601String() 生成 ISO 8601 格式的时间戳
HarmonyChannel.sendDataToHarmony(data) 调用平台通道发送数据
ScaffoldMessenger.of(context).showSnackBar 显示鸿蒙返回的结果
if (mounted) 检查 Widget 是否仍在树中,避免内存泄漏
backgroundColor: Colors.green 设置按钮为绿色

发送的数据结构:

{
  'title': '来自 Flutter 的数据',     // String
  'message': '你好,鸿蒙!',           // String
  'timestamp': '2024-01-15T10:30:00.000Z', // String (ISO 8601)
  'counter': 5,                        // int
  'items': ['item1', 'item2', 'item3'] // List<String>
}

3. 鸿蒙端 - EntryAbility(接收数据处理)

文件: ohos/entry/src/main/ets/entryability/EntryAbility.ets

import { 
  FlutterAbility, 
  FlutterEngine, 
  MethodChannel, 
  Log, 
  MethodCall, 
  MethodResult, 
  MethodCallHandler, 
  BinaryMessenger 
} from '@ohos/flutter_ohos';
import { GeneratedPluginRegistrant } from '../plugins/GeneratedPluginRegistrant';

const TAG = 'EntryAbility';
const CHANNEL_NAME = 'com.example.test1/harmony';

// 定义数据摘要接口
interface DataSummary {
  titleLength: number;
  messageLength: number;
  itemCount: number;
}

// 定义响应接口
interface ResponseData {
  code: number;
  message: string;
  receivedAt: string;
  dataSummary: DataSummary;
}

export default class EntryAbility extends FlutterAbility {
  private methodChannel: MethodChannel | null = null;

  configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    GeneratedPluginRegistrant.registerWith(flutterEngine)

    // 注册 MethodChannel 处理 Flutter 调用
    let messenger: BinaryMessenger = flutterEngine.dartExecutor.getBinaryMessenger();
    this.methodChannel = new MethodChannel(messenger, CHANNEL_NAME);

    let methodCallHandler: MethodCallHandler = {
      onMethodCall: (call: MethodCall, result: MethodResult) => {
        Log.i(TAG, '收到 Flutter 调用: ' + call.method);

        if (call.method === 'sendDataToHarmony') {
          // 处理 Flutter 发送的数据
          this.handleDataFromFlutter(call, result);
        } else {
          result.notImplemented();
        }
      }
    };

    this.methodChannel.setMethodCallHandler(methodCallHandler);
  }

  // 处理 Flutter 发送的数据
  private handleDataFromFlutter(call: MethodCall, result: MethodResult): void {
    Log.i(TAG, '收到 Flutter 发送的数据');

    // 获取数据参数
    let title: string = '';
    let message: string = '';
    let timestamp: string = '';
    let counter: number = 0;
    let items: Array<string> = [];

    // 从 call 中获取参数(使用 hasArgument 检查后再获取)
    if (call.hasArgument('title')) {
      title = call.argument('title') as string;
    }
    if (call.hasArgument('message')) {
      message = call.argument('message') as string;
    }
    if (call.hasArgument('timestamp')) {
      timestamp = call.argument('timestamp') as string;
    }
    if (call.hasArgument('counter')) {
      counter = call.argument('counter') as number;
    }
    if (call.hasArgument('items')) {
      items = call.argument('items') as Array<string>;
    }

    // 打印接收到的数据
    Log.i(TAG, '标题: ' + title);
    Log.i(TAG, '消息: ' + message);
    Log.i(TAG, '时间戳: ' + timestamp);
    Log.i(TAG, '计数器: ' + counter);
    Log.i(TAG, '列表项: ' + JSON.stringify(items));

    // 构造返回结果 - 使用显式接口类型
    let dataSummary: DataSummary = {
      titleLength: title.length,
      messageLength: message.length,
      itemCount: items.length
    };

    let response: ResponseData = {
      code: 200,
      message: '数据接收成功',
      receivedAt: new Date().toISOString(),
      dataSummary: dataSummary
    };

    Log.i(TAG, '返回给 Flutter: ' + JSON.stringify(response));

    // 返回成功结果给 Flutter
    result.success(response);
  }
}

代码解读:

3.1 接口定义
接口 说明
DataSummary 数据摘要接口,包含字符串长度和列表数量
ResponseData 响应数据接口,符合 ArkTS 强类型要求
3.2 数据接收处理
代码段 说明
call.hasArgument('key') 检查参数是否存在
call.argument('key') 获取指定 key 的参数值
as string / as number 类型断言,将参数转换为具体类型
3.3 响应数据构造
// 构造返回结果
let response: ResponseData = {
  code: 200,
  message: '数据接收成功',
  receivedAt: new Date().toISOString(),
  dataSummary: {
    titleLength: title.length,
    messageLength: message.length,
    itemCount: items.length
  }
};

// 返回给 Flutter
result.success(response);

返回的数据结构:

{
  "code": 200,
  "message": "数据接收成功",
  "receivedAt": "2024-01-15T10:30:01.123Z",
  "dataSummary": {
    "titleLength": 10,
    "messageLength": 6,
    "itemCount": 3
  }
}

三、关键技术点

1. ArkTS 强类型要求

鸿蒙 ArkTS 是强类型语言,所有对象必须显式声明类型:

// ❌ 错误:未声明类型的对象字面量
let response = {
  code: 200,
  message: '成功'
};

// ✅ 正确:使用接口声明类型
interface ResponseData {
  code: number;
  message: string;
}

let response: ResponseData = {
  code: 200,
  message: '成功'
};

2. 数据类型映射

Flutter 类型 鸿蒙 ArkTS 类型
String string
int number
double number
bool boolean
List Array<T>
Map ESObject / 接口

3. 参数获取方式

// 方式1:直接获取(需要类型断言)
let title = call.argument('title') as string;

// 方式2:先检查再获取(推荐,更安全)
if (call.hasArgument('title')) {
  title = call.argument('title') as string;
}

四、运行效果

  1. Flutter 页面显示绿色按钮:“发送数据到鸿蒙”

  2. 点击按钮后:

    • Flutter 构造数据 Map
    • 通过 MethodChannel 发送到鸿蒙
    • 鸿蒙接收并处理数据
    • 鸿蒙返回处理结果
    • Flutter 显示 SnackBar 展示返回结果
  3. 日志输出

    
    
    [EntryAbility] 收到 Flutter 发送的数据
    [EntryAbility] 标题: 来自 Flutter 的数据
    [EntryAbility] 消息: 你好,鸿蒙!
    [EntryAbility] 计数器: 5
    [EntryAbility] 返回给 Flutter: {"code":200,...}
    

在这里插入图片描述


五、扩展建议

  1. 复杂数据类型:可以发送嵌套的 Map 和 List
  2. 大数据量:建议分批发送或使用文件传输
  3. 错误处理:添加更完善的异常处理机制
  4. 数据校验:在接收端添加数据合法性校验
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐