在Flutter中通过PlatformChannel与原生 Android 和 iOS 进行通信,其中 PlatformChannel 分为三种:
MethodChannel:用于传递方法调用。Flutter主动调用Native的方法,并获取相应的返回值。
EventChannel:用于数据流(event streams)的通信。
BasicMessageChannel:用于传递字符串和半结构化的信息。
一、MethodChannel(方法通道)
基本原理:
MethodChannel 允许在 Flutter 和原生平台之间进行双向方法调用。通过定义一个特定的通道名称,Flutter 和原生代码都可以使用这个通道来发送和接收消息。
在 Flutter 端,使用
MethodChannel
类创建一个通道实例,并通过invokeMethod
方法调用原生平台的方法,或者使用setMethodCallHandler
方法设置一个处理原生平台调用 Flutter 方法的回调。在原生平台(Android 和 iOS)端,分别通过特定的代码来接收来自 Flutter 的方法调用,并可以通过通道向 Flutter 端返回结果。
示例:
Flutter 端调用原生 Android 方法:
import 'package:flutter/services.dart'; final MethodChannel _channel = MethodChannel('com.example.channel'); Future getPlatformVersion() async { try { final String version = await _channel.invokeMethod('getAndroidVersion'); return version; } on PlatformException catch (e) { return "Failed to get platform version: '${e.message}'."; } }
原生 Android 端响应 Flutter 调用:
import io.flutter.plugin.common.MethodCall; import io.flutter.plugin.common.MethodChannel; import io.flutter.plugin.common.MethodChannel.MethodCallHandler; import io.flutter.plugin.common.MethodChannel.Result; import android.os.Build; import android.util.Log; public class MainActivity extends FlutterActivity { private static final String CHANNEL = "com.example.channel"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler( new MethodCallHandler() { @Override public void onMethodCall(MethodCall call, Result result) { if (call.method.equals("getAndroidVersion")) { result.success(Build.VERSION.RELEASE); } else { result.notImplemented(); } } }); } }
Flutter 端调用原生 iOS 方法:
import 'package:flutter/services.dart'; final MethodChannel _channel = MethodChannel('com.example.channel'); Future getPlatformVersion() async { try { final String version = await _channel.invokeMethod('getiOSVersion'); return version; } on PlatformException catch (e) { return "Failed to get platform version: '${e.message}'."; } }
原生 iOS 端响应 Flutter 调用:
import Flutter import UIKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel(name: "com.example.channel", binaryMessenger: controller.binaryMessenger) channel.setMethodCallHandler({ (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in if call.method == "getiOSVersion" { result(UIDevice.current.systemVersion) } else { result(FlutterMethodNotImplemented) } }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
二、EventChannel(事件通道)
基本原理:
EventChannel 用于从原生平台向 Flutter 端发送数据流。原生平台可以不断地发送事件,Flutter 端通过设置事件监听器来接收这些事件。
在 Flutter 端,使用
EventChannel
类创建一个通道实例,并通过receiveBroadcastStream
方法获取一个流,然后可以使用StreamBuilder
等方式监听这个流。在原生平台端,通过特定的方式生成事件流并发送给 Flutter。
示例:
Flutter 端监听原生 Android 事件:
import 'package:flutter/services.dart'; final EventChannel _eventChannel = EventChannel('com.example.event'); StreamSubscription _subscription; void startListening() { _subscription = _eventChannel.receiveBroadcastStream().listen((event) { print('Received event from Android: $event'); }, onError: (error) { print('Error receiving event: $error'); }, onDone: () { print('Event stream completed.'); }); } void stopListening() { _subscription?.cancel(); }
原生 Android 端发送事件到 Flutter:
import io.flutter.plugin.common.EventChannel; import io.flutter.plugin.common.EventChannel.EventSink; import android.util.Log; public class EventEmitterService extends Service { private static final String TAG = "EventEmitterService"; private EventChannel.EventSink _eventSink; @Override public void onCreate() { super.onCreate(); new EventChannel(getApplicationContext().getMainLooper(), "com.example.event").setStreamHandler( new EventChannel.StreamHandler() { @Override public void onListen(Object args, EventSink eventSink) { _eventSink = eventSink; startEmittingEvents(); } @Override public void onCancel(Object args) { _eventSink = null; } }); } private void startEmittingEvents() { new Thread(new Runnable() { @Override public void run() { while (_eventSink!= null) { _eventSink.success("Event from Android"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } }
Flutter 端监听原生 iOS 事件:
import 'package:flutter/services.dart'; final EventChannel _eventChannel = EventChannel('com.example.event'); StreamSubscription _subscription; void startListening() { _subscription = _eventChannel.receiveBroadcastStream().listen((event) { print('Received event from iOS: $event'); }, onError: (error) { print('Error receiving event: $error'); }, onDone: () { print('Event stream completed.'); }); } void stopListening() { _subscription?.cancel(); }
原生 iOS 端发送事件到 Flutter:
import Flutter import UIKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let eventChannel = FlutterEventChannel(name: "com.example.event", binaryMessenger: controller.binaryMessenger) eventChannel.setStreamHandler(MyEventStreamHandler()) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } class MyEventStreamHandler: NSObject, FlutterStreamHandler { private var eventSink: FlutterEventSink? func onListen(withArguments arguments: Any?, eventSink: @escaping FlutterEventSink) -> FlutterError? { self.eventSink = eventSink startEmittingEvents() return nil } func onCancel(withArguments arguments: Any?) -> FlutterError? { eventSink = nil return nil } private func startEmittingEvents() { DispatchQueue.global().async { while self.eventSink!= nil { self.eventSink!("Event from iOS") sleep(5) } } } }
三、BasicMessageChannel(基本消息通道)
基本原理:
BasicMessageChannel 用于在 Flutter 和原生平台之间进行异步消息传递。可以发送任意类型的消息,并可以处理消息的回复。
在 Flutter 端,使用
BasicMessageChannel
类创建一个通道实例,并通过send
方法发送消息,设置一个处理原生平台回复的回调。在原生平台端,接收来自 Flutter 的消息,并可以通过通道向 Flutter 端发送回复。
示例:
Flutter 端发送消息到原生 Android 并接收回复:
import 'package:flutter/services.dart'; final BasicMessageChannel _messageChannel = BasicMessageChannel ('com.example.message', StringCodec()); Future sendMessageToAndroid(String message) async { try { final String reply = await _messageChannel.send(message); return reply; } on PlatformException catch (e) { return "Failed to send message: '${e.message}'."; } }
原生 Android 端接收 Flutter 消息并回复:
import io.flutter.plugin.common.BasicMessageChannel; import io.flutter.plugin.common.BasicMessageChannel.MessageHandler; import io.flutter.plugin.common.BasicMessageChannel.Reply; import android.util.Log; public class MainActivity extends FlutterActivity { private static final String CHANNEL = "com.example.message"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); final BasicMessageChannel messageChannel = new BasicMessageChannel<>( getFlutterView(), CHANNEL, StringCodec.INSTANCE); messageChannel.setMessageHandler( new MessageHandler () { @Override public void onMessage(String message, Reply reply) { Log.d( "MessageChannel", "Received message from Flutter: " + message); reply.reply( "Reply from Android: " + message); } }); } }
Flutter 端发送消息到原生 iOS 并接收回复:
import 'package:flutter/services.dart'; final BasicMessageChannel _messageChannel = BasicMessageChannel ('com.example.message', StringCodec()); Future sendMessageToiOS(String message) async { try { final String reply = await _messageChannel.send(message); return reply; } on PlatformException catch (e) { return "Failed to send message: '${e.message}'."; } }
原生 iOS 端接收 Flutter 消息并回复:
import Flutter import UIKit @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let messageChannel = FlutterBasicMessageChannel(name: "com.example.message", binaryMessenger: controller.binaryMessenger, codec: FlutterStringCodec.sharedInstance()) messageChannel.setMessageHandler({ (message, reply) in print("Received message from Flutter: \(message?? "")") reply("Reply from iOS: \(message?? "")") }) GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
--- END ---
热门跟贴