引言

Flutter 的跨端能力虽强,但无法完全脱离原生平台 —— 比如调用鸿蒙分布式文件服务、Android 相机、iOS 相册、支付 SDK 等,都需要与原生代码交互。很多开发者卡在 “Flutter 与原生通信” 环节:不知道选哪种通信方式、数据传输出错、原生视图嵌入 Flutter 卡顿…… 本文将从通信原理、基础交互、高级实战三个维度,用 6000 字 + 完整代码案例,带你掌握 Flutter 与鸿蒙 / Android/iOS 的原生交互全流程,解决 “Flutter 调用原生能力” 的所有痛点。

一、Flutter 与原生交互核心原理

1.1 通信通道类型

Flutter 提供了三种核心通信通道,覆盖所有交互场景:

通道类型 用途 数据流向 适用场景
Method Channel 方法调用(单次请求 - 响应) 双向(Flutter↔原生) 调用原生 API(如获取设备信息、支付)
Event Channel 事件流(原生主动推送数据) 原生→Flutter 监听传感器、设备状态、实时数据
Basic Message Channel 自定义消息(持续双向通信) 双向(Flutter↔原生) 复杂数据交互(如 protobuf 传输)

1.2 数据序列化规则

Flutter 与原生之间的通信数据需遵循序列化规则,支持的基础类型如下:

Flutter 类型 Android 类型 iOS 类型 鸿蒙类型
int int/long NSNumber int/long
double double NSNumber double
bool boolean NSNumber boolean
String String NSString String
List List/ArrayList NSArray List
Map Map/HashMap NSDictionary Map
null null nil null

注意:复杂类型(如对象)需转换为 Map 传输,再在两端分别解析。

1.3 不同平台交互差异

  • Android:基于 JNI/NDK,Flutter 工程下的android/app/src/main/kotlin目录编写原生代码;
  • iOS:基于 Objective-C/Swift,Flutter 工程下的ios/Runner目录编写原生代码;
  • 鸿蒙(OpenHarmony):基于方舟开发框架,Flutter 工程下的harmony目录编写原生代码(需 Flutter 鸿蒙适配插件)。

二、基础交互:Method Channel 实战(Flutter↔原生)

Method Channel 是最常用的交互方式,适用于 “Flutter 调用原生方法,原生返回结果” 的场景。

2.1 通用流程(所有平台)

  1. Flutter 端创建 Method Channel,调用原生方法;
  2. 原生端注册 Method Channel,监听并处理调用;
  3. 原生端返回结果给 Flutter 端;
  4. Flutter 端接收结果并处理。

2.2 实战 1:获取设备信息(Flutter↔Android/iOS/ 鸿蒙)

2.2.1 Flutter 端代码

dart

import 'package:flutter/services.dart';

class DeviceInfoManager {
  // 1. 创建Method Channel(名称需与原生端一致)
  static const MethodChannel _channel = MethodChannel('com.example/device_info');

  // 2. 调用原生方法:获取设备信息
  static Future<Map<String, dynamic>?> getDeviceInfo() async {
    try {
      // 调用原生方法,参数为可选
      final result = await _channel.invokeMethod('getDeviceInfo');
      return Map<String, dynamic>.from(result);
    } on PlatformException catch (e) {
      debugPrint("获取设备信息失败:${e.message}");
      return null;
    }
  }
}

// 使用示例
class DeviceInfoPage extends StatelessWidget {
  const DeviceInfoPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const AppBar(title: Text("设备信息")),
      body: Center(
        child: FutureBuilder<Map<String, dynamic>?>(
          future: DeviceInfoManager.getDeviceInfo(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const CircularProgressIndicator();
            }
            if (snapshot.hasError || !snapshot.hasData) {
              return const Text("获取设备信息失败");
            }
            final info = snapshot.data!;
            return Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text("设备名称:${info['deviceName']}"),
                Text("设备类型:${info['deviceType']}"),
                Text("系统版本:${info['systemVersion']}"),
                Text("设备ID:${info['deviceId']}"),
              ],
            );
          },
        ),
      ),
    );
  }
}
2.2.2 Android 端代码(Kotlin)

kotlin

