Flutter 与原生通信

Flutter 与原生之间的通信主要基于通道机制,包括 MethodChannel、EventChannel 和 BasicMessageChannel。

  • MethodChannel:用于 Flutter 与原生之间的方法调用,实现双向通信,适合一次性的方法调用并获取返回值,如 Flutter调用原生拍照功能并获取照片路径。
  • EventChannel:主要用于原生向 Flutter 发送数据流,例如原生端将传感器数据实时传递给 Flutter 端。
  • BasicMessageChannel:用于 Flutter 与原生之间传递字符串、二进制数据等基本类型的数据,可进行简单的数据交换。

1. Flutter 调用原生

Flutter 端代码

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Flutter 调用原生示例'),
        ),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              const platform = MethodChannel('com.example.flutter_native');
              try {
                final String result = await platform.invokeMethod('getNativeMessage');
                print('原生返回的消息: $result');
              } on PlatformException catch (e) {
                print('调用原生方法失败: ${e.message}');
              }
            },
            child: const Text('调用原生方法'),
          ),
        ),
      ),
    );
  }
}

在 Flutter 端,创建 MethodChannel 实例,使用 invokeMethod 方法调用原生端的 getNativeMessage 方法,并处理返回结果。

安卓原生端代码(Kotlin)

package com.example.flutter_native

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.flutter_native"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            if (call.method == "getNativeMessage") {
                result.success("这是来自安卓原生的消息")
            } else {
                result.notImplemented()
            }
        }
    }
}

在安卓端,创建 MethodChannel 实例,设置方法调用处理程序,当接收到 getNativeMessage 方法调用时,返回消息给 Flutter 端。

iOS 原生端代码(Swift)

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.flutter_native", binaryMessenger: controller.binaryMessenger)
        channel.setMethodCallHandler { [weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) in
            if call.method == "getNativeMessage" {
                result("这是来自 iOS 原生的消息")
            } else {
                result(FlutterMethodNotImplemented)
            }
        }
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

在 iOS 端,创建 FlutterMethodChannel 实例,设置方法调用处理程序,处理 getNativeMessage 方法调用并返回消息给 Flutter 端。

2. 原生调用 Flutter

Flutter 端代码

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    const platform = MethodChannel('com.example.native_flutter');
    platform.setMethodCallHandler((call) async {
      if (call.method == "getFlutterMessage") {
        return "这是来自 Flutter 的消息";
      }
      return null;
    });

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('原生调用 Flutter 示例'),
        ),
        body: const Center(
          child: Text('等待原生调用...'),
        ),
      ),
    );
  }
}

在 Flutter 端,创建 MethodChannel 实例,使用 setMethodCallHandler 方法设置处理原生调用的回调,当接收到 getFlutterMessage 方法调用时,返回消息给原生端。

安卓原生端代码(Kotlin)

package com.example.native_flutter

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.native_flutter"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        val channel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
        channel.invokeMethod("getFlutterMessage", null) { result ->
            println("Flutter 返回的消息: $result")
        }
    }
}

在安卓端,创建 MethodChannel 实例,使用 invokeMethod 方法调用 Flutter 端的 getFlutterMessage 方法,并处理返回结果。

iOS 原生端代码(Swift)

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.native_flutter", binaryMessenger: controller.binaryMessenger)
        channel.invokeMethod("getFlutterMessage", arguments: nil) { (result) in
            if let message = result as? String {
                print("Flutter 返回的消息: \(message)")
            }
        }
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

在 iOS 端,创建 FlutterMethodChannel 实例,使用 invokeMethod 方法调用 Flutter 端的 getFlutterMessage 方法,并处理返回结果。

3. EventChannel和BasicMessageChannel

EventChannel和BasicMessageChannel跟上面MethodChannel大同小异。

EventChannel

Flutter端

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    const eventChannel = EventChannel('com.example.event_channel');
    eventChannel.receiveBroadcastStream().listen((event) {
      print('接收到原生端的事件: $event');
    }, onError: (error) {
      print('接收事件时出错: $error');
    });

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('EventChannel 示例'),
        ),
        body: const Center(
          child: Text('等待原生端发送事件...'),
        ),
      ),
    );
  }
}

在 Flutter 端,创建 EventChannel 实例,使用 receiveBroadcastStream 方法接收原生端发送的数据流,并通过 listen 方法监听事件。

