首页 > 其他分享 >Flutter 如何与原生平台通信

Flutter 如何与原生平台通信

时间:2023-08-21 23:03:40浏览次数:37  
标签:原生 String 二进制 平台 通信 message data Flutter

Flutter 是开发跨平台应用程序的完美工具。使用 Flutter,您可以轻松制作出性能卓越、美观大方的应用程序。但为了访问原生平台 API,您需要与原生平台进行通信。

Flutter 只能理解 Dart 语言,原生平台只能理解它们各自的编程语言。那么,Flutter 和原生平台是如何相互通信的呢?

Flutter 如何与原生平台通信_flutter

是 二进制

Flutter 通过传递二进制消息与本机平台通信。为了区分消息,使用了通道。那么我们如何跨平台发送这些二进制消息呢?

我们可以利用 BinaryMessenger 类跨平台发送消息。

BinaryMessenger[1] 类是由 Flutter 团队定义的信使类,它跨 Flutter 平台屏障发送二进制数据。该类还能为接收到的信息注册处理程序。

Flutter 如何与原生平台通信_flutter_02

下面的代码使用 BinaryMessenger 通过通道 foo 跨平台发送二进制信息。

import 'dart:convert'; 
import 'package:flutter/services.dart';
import 'dart:ui' as ui; 

class CustomBinaryMessenger {

  // 将给定值作为二进制信息发送的静态方法。
  static Future<void> givenValue(String data) async {
    // 创建一个缓冲区来保存二进制数据。
    final WriteBuffer buffer = WriteBuffer();

    // Convert the given data string into UTF-8 bytes.
    final List<int> utf8Bytes = utf8.encode(data);

    // Convert the UTF-8 bytes into an Uint8List.
    final Uint8List utf8Int8List = Uint8List.fromList(utf8Bytes);

    // Put the Uint8List into the buffer.
    buffer.putUint8List(utf8Int8List);

    // Get the final binary message data from the buffer.
    final ByteData message = buffer.done();

    // 通过 chaneel `foo` 使用 'Messenger' 类发送二进制消息。
    await Messenger().send('foo', message);

    return;
  }
}

// BinaryMessenger 接口的自定义实现。为了举例说明,我在这里只处理发送
class Messenger implements BinaryMessenger {
  @override
  // 处理传入的平台信息。在这种情况下,它会抛出一个不支持的错误。
  Future<void> handlePlatformMessage(
      String channel, ByteData? data, PlatformMessageResponseCallback? callback) {
    throw UnsupportedError("This platform message handling is not supported.");
  }

  @override
  // 使用 "ui.PlatformDispatcher "向平台发送二进制信息。
  Future<ByteData?>? send(String channel, ByteData? message) {
    // Use the 'ui.PlatformDispatcher' to send the platform message and handle the callback
    ui.PlatformDispatcher.instance.sendPlatformMessage(channel, message, (data) {});

    return null;
  }

  @override
  // 为收到的信息设置一个处理程序。在这种情况下,它会抛出一个不支持的错误。
  void setMessageHandler(String channel, MessageHandler? handler) {
    throw UnsupportedError("Setting message handler is not supported.");
  }
}

在Android上,您可以使用以下代码接收它:

class MainActivity : FlutterActivity() {

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

        // 配置二进制信使以处理来自 Flutter 的消息。
        flutterEngine.dartExecutor.binaryMessenger.setMessageHandler("foo") { message, reply ->
        message?.order(ByteOrder.nativeOrder()) // 确保正确的字节顺序。
        val data = decodeUtf8String(message!!) // 将二进制数据解码为 UTF-8 字符串。
        val x = message.toString() // 将消息转换为字符串以进行演示。
        // 显示带有收到的消息的Toast。
        Toast.makeText(this, "Received message from Flutter: $data", Toast.LENGTH_SHORT).show()
        reply.reply(null)
        }

        // 调用超级方法以完成FlutterEngine配置。
        super.configureFlutterEngine(flutterEngine)
    }

    // 将 ByteBuffer 解码为 UTF-8 字符串的函数。
    private fun decodeUtf8String(byteBuffer: ByteBuffer): String {
        return try {
            val byteArray = ByteArray(byteBuffer.remaining())
            byteBuffer.get(byteArray)
            String(byteArray, Charsets.UTF_8)
        } catch (e: Exception) {
            e.printStackTrace()
            ""
        }
    }
}

同样,对于 IOS,

import UIKit
import Flutter

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
      let flutterViewController = self.window.rootViewController as! FlutterViewController

      // 配置二进制信使以处理来自 Flutter 的消息。
      let binaryMessenger = flutterViewController.engine!.binaryMessenger
      binaryMessenger.setMessageHandlerOnChannel("foo", binaryMessageHandler: { [weak self] message, reply in
          // 确保正确的字节顺序。
           guard let message = message else {
               reply(nil)
               return
           }
           // 将二进制数据解码为 UTF-8 字符串。
           if let data = String(data: message, encoding: .utf8) {
               let x = message.debugDescription // 将消息转换为字符串以进行演示。
               // 显示带有收到消息的提示。
               let alertController = UIAlertController(
                   title: "Message from Flutter",
                   message: data,
                   preferredStyle: .alert
               )
               alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
               flutterViewController.present(alertController, animated: true, completion: nil)
           }
           reply(nil)
      }
    )

      GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }

    // 将 ByteBuffer 解码为 UTF-8 字符串的函数。
    private func decodeUtf8String(byteBuffer: FlutterStandardTypedData) -> String? {
            let byteArray = [UInt8](byteBuffer.data)
            return  String(bytes: byteArray, encoding: .utf8)
    }
}