// android/app/src/main/kotlin/com/example/flutter_native_interaction/MainActivity.kt
package com.example.flutter_native_interaction

import android.os.Build
import android.provider.Settings
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    // 1. 定义Channel名称(与Flutter端一致)
    private val CHANNEL = "com.example/device_info"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        // 2. 注册Method Channel
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            // 3. 处理Flutter调用的方法
            when (call.method) {
                "getDeviceInfo" -> {
                    // 获取设备信息
                    val deviceInfo = mapOf(
                        "deviceName" to android.os.Build.MODEL,
                        "deviceType" to "Android",
                        "systemVersion" to Build.VERSION.RELEASE,
                        "deviceId" to Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
                    )
                    // 4. 返回结果给Flutter
                    result.success(deviceInfo)
                }
                else -> {
                    // 方法不存在
                    result.notImplemented()
                }
            }
        }
    }
}
2.2.3 iOS 端代码(Swift)

swift

// ios/Runner/AppDelegate.swift
import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    // 1. 注册Method Channel(名称与Flutter端一致)
    let deviceChannel = FlutterMethodChannel(name: "com.example/device_info", binaryMessenger: controller.binaryMessenger)
    // 2. 处理Flutter调用
    deviceChannel.setMethodCallHandler({
      (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
      if call.method == "getDeviceInfo" {
        // 获取设备信息
        let deviceName = UIDevice.current.name
        let deviceType = "iOS"
        let systemVersion = UIDevice.current.systemVersion
        let deviceId = UIDevice.current.identifierForVendor?.uuidString ?? ""
        // 返回结果
        result([
          "deviceName": deviceName,
          "deviceType": deviceType,
          "systemVersion": systemVersion,
          "deviceId": deviceId
        ])
      } else {
        result(FlutterMethodNotImplemented)
      }
    })
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}
2.2.4 鸿蒙端代码(ArkTS)

typescript

运行

// harmony/src/main/ets/entryability/EntryAbility.ets
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { FlutterHarmonyChannel } from '@ohos/flutter_harmony';

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    // 1. 注册Method Channel(名称与Flutter端一致)
    FlutterHarmonyChannel.registerMethodChannel('com.example/device_info', (method, params, callback) => {
      if (method === 'getDeviceInfo') {
        // 获取鸿蒙设备信息
        const deviceInfo = {
          deviceName: ohos.system.deviceInfo.deviceName,
          deviceType: ohos.system.deviceInfo.deviceType,
          systemVersion: ohos.system.deviceInfo.sdkVersion,
          deviceId: ohos.system.deviceInfo.uuid
        };
        // 返回结果给Flutter
        callback.success(deviceInfo);
      } else {
        callback.notImplemented();
      }
    });
  }

  onWindowStageCreate(windowStage: window.WindowStage) {
    super.onWindowStageCreate(windowStage);
    windowStage.loadContent('pages/index', (err, data) => {
      if (err) {
        console.error('Failed to load content. Cause: ' + JSON.stringify(err));
        return;
      }
    });
  }
}

2.3 实战 2:原生调用 Flutter 方法(反向调用)

Method Channel 也支持原生主动调用 Flutter 方法,适用于 “原生事件触发 Flutter 更新” 的场景:

2.3.1 Flutter 端代码(注册方法)

dart

class ReverseCallManager {
  static const MethodChannel _channel = MethodChannel('com.example/reverse_call');

  // 初始化:注册原生可调用的方法
  static void init() {
    _channel.setMethodCallHandler((call) async {
      switch (call.method) {
        case "onNativeEvent":
          // 处理原生触发的事件
          final message = call.arguments as String;
          debugPrint("收到原生事件:$message");
          // 返回结果给原生
          return "Flutter已接收事件:$message";
        default:
          throw MissingPluginException("方法未实现");
      }
    });
  }
}

// 在main中初始化
void main() {
  ReverseCallManager.init();
  runApp(const MyApp());
}
2.3.2 Android 端代码(调用 Flutter 方法)

kotlin

