flutter 与 Android iOS 通信?以及实现原理(一)

Flutter 与原生(Android/iOS)的通信通过 平台通道(Platform Channel) 实现,支持三种通信模式:方法调用事件流消息传递

一、通信方式

通信方式 方向 特点 适用场景
MethodChannel 双向 一次性调用,有返回值 获取电池电量、打开相机
EventChannel 原生 → Flutter 持续事件流 传感器数据、位置更新
BasicMessageChannel 双向 自定义编解码器 复杂数据传递、长连接

二、MethodChannel(方法通道)

1. 工作原理

2. Flutter 端实现

复制代码
// 1. 创建 MethodChannel
import 'package:flutter/services.dart';

class BatteryService {
  static const platform = MethodChannel('com.example.battery');
  
  // 2. 调用原生方法
  Future<int> getBatteryLevel() async {
    try {
      final int result = await platform.invokeMethod('getBatteryLevel');
      return result;
    } on PlatformException catch (e) {
      print("错误: ${e.message}");
      return -1;
    }
  }
  
  // 带参数的调用
  Future<void> setVolume(double volume) async {
    await platform.invokeMethod('setVolume', {'volume': volume});
  }
}

3. Android 端实现

复制代码
// MainActivity.kt
import androidx.annotation.NonNull
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.os.BatteryManager
import android.content.Context

class MainActivity: FlutterActivity() {
    private val CHANNEL = "com.example.battery"
    
    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
            .setMethodCallHandler { call, result ->
                when (call.method) {
                    "getBatteryLevel" -> {
                        val batteryLevel = getBatteryLevel()
                        if (batteryLevel != -1) {
                            result.success(batteryLevel)
                        } else {
                            result.error("UNAVAILABLE", "无法获取电量", null)
                        }
                    }
                    "setVolume" -> {
                        val volume = call.argument<Double>("volume")
                        setSystemVolume(volume)
                        result.success(null)
                    }
                    else -> result.notImplemented()
                }
            }
    }
    
    private fun getBatteryLevel(): Int {
        val batteryManager = getSystemService(Context.BATTERY_SERVICE) as BatteryManager
        return batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
    }
}

4. iOS 端实现

复制代码
// AppDelegate.swift
import UIKit
import Flutter

@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller = window?.rootViewController as! FlutterViewController
        let batteryChannel = FlutterMethodChannel(
            name: "com.example.battery",
            binaryMessenger: controller.binaryMessenger
        )
        
        batteryChannel.setMethodCallHandler { [weak self] (call, result) in
            switch call.method {
            case "getBatteryLevel":
                self?.getBatteryLevel(result: result)
            case "setVolume":
                if let args = call.arguments as? [String: Any],
                   let volume = args["volume"] as? Double {
                    self?.setSystemVolume(volume)
                    result(nil)
                } else {
                    result(FlutterError(code: "INVALID_ARGS", message: "无效参数", details: nil))
                }
            default:
                result(FlutterMethodNotImplemented)
            }
        }
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    private func getBatteryLevel(result: FlutterResult) {
        let device = UIDevice.current
        device.isBatteryMonitoringEnabled = true
        let level = device.batteryLevel
        if level < 0 {
            result(FlutterError(code: "UNAVAILABLE", message: "无法获取电量", details: nil))
        } else {
            result(Int(level * 100))
        }
    }
}

三、EventChannel(事件通道)

1. 工作原理

2. Flutter 端实现

复制代码
import 'package:flutter/services.dart';

class SensorService {
  static const EventChannel _eventChannel = EventChannel('com.example.sensor');
  
  // 创建事件流
  Stream<dynamic> get sensorStream async* {
    yield* _eventChannel.receiveBroadcastStream();
  }
  
  // 监听传感器数据
  void listenSensor() {
    sensorStream.listen(
      (event) {
        print('传感器数据: $event');
      },
      onError: (error) {
        print('错误: $error');
      },
      cancelOnError: false,
    );
  }
}

// 使用示例
class SensorWidget extends StatefulWidget {
  @override
  _SensorWidgetState createState() => _SensorWidgetState();
}