通信是双向的,您可以从本机平台发送到 Flutter。确保在我们的类 Messenger 中实现 setMessageHandler 以接收来自本机平台的二进制消息并对其进行解码。只需反转我们的代码流,您就可以发送:

在 IOS 中,使用

// 从平台向 flutter 发送二进制信息。它将通道和信息作为参数
flutterViewController.engine!.binaryMessenger.send(onChannel: <#T##String#>, message: <#T##Data?#>)

在安卓中使用:

// 将二进制信息从平台发送至 flutter。
flutterEngine.dartExecutor.binaryMessenger.send()

消息和响应以异步方式传递,以确保用户界面保持响应。

现在,您可以将消息从 Flutter 传递到本机平台,反之亦然。但是,正如您在处理二进制消息时所看到的,我们必须担心编码、解码和处理寄存器等。它可能导致代码冗长并增加代码的复杂性。

那么,解决方案是什么?

平台通道:让上述过程变得更加简单,就引出了平台通道。平台通道是一种将通道名称和编解码器结合在一起的结构。

这种配对可将信息转换成二进制格式进行传输,并在接收时将其从二进制格式转换回来。它让使用本机平台变得更加容易。

请看这个名为 MethodChannel [2] 的平台通道。如果查看一下代码,就会发现它正在处理自己的 BinaryMessenger。

后面详细介绍平台通道以及如何使用它将消息在 Flutter 和本机平台之间的传递。

引用链接

[1] BinaryMessenger: https://api.flutter.dev/flutter/services/BinaryMessenger-class.html
[2] MethodChannel : https://github.com/flutter/flutter/blob/efbf63d9c6/packages/flutter/lib/src/services/platform_channel.dart#L245

标签:原生,String,二进制,平台,通信,message,data,Flutter
From: https://blog.51cto.com/sdwml/7180543

相关文章

  • 直播软件开发,Flutter实现点击头像更新头像的功能
    直播软件开发,Flutter实现点击头像更新头像的功能InkWell(            onTap:(){             showDialog(              context:context,              builder......
  • 分享ShareSDK flutter
     https://blog.csdn.net/apkkkk/article/details/128020409官方文档https://developer.umeng.com/docs/119267/detail/174923......
  • 极光推送 flutter
    iOS和安卓平台配置http://isea.site/index.php/archives/42/官方文档https://docs.jiguang.cn/jpush/client/client_pluginsgithubhttps://github.com/jpush/jpush-flutter-plugin......
  • 触摸屏与PLC之间 EtherNet/IP无线以太网通信
    在实际系统中,同一个车间里分布多台PLC,用触摸屏集中控制。通常所有设备距离在几十米到上百米不等。在有通讯需求的时候,如果布线的话,工程量较大耽误工期,这种情况下比较适合采用无线通信方式。本方案以MCGS触摸屏和2台三菱FX5uPLC为例,介绍触摸屏与多台PLC的无线以太网通信实现过程。......
  • 《串口篇》实现模拟串口通信(未验证)
    实现串口通信参考链接:https://www.jb51.net/article/279177.htm新建项目出于简单考虑,首先创建一个Winform项目,本文项目名称为portTest。串口通信,至少有两个串口才能通信,所以拖动两个GroupBox,一左一右,里面分别放置一个Combobox、一个按钮,以及两个TextBox用于发送和接收内容,第二......
  • 《串口篇》实现串口通信
    实现串口通信参考链接:jb51.net/article/237854.htm本文实例为大家分享了C#实现串口通信的具体代码,供大家参考,具体内容如下基本概念前端效果使用winform代码实现如下点击查看代码namespaceSerialPortTest {   publicpartialclassForm1:Form   {......
  • HTML5原生拖拽/拖放 Drag & Drop 详解
    前言拖放(drap&drop)在我们平时的工作中,经常遇到。它表示:抓取对象以后拖放到另一个位置。目前,它是HTML5标准的一部分。我从几个方面学习并实践这个功能。拖放的流程对应的事件我们先看下拖放的流程:选中--->拖动--->释放然后,我们一步步看下这个过程中,会发生的事情。选......
  • Flutter 应用程序如何组织可扩展的文件夹结构
    开发人员在使用Flutter时经常面临的挑战之一是如何以可扩展和可维护的方式组织项目。文件夹结构在这方面起着关键作用。让我们深入了解如何构建Flutter应用程序以实现可扩展性。文件夹结构的重要性为Flutter应用程序选择正确的文件夹结构是非常重要的。它直接影响团队合作时......
  • 二、原生 API 的注解使用示例
    [email protected](METHOD)@Retention(RUNTIME)public@interfaceRequestLine{//请求方式+uriStringvalue();//斜线是否base64编码booleandecodeSlash()defaulttrue;//默认支持URL传多值,是通过key来传输的。形如:key=value1&......
  • 设计一个网络通信协议
    [email protected],2023Description设计一个网络通信协议大多数时候,并不需要进行协议设计,只需要使用成熟的协议就行了。但架不住少数时候的存在,所以就需要了解如何去设计一个协议。实际上协议工程学是一门专门的学科,而且互联网络常见......