// 在需要调用的地方执行
private fun callFlutterMethod() {
    val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "com.example/reverse_call")
    // 调用Flutter方法
    channel.invokeMethod("onNativeEvent", "Android原生触发的事件", object : MethodChannel.Result {
        override fun success(result: Any?) {
            Log.d("Native", "Flutter返回:$result")
        }

        override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
            Log.e("Native", "调用失败:$errorMessage")
        }

        override fun notImplemented() {
            Log.w("Native", "方法未实现")
        }
    })
}

三、实时通信:Event Channel 实战(原生→Flutter)

Event Channel 适用于 “原生主动向 Flutter 推送实时数据” 的场景,比如监听鸿蒙分布式设备状态、Android 传感器数据、iOS 定位信息等。

3.1 通用流程

  1. Flutter 端创建 Event Channel,监听原生事件;
  2. 原生端注册 Event Channel,提供事件流;
  3. 原生端推送事件到 Flutter 端;
  4. Flutter 端接收并处理事件。

3.2 实战:监听鸿蒙分布式设备状态

3.2.1 Flutter 端代码

dart

import 'package:flutter/services.dart';

class DeviceStatusManager {
  // 1. 创建Event Channel(名称与原生端一致)
  static const EventChannel _channel = EventChannel('com.example/device_status');

  // 2. 监听设备状态
  static Stream<Map<String, dynamic>> listenDeviceStatus() {
    return _channel.receiveBroadcastStream().map((event) {
      return Map<String, dynamic>.from(event);
    });
  }
}

// 使用示例
class DeviceStatusPage extends StatefulWidget {
  const DeviceStatusPage({super.key});

  @override
  State<DeviceStatusPage> createState() => _DeviceStatusPageState();
}

class _DeviceStatusPageState extends State<DeviceStatusPage> {
  List<Map<String, dynamic>> _deviceList = [];

  @override
  void initState() {
    super.initState();
    // 监听设备状态
    DeviceStatusManager.listenDeviceStatus().listen((deviceInfo) {
      setState(() {
        // 更新设备列表
        final index = _deviceList.indexWhere((d) => d['deviceId'] == deviceInfo['deviceId']);
        if (index >= 0) {
          _deviceList[index] = deviceInfo;
        } else {
          _deviceList.add(deviceInfo);
        }
      });
    }, onError: (error) {
      debugPrint("监听设备状态失败:$error");
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const AppBar(title: Text("鸿蒙设备状态")),
      body: ListView.builder(
        itemCount: _deviceList.length,
        itemBuilder: (context, index) {
          final device = _deviceList[index];
          return ListTile(
            title: Text(device['deviceName']),
            subtitle: Text("状态:${device['status']}"),
            leading: Icon(
              device['status'] == 'online' ? Icons.check_circle : Icons.error,
              color: device['status'] == 'online' ? Colors.green : Colors.red,
            ),
          );
        },
      ),
    );
  }
}
3.2.2 鸿蒙端代码(ArkTS)

typescript

运行

// harmony/src/main/ets/entryability/DeviceStatusProvider.ets
import { FlutterHarmonyChannel } from '@ohos/flutter_harmony';
import distributedDevice from '@ohos.distributedDevice';

// 1. 注册Event Channel并提供事件流
export function registerDeviceStatusChannel() {
  FlutterHarmonyChannel.registerEventChannel('com.example/device_status', (events) => {
    // 监听鸿蒙分布式设备状态
    distributedDevice.on('deviceChange', (deviceInfo) => {
      // 推送设备状态到Flutter
      events.success({
        deviceId: deviceInfo.deviceId,
        deviceName: deviceInfo.deviceName,
        deviceType: deviceInfo.deviceType,
        status: deviceInfo.status // online/offline/connected
      });
    });

    // 初始加载设备列表
    distributedDevice.getDeviceList().then((list) => {
      list.forEach((device) => {
        events.success({
          deviceId: device.deviceId,
          deviceName: device.deviceName,
          deviceType: device.deviceType,
          status: device.status
        });
      });
    });

    // 取消监听的回调
    return () => {
      distributedDevice.off('deviceChange');
    };
  });
}

// 在EntryAbility中初始化
import UIAbility from '@ohos.app.ability.UIAbility';
import { registerDeviceStatusChannel } from './DeviceStatusProvider';

export default class EntryAbility extends UIAbility {
  onCreate(want, launchParam) {
    // 注册设备状态Event Channel
    registerDeviceStatusChannel();
  }
}

四、高级交互:原生视图嵌入 Flutter

有时需要在 Flutter 中嵌入原生视图,比如鸿蒙原生地图、Android 支付控件、iOS 视频播放器等。

4.1 通用流程

