flutter与原生交互的具体实现

PlatformChannel功能简介 PlatformChannel分为BasicMessageChannel、MethodChannel以及EventChannel三种。其各自的主要用途如下:

  • BasicMessageChannel: 用于传递数据。Flutter与原生项目的资源是不共享的,可以通过BasicMessageChannel来获取Native项目的图标等资源。
  • MethodChannel: 传递方法调用。Flutter主动调用Native的方法,并获取相应的返回值。比如获取系统电量,发起Toast等调用系统API,可以通过这个来完成。
  • EventChannel: 传递事件。这里是Native将事件通知到Flutter。比如Flutter需要监听网络情况,这时候MethodChannel就无法胜任这个需求了。EventChannel可以将Flutter的一个监听交给Native,Native去做网络广播的监听,当收到广播后借助EventChannel调用Flutter注册的监听,完成对Flutter的事件通知。
其实可以看到,无论传方法还是传事件,其本质上都是数据的传递,不过上层包的一些逻辑不同而已。
具体实现 BasicMessageChannel 初始直接在Native端发送消息, flutter是收不到的, 因为还没有执行接收监听方法, 所以在Native端发送消息, 需要注意一下时机
flutter
static const messageChannel = const BasicMessageChannel('samples.flutter.io/message', StandardMessageCodec()); static const messageChannel2 = const BasicMessageChannel('samples.flutter.io/message2', StandardMessageCodec()); Future sendMessage() async { String reply = await messageChannel.send('发送给Native端的数据'); print('reply: $reply'); return reply; }void receiveMessage() { messageChannel2.setMessageHandler((message) async { print('message: $message'); return '返回Native端的数据'; }); }@override void initState() { // TODO: implement initState super.initState(); receiveMessage(); sendMessage(); }

【flutter与原生交互的具体实现】ios
// 初始化定义 FlutterBasicMessageChannel* messageChannel = [FlutterBasicMessageChannel messageChannelWithName:@"samples.flutter.io/message" binaryMessenger:controller]; // 接收消息监听 [messageChannel setMessageHandler:^(id message, FlutterReply callback) { NSLog(message); callback(@"返回flutter端的数据"); }]; // 触发事件执行FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; FlutterBasicMessageChannel* messageChannel2 = [FlutterBasicMessageChannel messageChannelWithName:@"samples.flutter.io/message2" binaryMessenger:controller]; // 发送消息 [messageChannel2 sendMessage:(@"发送给flutter的数据") reply:^(id reply) { NSLog(reply); }];

android
BasicMessageChannel messageChannel = new BasicMessageChannel(getFlutterView(), "samples.flutter.io/message", StandardMessageCodec.INSTANCE); // 接收消息监听 messageChannel.setMessageHandler(new BasicMessageChannel.MessageHandler() { @Override public void onMessage(Object o, BasicMessageChannel.Reply reply) { System.out.println("onMessage: " + o); reply.reply("返回给flutter的数据"); } }); // 触发事件执行BasicMessageChannel messageChannel2 = new BasicMessageChannel(getFlutterView(), "samples.flutter.io/message2", StandardMessageCodec.INSTANCE); // 发送消息 messageChannel2.send("发送给flutter的数据", new BasicMessageChannel.Reply() { @Override public void reply(Object o) {System.out.println("onReply: " + o); } });
MethodChannel flutter
static const platform = const MethodChannel('samples.flutter.io/battery'); Future _getBatteryLevel() async { String batteryLevel; try { final int result = await platform.invokeMethod('getBatteryLevel'); batteryLevel = 'Battery level at $result % .'; } on PlatformException catch (e) { batteryLevel = "Failed to get battery level: '${e.message}'."; }setState(() { _batteryLevel = batteryLevel; }); }// 执行_getBatteryLevel方法

ios
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; FlutterMethodChannel* batteryChannel = [FlutterMethodChannel methodChannelWithName:@"samples.flutter.io/battery" binaryMessenger:controller]; [batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) { // TODO if ([@"getBatteryLevel" isEqualToString:call.method]) { int batteryLevel = [self getBatteryLevel]; if (batteryLevel == -1) {result([FlutterError errorWithCode:@"UNAVAILABLE" message:@"Battery info unavailable" details:nil]); } else { result(@(batteryLevel)); } } else { result(FlutterMethodNotImplemented); } }]; - (int)getBatteryLevel { UIDevice* device = UIDevice.currentDevice; device.batteryMonitoringEnabled = YES; if (device.batteryState == UIDeviceBatteryStateUnknown) { return -1; } else { return (int)(device.batteryLevel * 100); } }

android
new MethodChannel(getFlutterView(), CHANNEL).setMethodCallHandler( new MethodCallHandler() { @Override public void onMethodCall(MethodCall call, Result result) { // TODO if (call.method.equals("getBatteryLevel")) { int batteryLevel = getBatteryLevel(); if (batteryLevel != -1) { result.success(batteryLevel); } else { result.error("UNAVAILABLE", "Battery level not available.", null); } } else { result.notImplemented(); } } } ); private int getBatteryLevel() { int batteryLevel = -1; if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { BatteryManager batteryManager = (BatteryManager) getSystemService(BATTERY_SERVICE); batteryLevel = batteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY); } else { Intent intent = new ContextWrapper(getApplicationContext()). registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); batteryLevel = (intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) * 100) / intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1); }return batteryLevel; }

FlutterEventChannel flutter
static const EventChannel _eventChannel = const EventChannel('samples.flutter.io/test'); void _onEvent(Object event) { print('返回的内容: $event'); }void _onError(Object error) { print('返回的错误'); }@override void initState() { // TODO: implement initState super.initState(); // 监听开始 _eventChannel.receiveBroadcastStream().listen(_onEvent, onError: _onError); }

ios
FlutterViewController* controller = (FlutterViewController*)self.window.rootViewController; FlutterEventChannel* eventChannel = [FlutterEventChannel eventChannelWithName:@"samples.flutter.io/test" binaryMessenger:controller]; [eventChannel setStreamHandler:self]; FlutterEventSinkeventSink; // // 这个onListen是Flutter端开始监听这个channel时的回调,第二个参数 EventSink是用来传数据的载体。 - (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(FlutterEventSink)events { eventSink = events; // arguments flutter给native的参数 // 回调给flutter, 建议使用实例指向,因为该block可以使用多次 if (events) { events(@"主动发送通知到flutter"); }// 监听电池状态 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onBatteryStateDidChange:) name:UIDeviceBatteryStateDidChangeNotification object:nil]; return nil; }/// flutter不再接收 - (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments { // arguments flutter给native的参数 [[NSNotificationCenter defaultCenter] removeObserver:self]; eventSink = nil; return nil; }- (void)onBatteryStateDidChange:(NSNotification*)notification { if (eventSink == nil) return; UIDeviceBatteryState state = [[UIDevice currentDevice] batteryState]; switch (state) { case UIDeviceBatteryStateFull: case UIDeviceBatteryStateCharging: eventSink(@"charging"); break; case UIDeviceBatteryStateUnplugged: eventSink(@"discharging"); break; default: eventSink([FlutterError errorWithCode:@"UNAVAILABLE" message:@"Charging status unavailable" details:nil]); break; } }

android
new EventChannel(getFlutterView(), CHANNEL2).setStreamHandler( new EventChannel.StreamHandler() { @Override public void onListen(Object o, EventChannel.EventSink eventSink) { this.eventSink = eventSink; handler.sendEmptyMessageDelayed(1, 1000); }@Override public void onCancel(Object o) {}private EventChannel.EventSink eventSink; private int count = 0; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); eventSink.success((count++) + "主动发送消息给flutter"); //handler.sendEmptyMessageDelayed(1,1000); } }; } );

源码
github: https://github.com/shimuhui/flutterToNative

    推荐阅读