class _SensorWidgetState extends State<SensorWidget> {
  final SensorService _sensorService = SensorService();
  StreamSubscription? _subscription;
  
  @override
  void initState() {
    super.initState();
    _startListening();
  }
  
  void _startListening() {
    _subscription = _sensorService.sensorStream.listen(
      (data) {
        setState(() {
          // 更新 UI
        });
      },
    );
  }
  
  @override
  void dispose() {
    _subscription?.cancel();
    super.dispose();
  }
  
  @override
  Widget build(BuildContext context) {
    return Container();
  }
}

3. Android 端实现

复制代码
class MainActivity: FlutterActivity() {
    private val EVENT_CHANNEL = "com.example.sensor"
    private var eventSink: EventChannel.EventSink? = null
    private var sensorManager: SensorManager? = null
    private var sensorEventListener: SensorEventListener? = null
    
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        
        EventChannel(flutterEngine.dartExecutor.binaryMessenger, EVENT_CHANNEL)
            .setStreamHandler(object : EventChannel.StreamHandler {
                override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                    eventSink = events
                    startSensorListening()
                }
                
                override fun onCancel(arguments: Any?) {
                    stopSensorListening()
                    eventSink = null
                }
            })
    }
    
    private fun startSensorListening() {
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        val accelerometer = sensorManager?.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
        
        sensorEventListener = object : SensorEventListener {
            override fun onSensorChanged(event: SensorEvent?) {
                event?.let {
                    val x = it.values[0]
                    val y = it.values[1]
                    val z = it.values[2]
                    eventSink?.success(mapOf("x" to x, "y" to y, "z" to z))
                }
            }
            
            override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
        }
        
        sensorEventListener?.let {
            sensorManager?.registerListener(it, accelerometer, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }
    
    private fun stopSensorListening() {
        sensorEventListener?.let {
            sensorManager?.unregisterListener(it)
        }
    }
}

4. iOS 端实现

复制代码
class AppDelegate: FlutterAppDelegate {
    private let EVENT_CHANNEL = "com.example.sensor"
    private var eventSink: FlutterEventSink?
    private var motionManager: CMMotionManager?
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        let controller = window?.rootViewController as! FlutterViewController
        let eventChannel = FlutterEventChannel(
            name: EVENT_CHANNEL,
            binaryMessenger: controller.binaryMessenger
        )
        
        eventChannel.setStreamHandler(self)
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

extension AppDelegate: FlutterStreamHandler {
    func onListen(withArguments arguments: Any?,
                  eventSink: @escaping FlutterEventSink) -> FlutterError? {
        self.eventSink = eventSink
        startAccelerometerUpdates()
        return nil
    }
    
    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        stopAccelerometerUpdates()
        eventSink = nil
        return nil
    }
    
    private func startAccelerometerUpdates() {
        motionManager = CMMotionManager()
        motionManager?.accelerometerUpdateInterval = 0.1
        motionManager?.startAccelerometerUpdates(to: .main) { [weak self] data, error in
            if let data = data {
                self?.eventSink?([
                    "x": data.acceleration.x,
                    "y": data.acceleration.y,
                    "z": data.acceleration.z
                ])
            }
        }
    }
    
    private func stopAccelerometerUpdates() {
        motionManager?.stopAccelerometerUpdates()
        motionManager = nil
    }
}

四、BasicMessageChannel(消息通道)

1. Flutter 端实现

复制代码
import 'package:flutter/services.dart';
import 'dart:convert';

class MessageService {
  static const BasicMessageChannel _channel = BasicMessageChannel(
    'com.example.messages',
    StringCodec(),  // 或 JSONMessageCodec(), StandardMessageCodec()
  );
  
  // 发送消息并接收回复
  Future<String> sendMessage(String message) async {
    final reply = await _channel.send(message);
    return reply.toString();
  }
  
  // 设置消息处理器
  void setMessageHandler() {
    _channel.setMessageHandler((message) async {
      print('收到消息: $message');
      return '回复: ${message.toString().toUpperCase()}';
    });
  }
}

// 使用自定义编解码器
class User {
  final String name;
  final int age;
  
  User(this.name, this.age);
  
  Map<String, dynamic> toJson() => {'name': name, 'age': age};
  
  static User fromJson(Map<String, dynamic> json) =>
      User(json['name'], json['age']);
}

class UserMessageChannel {
  static const BasicMessageChannel _channel = BasicMessageChannel(
    'com.example.user',
    StandardMessageCodec(),  // 支持更多类型
  );
  
  Future<User?> getUser() async {
    final result = await _channel.send('getUser');
    if (result != null && result is Map) {
      return User.fromJson(result);
    }
    return null;
  }
}

2. Android 端实现

复制代码
class MainActivity: FlutterActivity() {
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        
        BasicMessageChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "com.example.messages",
            StringCodec.INSTANCE
        ).setMessageHandler { message, reply ->
            println("收到消息: $message")
            reply.reply("原生回复: ${message?.toString()?.uppercase()}")
        }
        
        // 使用 JSON 编解码器
        BasicMessageChannel(
            flutterEngine.dartExecutor.binaryMessenger,
            "com.example.user",
            StandardMessageCodec.INSTANCE
        ).setMessageHandler { message, reply ->
            when (message) {
                "getUser" -> {
                    val user = mapOf("name" to "Alice", "age" to 25)
                    reply.reply(user)
                }
                else -> reply.reply(null)
            }
        }
    }
}