  1. 原生端创建自定义视图(View/UIView/Component);
  2. Flutter 端使用AndroidView/UiKitView/HarmonyView嵌入原生视图;
  3. 通过 Method Channel 实现 Flutter 与原生视图的交互。

4.2 实战:Flutter 中嵌入鸿蒙原生地图组件

4.2.1 鸿蒙端创建地图组件(ArkTS)

typescript

运行

// harmony/src/main/ets/pages/MapComponent.ets
@Entry
@Component
struct MapComponent {
  @State latitude: number = 39.908823;
  @State longitude: number = 116.397470;

  build() {
    Map({
      latitude: this.latitude,
      longitude: this.longitude,
      zoomLevel: 16
    })
    .width('100%')
    .height('100%')
    .onMapClick((lat, lng) => {
      // 地图点击事件,通过Method Channel传递给Flutter
      FlutterHarmonyChannel.invokeMethod('map_click', {
        latitude: lat,
        longitude: lng
      });
    });
  }

  // 接收Flutter的参数(如修改地图中心点)
  setCenter(lat: number, lng: number) {
    this.latitude = lat;
    this.longitude = lng;
  }
}
4.2.2 Flutter 端嵌入鸿蒙地图组件

dart

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

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

  @override
  State<HarmonyMapPage> createState() => _HarmonyMapPageState();
}

class _HarmonyMapPageState extends State<HarmonyMapPage> {
  late HarmonyViewController _mapController;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const AppBar(title: Text("鸿蒙地图")),
      body: Column(
        children: [
          // 嵌入鸿蒙地图组件
          SizedBox(
            width: double.infinity,
            height: 400,
            child: HarmonyView(
              viewType: "com.example/map_view",
              onPlatformViewCreated: (controller) {
                _mapController = controller;
                // 初始化地图中心点
                _mapController.invokeMethod('setCenter', [39.908823, 116.397470]);
              },
              // 监听地图点击事件
              methodChannel: MethodChannel('com.example/map_view'),
              onMethodCall: (call) async {
                if (call.method == 'map_click') {
                  final lat = call.arguments['latitude'];
                  final lng = call.arguments['longitude'];
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(content: Text("地图点击:$lat, $lng")),
                  );
                }
              },
            ),
          ),
          // 按钮:修改地图中心点
          ElevatedButton(
            onPressed: () {
              _mapController.invokeMethod('setCenter', [31.230416, 121.473701]);
            },
            child: const Text("切换到上海"),
          ),
        ],
      ),
    );
  }
}

五、实战项目:Flutter + 鸿蒙分布式文件选择器

5.1 项目需求

打造一个 Flutter 应用,调用鸿蒙分布式文件服务,实现:

  1. 扫描鸿蒙分布式设备;
  2. 选择远程设备的文件;
  3. 下载文件到本地;
  4. 实时显示下载进度。

5.2 核心代码实现

5.2.1 Flutter 端代码(整合 Method/Event Channel)

dart

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

// 1. 设备管理
class HarmonyDeviceManager {
  static const MethodChannel _deviceChannel = MethodChannel('com.example/harmony_device');
  static const EventChannel _fileProgressChannel = EventChannel('com.example/file_progress');

  // 扫描分布式设备
  static Future<List<Map<String, dynamic>>?> scanDevices() async {
    try {
      final result = await _deviceChannel.invokeMethod('scanDevices');
      return (result as List).map((e) => Map<String, dynamic>.from(e)).toList();
    } on PlatformException catch (e) {
      debugPrint("扫描设备失败:${e.message}");
      return null;
    }
  }

