9.1 平台通道(Platform Channel)

Platform Channel 是 Flutter 与原生平台(Android/iOS)之间通信的桥梁,允许 Dart 代码调用原生 API,或原生代码向 Flutter 推送事件。


一、通信机制概述

复制代码
Flutter (Dart)          Platform Channel          原生 (Java/Swift)
     │                                                    │
     │  MethodChannel.invokeMethod('getBatteryLevel')     │
     │ ─────────────────────────────────────────────────► │
     │                                                    │ 执行原生代码
     │  result: 85                                        │
     │ ◄───────────────────────────────────────────────── │
     │                                                    │
     │  EventChannel.receiveBroadcastStream()             │
     │ ─────────────────────────────────────────────────► │
     │  event: {charging: true}                           │
     │ ◄───────────────────────────────────────────────── │ 原生推送事件

三种 Channel 类型:

Channel 方向 适用场景
MethodChannel 双向,单次调用 调用原生 API,获取返回值
EventChannel 原生 → Flutter,持续流 传感器、电量、网络状态变化
BasicMessageChannel 双向,自定义编解码 低频消息传递

二、MethodChannel

2.1 Flutter 侧

dart 复制代码
class BatteryService {
  static const _channel = MethodChannel('com.example.app/battery');

  static Future<int> getBatteryLevel() async {
    try {
      final level = await _channel.invokeMethod<int>('getBatteryLevel');
      return level ?? -1;
    } on PlatformException catch (e) {
      debugPrint('Battery error: ${e.message}');
      return -1;
    } on MissingPluginException {
      debugPrint('Battery plugin not available');
      return -1;
    }
  }

  static Future<bool> isCharging() async {
    final result = await _channel.invokeMethod<bool>('isCharging');
    return result ?? false;
  }
}

2.2 Android 侧(Kotlin)

kotlin 复制代码
// android/app/src/main/kotlin/.../MainActivity.kt
class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.app/battery"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)

        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
            .setMethodCallHandler { call, result ->
                when (call.method) {
                    "getBatteryLevel" -> {
                        val level = getBatteryLevel()
                        if (level != -1) result.success(level)
                        else result.error("UNAVAILABLE", "Battery not available", null)
                    }
                    "isCharging" -> {
                        result.success(isDeviceCharging())
                    }
                    else -> result.notImplemented()
                }
            }
    }

    private fun getBatteryLevel(): Int {
        val batteryManager = getSystemService(BATTERY_SERVICE) as BatteryManager
        return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
    }
}

2.3 iOS 侧(Swift)

swift 复制代码
// ios/Runner/AppDelegate.swift
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions options: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller = window?.rootViewController as! FlutterViewController
        let channel = FlutterMethodChannel(
            name: "com.example.app/battery",
            binaryMessenger: controller.binaryMessenger
        )

        channel.setMethodCallHandler { call, result in
            switch call.method {
            case "getBatteryLevel":
                let device = UIDevice.current
                device.isBatteryMonitoringEnabled = true
                if device.batteryState == .unknown {
                    result(FlutterError(
                        code: "UNAVAILABLE",
                        message: "Battery not available",
                        details: nil
                    ))
                } else {
                    result(Int(device.batteryLevel * 100))
                }
            default:
                result(FlutterMethodNotImplemented)
            }
        }

        return super.application(application, didFinishLaunchingWithOptions: options)
    }
}

三、EventChannel

3.1 Flutter 侧(监听流)

dart 复制代码
class NetworkStatusService {
  static const _channel = EventChannel('com.example.app/network');

  static Stream<bool> get onConnectivityChanged {
    return _channel
        .receiveBroadcastStream()
        .map((event) => event as bool);
  }
}

// 使用
class ConnectivityWidget extends StatefulWidget { ... }
class _State extends State<ConnectivityWidget> {
  StreamSubscription? _sub;
  bool _isConnected = true;

  @override
  void initState() {
    super.initState();
    _sub = NetworkStatusService.onConnectivityChanged.listen((connected) {
      setState(() => _isConnected = connected);
    });
  }

  @override
  void dispose() {
    _sub?.cancel();
    super.dispose();
  }
}

3.2 Android 侧(Kotlin)

kotlin 复制代码
class ConnectivityStreamHandler(context: Context) : EventChannel.StreamHandler {
    private val connectivityManager =
        context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
    private var callback: ConnectivityManager.NetworkCallback? = null

    override fun onListen(arguments: Any?, events: EventChannel.EventSink) {
        callback = object : ConnectivityManager.NetworkCallback() {
            override fun onAvailable(network: Network) {
                events.success(true)
            }
            override fun onLost(network: Network) {
                events.success(false)
            }
        }
        connectivityManager.registerDefaultNetworkCallback(callback!!)
    }

    override fun onCancel(arguments: Any?) {
        callback?.let { connectivityManager.unregisterNetworkCallback(it) }
        callback = null
    }
}

四、BasicMessageChannel

dart 复制代码
// 双向通信(不需要请求-响应模式,适合消息传递)
static const _messageChannel = BasicMessageChannel<String>(
  'com.example.app/messages',
  StringCodec(),
);

// 发送消息到原生
await _messageChannel.send('Hello from Flutter');

// 监听来自原生的消息
_messageChannel.setMessageHandler((message) async {
  print('Message from native: $message');
  return 'Flutter received: $message'; // 可选的回复
});

小结

Channel 场景
MethodChannel Flutter 调原生 API,一次性调用返回结果
EventChannel 原生持续推送数据(传感器/网络/电量)
BasicMessageChannel 轻量双向消息

👉 下一节:9.2 原生插件开发

相关推荐
恋猫de小郭10 小时前
Android CLI 支持 AI Agent 通过 Device Streaming 调试云真机
android·前端·flutter
m0_738185821 天前
Flutter 鸿蒙化实战:flutter_scankit 适配 OpenHarmony,华为 ScanKit 扫码
flutter·华为·harmonyos·鸿蒙
事圆则缓1 天前
Flutter 开发鸿蒙实战:从 OpenHarmony 适配版到 HAP 构建与插件接入
flutter·华为·harmonyos
天空之城--1 天前
Android一周动态:Android 18首次官宣、Compose Material3 1.4转正(5趋势+5资讯)
android·人工智能·flutter·架构·android jetpack
恋猫de小郭1 天前
Meta 分享怎么用 AI 迁移 Compose 项目不烧心
android·前端·flutter
EatFan1 天前
Flutter 鸿蒙适配实践 2026:从环境搭建、混合渲染到 OpenTelemetry 性能基建
flutter·华为·harmonyos·openharmony·opentelemetry·鸿蒙适配·impeller
m0_738185821 天前
Flutter 鸿蒙化实战:flutter_secure_storage 适配 OpenHarmony,敏感数据安全存储
安全·flutter·华为·harmonyos·鸿蒙
传奇开心果编程2 天前
【现代声明式UI学与练】第1课 从命令式UI到声明式UI
学习·flutter·ui·swiftui·react·android jetpack
m0_738185822 天前
Flutter 鸿蒙化实战:flutter_nfc_kit 适配 OpenHarmony,NFC 读写一步到位
flutter·华为·harmonyos·鸿蒙
恋猫de小郭2 天前
KMP 又改了编译流程, Separate Compilation 禁止了 `commonMain` 的依赖穿透
android·前端·flutter