安卓端

 package com.example.event_channel

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.EventChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.event_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        EventChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setStreamHandler(
            object : EventChannel.StreamHandler {
                private var eventSink: EventChannel.EventSink? = null

                override fun onListen(arguments: Any?, events: EventChannel.EventSink?) {
                    eventSink = events
                    // 模拟每隔 1 秒发送一个事件
                    val timer = android.os.Handler()
                    val runnable = object : Runnable {
                        var counter = 0
                        override fun run() {
                            eventSink?.success("事件 $counter")
                            counter++
                            timer.postDelayed(this, 1000)
                        }
                    }
                    timer.post(runnable)
                }

                override fun onCancel(arguments: Any?) {
                    eventSink = null
                }
            }
        )
    }
}

在安卓端,创建 EventChannel 实例,设置 StreamHandler,在 onListen 方法中模拟每隔 1 秒向 Flutter 端发送一个事件,在 onCancel 方法中取消事件发送。

iOS 原生端代码(Swift)

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_channel", binaryMessenger: controller.binaryMessenger)
        eventChannel.setStreamHandler(
            MyStreamHandler()
        )
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

class MyStreamHandler: NSObject, FlutterStreamHandler {
    var eventSink: FlutterEventSink?
    var timer: Timer?

    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        eventSink = events
        // 模拟每隔 1 秒发送一个事件
        timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] _ in
            var counter = 0
            self?.eventSink?("事件 \(counter)")
            counter += 1
        }
        return nil
    }

    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        timer?.invalidate()
        timer = nil
        eventSink = nil
        return nil
    }
}

在 iOS 端,创建 FlutterEventChannel 实例,设置 StreamHandler,在 onListen 方法中模拟每隔 1 秒向 Flutter 端发送一个事件,在 onCancel 方法中取消事件发送。

BasicMessageChannel

BasicMessageChannel 用于 Flutter 与原生之间传递字符串、二进制数据等基本类型的数据,是一种双向通信机制,适用于简单的数据交换场景,比如传递配置信息、状态信息等。双方可以互相发送和接收数据。

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    const messageChannel = BasicMessageChannel<String>('com.example.message_channel', StringCodec());
    messageChannel.send('来自 Flutter 的消息').then((reply) {
      if (reply != null) {
        print('收到原生端的回复: $reply');
      }
    });

    messageChannel.setMessageHandler((message) async {
      print('收到原生端的消息: $message');
      return 'Flutter 已收到消息';
    });

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('BasicMessageChannel 示例'),
        ),
        body: const Center(
          child: Text('进行消息通信...'),
        ),
      ),
    );
  }
}

在 Flutter 端,创建 BasicMessageChannel 实例,使用 send 方法向原生端发送消息,并处理原生端的回复;使用 setMessageHandler 方法设置处理原生端发送消息的回调。

安卓原生端代码(Kotlin)

package com.example.message_channel

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.BasicMessageChannel
import io.flutter.plugin.common.StringCodec

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.message_channel"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        val messageChannel = BasicMessageChannel<String>(
            flutterEngine.dartExecutor.binaryMessenger,
            CHANNEL,
            StringCodec()
        )
        messageChannel.send("来自安卓原生的消息") { reply ->
            if (reply != null) {
                println("收到 Flutter 的回复: $reply")
            }
        }

        messageChannel.setMessageHandler { message, reply ->
            println("收到 Flutter 的消息: $message")
            reply.reply("安卓原生已收到消息")
        }
    }
}

在安卓端,创建 BasicMessageChannel 实例,使用 send 方法向 Flutter 端发送消息,并处理 Flutter 端的回复;使用 setMessageHandler 方法设置处理 Flutter 端发送消息的回调。

iOS 原生端代码(Swift)

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_channel", binaryMessenger: controller.binaryMessenger, codec: FlutterStringCodec.sharedInstance())
        messageChannel.sendMessage("来自 iOS 原生的消息") { (reply) in
            if let replyMessage = reply as? String {
                print("收到 Flutter 的回复: \(replyMessage)")
            }
        }

        messageChannel.setMessageHandler { (message, reply) in
            if let message = message as? String {
                print("收到 Flutter 的消息: \(message)")
                reply("iOS 原生已收到消息")
            }
        }
        GeneratedPluginRegistrant.register(with: self)
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

在 iOS 端,创建 FlutterBasicMessageChannel 实例,使用 sendMessage 方法向 Flutter 端发送消息,并处理 Flutter 端的回复;使用 setMessageHandler 方法设置处理 Flutter 端发送消息的回调。

另外:采用信鸽pigeons三方库通信也是一个不错的选择

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SY.ZHOU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值