  // 浏览远程设备文件
  static Future<List<Map<String, dynamic>>?> browseFiles(String deviceId, String path) async {
    try {
      final result = await _deviceChannel.invokeMethod('browseFiles', {
        'deviceId': deviceId,
        'path': path,
      });
      return (result as List).map((e) => Map<String, dynamic>.from(e)).toList();
    } on PlatformException catch (e) {
      debugPrint("浏览文件失败:${e.message}");
      return null;
    }
  }

  // 下载文件
  static Future<String?> downloadFile(String deviceId, String srcPath, String destPath) async {
    try {
      final taskId = await _deviceChannel.invokeMethod('downloadFile', {
        'deviceId': deviceId,
        'srcPath': srcPath,
        'destPath': destPath,
      });
      return taskId as String;
    } on PlatformException catch (e) {
      debugPrint("下载文件失败:${e.message}");
      return null;
    }
  }

  // 监听下载进度
  static Stream<Map<String, dynamic>> listenDownloadProgress() {
    return _fileProgressChannel.receiveBroadcastStream().map((event) {
      return Map<String, dynamic>.from(event);
    });
  }
}

// 2. 文件选择页面
class HarmonyFilePickerPage extends StatefulWidget {
  const HarmonyFilePickerPage({super.key});

  @override
  State<HarmonyFilePickerPage> createState() => _HarmonyFilePickerPageState();
}

class _HarmonyFilePickerPageState extends State<HarmonyFilePickerPage> {
  List<Map<String, dynamic>> _devices = [];
  List<Map<String, dynamic>> _files = [];
  Map<String, dynamic>? _selectedDevice;
  String _currentPath = '/';
  Map<String, int> _downloadProgress = {};

  @override
  void initState() {
    super.initState();
    // 扫描设备
    _scanDevices();
    // 监听下载进度
    HarmonyDeviceManager.listenDownloadProgress().listen((progress) {
      setState(() {
        _downloadProgress[progress['taskId']] = progress['progress'];
      });
    });
  }

  Future<void> _scanDevices() async {
    final devices = await HarmonyDeviceManager.scanDevices();
    if (devices != null) {
      setState(() => _devices = devices);
    }
  }

  Future<void> _browseFiles() async {
    if (_selectedDevice == null) return;
    final files = await HarmonyDeviceManager.browseFiles(
      _selectedDevice!['deviceId'],
      _currentPath,
    );
    if (files != null) {
      setState(() => _files = files);
    }
  }

  Future<void> _downloadFile(Map<String, dynamic> file) async {
    if (_selectedDevice == null) return;
    final destPath = "/sdcard/Download/${file['name']}";
    final taskId = await HarmonyDeviceManager.downloadFile(
      _selectedDevice!['deviceId'],
      file['path'],
      destPath,
    );
    if (taskId != null) {
      setState(() => _downloadProgress[taskId] = 0);
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text("开始下载:${file['name']}")),
      );
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const AppBar(title: Text("鸿蒙分布式文件选择器")),
      body: Column(
        children: [
          // 设备选择
          Padding(
            padding: const EdgeInsets.all(16),
            child: DropdownButton<Map<String, dynamic>>(
              hint: const Text("选择分布式设备"),
              value: _selectedDevice,
              items: _devices.map((device) {
                return DropdownMenuItem(
                  value: device,
                  child: Text(device['deviceName']),
                );
              }).toList(),
              onChanged: (value) {
                setState(() {
                  _selectedDevice = value;
                  _currentPath = '/';
                });
                _browseFiles();
              },
            ),
          ),
          // 路径导航
          Padding(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            child: Text("当前路径:$_currentPath"),
          ),
          // 文件列表
          Expanded(
            child: ListView.builder(
              itemCount: _files.length,
              itemBuilder: (context, index) {
                final file = _files[index];
                return ListTile(
                  leading: Icon(file['isDirectory'] ? Icons.folder : Icons.file_copy),
                  title: Text(file['name']),
                  subtitle: Text(file['isDirectory'] ? "文件夹" : "大小:${_formatSize(file['size'])}"),
                  onTap: () {
                    if (file['isDirectory']) {
                      setState(() => _currentPath = file['path']);
                      _browseFiles();
                    } else {
                      _downloadFile(file);
                    }
                  },
                );
              },
            ),
          ),
          // 下载进度
          if (_downloadProgress.isNotEmpty)
            Column(
              children: _downloadProgress.entries.map((entry) {
                return LinearProgressIndicator(
                  value: entry.value / 100,
                  backgroundColor: Colors.grey[200],
                  valueColor: const AlwaysStoppedAnimation<Color>(Colors.blue),
                );
              }).toList(),
            ),
        ],
      ),
    );
  }

  // 格式化文件大小
  String _formatSize(int size) {
    if (size < 1024) return "$size B";
    if (size < 1024 * 1024) return "${(size / 1024).toStringAsFixed(2)} KB";
    if (size < 1024 * 1024 * 1024) return "${(size / (1024 * 1024)).toStringAsFixed(2)} MB";
    return "${(size / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB";
  }
}