五、实现原理

1. 核心架构

2. 序列化机制

Flutter 使用 StandardMessageCodec 进行数据序列化,支持的数据类型:

Dart 类型 Android 类型 iOS 类型
null null nil
bool Boolean NSNumber(bool)
int Integer/Long NSNumber(int)
double Double NSNumber(double)
String String NSString
Uint8List byte[] FlutterStandardTypedData
List ArrayList NSArray
Map HashMap NSDictionary

3. 线程模型

复制代码
// Flutter 端调用
await platform.invokeMethod('getData');  // 在 UI 线程

// Android 端处理
override fun onMethodCall(call: MethodCall, result: Result) {
    // 默认在主线程(UI 线程)执行
    Thread {
        // 耗时操作
        val data = heavyComputation()
        
        // 必须切回主线程返回结果
        Handler(Looper.getMainLooper()).post {
            result.success(data)
        }
    }.start()
}

// 使用协程优化
override fun onMethodCall(call: MethodCall, result: Result) {
    CoroutineScope(Dispatchers.IO).launch {
        val data = heavyComputation()
        withContext(Dispatchers.Main) {
            result.success(data)
        }
    }
}

4. 消息队列机制

复制代码
// Flutter Engine 层(简化)
class PlatformMessageRouter {
  void HandlePlatformMessage(const PlatformMessage& message) {
    // 1. 反序列化消息
    auto decoded = codec_.DecodeMessage(message);
    
    // 2. 查找对应的 Channel Handler
    auto handler = GetHandler(message.channel);
    
    // 3. 在 Platform Thread 执行
    TaskRunner::PostTask([handler, decoded]() {
      auto result = handler->OnMessage(decoded);
      
      // 4. 序列化结果并返回
      SendPlatformMessageResponse(result);
    });
  }
};
相关推荐
Lambert_lin03 小时前
Android grade9.0 之后 自定义apk 名称
android·kotlin
fengci.4 小时前
ctfshow其他(web408-web432)
android·开发语言·前端·学习·php
Kapaseker4 小时前
“点击显示全文” — Compose 实现
android·kotlin
lxysbly4 小时前
安卓土星ss模拟器下载(支持中文、金手指)
android
2601_949593654 小时前
Flutter OpenHarmony 三方库 path_provider 文件路径获取适配详解
flutter
冰凌时空4 小时前
30 Apps 第 1 天:待办清单 App —— 数据层完整设计
前端·ios
哈撒Ki4 小时前
快速入门 Dart 语言
前端·flutter·dart
小蜜蜂嗡嗡5 小时前
flutter 自定义走马灯,内部为Widget控件的走马灯效果二:横向无限匀速滚动+每个Item与屏幕左侧对齐时,停靠3秒再继续滚动
开发语言·flutter
2501_915909065 小时前
Xcode从入门到精通:全面解析iOS开发IDE的核心功能与实际应用指南
ide·vscode·ios·个人开发·xcode·swift·敏捷流程