// 3. 入口
void main() {
  runApp(const MaterialApp(
    title: "Flutter鸿蒙原生交互",
    home: HarmonyFilePickerPage(),
    debugShowCheckedModeBanner: false,
  ));
}
5.2.2 鸿蒙端核心代码(ArkTS)

typescript

运行

// 分布式文件服务封装
import distributedFile from '@ohos.file.distributed';
import { FlutterHarmonyChannel } from '@ohos/flutter_harmony';

// 注册Method Channel
export function registerFileChannel() {
  // 设备扫描
  FlutterHarmonyChannel.registerMethodChannel('com.example/harmony_device', (method, params, callback) => {
    switch (method) {
      case 'scanDevices':
        // 扫描分布式设备
        distributedFile.scanDevices().then((devices) => {
          callback.success(devices);
        }).catch((err) => {
          callback.error('SCAN_FAILED', err.message, null);
        });
        break;
      case 'browseFiles':
        // 浏览文件
        const deviceId = params.deviceId;
        const path = params.path;
        distributedFile.listFiles(deviceId, path).then((files) => {
          callback.success(files);
        }).catch((err) => {
          callback.error('BROWSE_FAILED', err.message, null);
        });
        break;
      case 'downloadFile':
        // 下载文件
        const taskId = `download_${Date.now()}`;
        const srcPath = params.srcPath;
        const destPath = params.destPath;
        // 监听下载进度
        distributedFile.on('transferProgress', taskId, (progress) => {
          // 推送进度到Flutter
          FlutterHarmonyChannel.emitEvent('com.example/file_progress', {
            taskId: taskId,
            progress: Math.round((progress.transferred / progress.total) * 100),
          });
        });
        // 执行下载
        distributedFile.transferFile({
          taskId: taskId,
          sourceDeviceId: params.deviceId,
          sourcePath: srcPath,
          targetPath: destPath,
        }).then(() => {
          callback.success(taskId);
        }).catch((err) => {
          callback.error('DOWNLOAD_FAILED', err.message, null);
        });
        break;
      default:
        callback.notImplemented();
    }
  });

  // 注册Event Channel(下载进度)
  FlutterHarmonyChannel.registerEventChannel('com.example/file_progress', (events) => {
    // 保持通道打开,接收进度推送
    return () => {};
  });
}

六、避坑指南与最佳实践

6.1 常见问题与解决方案

问题 原因 解决方案
通信通道名称不一致 Flutter 与原生端 Channel 名称不同 统一命名规范(如 com. 公司 / 功能)
数据类型转换失败 两端数据类型不匹配(如 int→String) 严格遵循序列化规则,复杂类型转 Map 传输
原生方法未实现 Flutter 调用的方法名拼写错误 统一方法名常量,避免硬编码
内存泄漏 Event Channel 未取消监听 在 dispose 中取消 Stream 订阅
鸿蒙端通信无响应 未配置分布式权限 在 config.json 中添加分布式权限声明

6.2 最佳实践

  1. 统一通道命名规范:采用 “域名反转 + 功能” 的格式(如 com.example/device_info),避免冲突;
  2. 错误处理:所有通信都要捕获 PlatformException,给出友好提示;
  3. 资源释放:Event Channel 的 Stream 订阅需在 dispose 中取消,避免内存泄漏;
  4. 数据校验:原生端返回数据前校验格式,Flutter 端接收后二次校验;
  5. 性能优化:避免频繁通信
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