Flutter跨平台通信插件pigeon的使用

发布于 1周前 作者 zlyuanteng 来自 Flutter

Flutter跨平台通信插件Pigeon的使用

简介

Pigeon是一个代码生成工具,用于使Flutter和主机平台之间的通信类型安全、更简单和更快捷。它消除了在多个平台和语言之间管理字符串的需求,并提高了与常见方法通道模式相比的效率。最重要的是,它消除了编写自定义平台通道代码的需求,因为Pigeon会为你生成这些代码。

特性

支持的平台

  • Android: Kotlin 和 Java 代码
  • iOS 和 macOS: Swift 和 Objective-C 代码
  • Windows: C++ 代码
  • Linux: GObject 代码

支持的数据类型

Pigeon 使用 StandardMessageCodec,因此支持任何平台通道支持的数据类型。此外,还支持自定义类、嵌套数据类型和枚举。

同步和异步方法

虽然所有跨平台通道API(如Pigeon方法)调用都是异步的,但Pigeon方法可以在本地端以同步方法编写,以简化回复逻辑。如果需要异步方法,可以使用 @async 注解。

错误处理

对于Kotlin、Java和Swift,所有Host API异常都会转换为Flutter的 PlatformException。对于Objective-C和C++,可以通过提供的 FlutterError 类发送错误信息。

任务队列

当目标是支持TaskQueue API的Flutter版本时,可以使用 TaskQueue 注解选择处理HostApi方法的线程模型。

多实例支持

现在支持通过提供唯一的消息通道后缀字符串来创建多个实例并行运行。

使用步骤

  1. 添加pigeon作为开发依赖:

    dev_dependencies:
      pigeon: ^0.2.0
    
  2. 创建接口定义文件: 在项目根目录下创建一个 .dart 文件(例如 api.pigeon.dart),用于定义通信接口。

  3. 运行pigeon生成代码:

    flutter pub get
    dart run pigeon --input ./api.pigeon.dart --dart_out ./lib/api.dart --objc_header_out ./ios/Runner/Pigeon.h --objc_source_out ./ios/Runner/Pigeon.m --java_out ./android/app/src/main/java/com/example/flutter_pigeon/Pigeon.java --cpp_header_out ./windows/pigeon/pigeon.h --cpp_source_out ./windows/pigeon/pigeon.cc --gobject_out ./linux/pigeon/
    
  4. 将生成的Dart代码添加到 ./lib 目录: 将生成的Dart文件复制到项目的 lib 目录中。

  5. 实现主机语言代码并添加到构建中: 根据平台不同,将生成的代码添加到相应的目录并实现接口。

  6. 调用生成的Dart方法: 在Flutter代码中调用生成的方法。

定义通信接口的规则

  • 文件中不应包含方法或函数定义,只应包含声明。
  • 自定义类应定义为具有支持数据类型的字段。
  • APIs 应定义为带有 @HostApi()@FlutterApi() 元数据的抽象类。
  • 方法声明应具有参数和返回值,其类型应在文件中定义、是支持的数据类型或为 void
  • 事件通道仅支持Swift、Kotlin和Dart生成器。
  • 事件通道方法应包装在一个带有 @EventChannelApi 元数据的抽象类中。
  • 事件通道定义不应包括 Stream 返回类型,只需指定流中的类型。

示例代码

定义接口

// api.pigeon.dart

import 'package:pigeon/pigeon.dart';

class Message {
  String text;
}

@HostApi()
abstract class Api {
  void echo(Message message);
}

生成代码

运行以下命令生成代码:

dart run pigeon --input ./api.pigeon.dart --dart_out ./lib/api.dart --objc_header_out ./ios/Runner/Pigeon.h --objc_source_out ./ios/Runner/Pigeon.m --java_out ./android/app/src/main/java/com/example/flutter_pigeon/Pigeon.java --cpp_header_out ./windows/pigeon/pigeon.h --cpp_source_out ./windows/pigeon/pigeon.cc --gobject_out ./linux/pigeon/

实现iOS代码

// ios/Runner/AppDelegate.swift

import UIKit
import Flutter
import Pigeon

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
    let api = Api()
    api.setup(withBinaryMessenger: controller.binaryMessenger)
    
    api.echoHandler = { (message) in
      print("Received message: \(message.text)")
      return Message(text: "Echo: \(message.text)")
    }
    
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

实现Android代码

// android/app/src/main/kotlin/com/example/flutter_pigeon/MainActivity.kt

import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
import com.example.flutter_pigeon.Pigeon.Api
import com.example.flutter_pigeon.Pigeon.Message

class MainActivity: FlutterActivity() {
  private lateinit var api: Api

  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    api = Api()
    api.setup(flutterEngine.dartExecutor.binaryMessenger)

    api.echo = { message ->
      println("Received message: ${message.text}")
      Message().apply { this.text = "Echo: ${message.text}" }
    }
  }
}

调用生成的Dart方法

// lib/main.dart

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Pigeon Example')),
        body: Center(
          child: ElevatedButton(
            onPressed: () async {
              final api = Api();
              final response = await api.echo(Message(text: "Hello from Flutter"));
              print("Response: ${response.text}");
            },
            child: Text('Send Message'),
          ),
        ),
      ),
    );
  }
}

注意事项

  • Pigeon生成的代码主要用于内部实现,不建议将其用于公共API。
  • 双方通信代码必须由相同版本的Pigeon生成,否则可能导致应用崩溃。

希望这个详细的指南能帮助你更好地理解和使用Pigeon进行跨平台通信!如果有任何问题,请随时提问。


更多关于Flutter跨平台通信插件pigeon的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter跨平台通信插件pigeon的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用跨平台通信插件Pigeon的示例代码。Pigeon是Flutter团队开发的一个用于生成跨平台代码的工具,它允许在Flutter和原生平台(如iOS和Android)之间进行高效通信。

1. 设置Pigeon

首先,你需要确保你的Flutter项目已经初始化,并且你已经在项目中添加了Pigeon依赖。

添加Pigeon依赖

在你的pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  pigeon: ^x.y.z  # 替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 定义通信协议

接下来,你需要定义一个.dart文件来描述Flutter和原生平台之间的通信协议。例如,创建一个名为messaging.dart的文件:

// messaging.dart
import 'package:pigeon/messaging.dart';

@HostApi()
abstract class MyHostApi {
  String echo(String message);
}

@FlutterApi()
abstract class MyFlutterApi {
  void receiveMessage(String message);
}

3. 生成代码

使用Pigeon CLI工具生成原生平台的代码。首先,你需要确保你已经安装了Dart SDK,并且你的PATH环境变量中包含了Dart可执行文件的路径。

然后,在你的Flutter项目根目录下运行以下命令:

dart pub global activate pigeon
dart pub global run pigeon --input=messaging.dart --dart_out=lib/generated --objc_header_out=ios/Runner/generated --objc_source_out=ios/Runner/generated --java_out=android/app/src/main/java/com/example/yourapp/generated --kotlin_out=android/app/src/main/kotlin/com/example/yourapp/generated

注意:将com.example.yourapp替换为你的Android项目的实际包名。

4. 在Flutter中使用生成的API

现在,你可以在Flutter代码中调用生成的API。例如,在lib/main.dart中:

import 'package:flutter/material.dart';
import 'generated/messaging.dart';  // 导入生成的Dart代码

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Pigeon Demo'),
        ),
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatefulWidget {
  @override
  _MyWidgetState createState() => _MyWidgetState();
}

class _MyWidgetState extends State<MyWidget> {
  late MyHostApi _hostApi;

  @override
  void initState() {
    super.initState();
    _hostApi = MyHostApi.hostApi;
  }

  void _sendMessage() async {
    String response = await _hostApi.echo("Hello from Flutter!");
    print("Received from host: $response");
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: <Widget>[
        Text('Press the button to send a message to the host platform:'),
        ElevatedButton(
          onPressed: _sendMessage,
          child: Text('Send Message'),
        ),
      ],
    );
  }
}

5. 在原生平台实现API

iOS

ios/Runner/generated目录下,你会找到生成的Objective-C头文件和实现文件。你需要在AppDelegate.swiftAppDelegate.m中实现这些API。

例如,在AppDelegate.swift中:

import UIKit
import Flutter
import your_project_name_Generated  // 导入生成的文件

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    
    // 实现MyHostApi协议
    let myHostApi = MyHostApiImpl()
    MyHostApi.setHostApi(myHostApi)
    
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

// 实现MyHostApi协议的方法
class MyHostApiImpl: NSObject, MyHostApi {
  func echo(message: String) -> String {
    return "Echo: \(message)"
  }
}

Android

android/app/src/main/java/com/example/yourapp/generated目录下,你会找到生成的Java或Kotlin文件。你需要在你的MainActivity.ktMainActivity.java中实现这些API。

例如,在MainActivity.kt中:

package com.example.yourapp

import android.os.Bundle
import io.flutter.embedding.android.FlutterActivity
import com.example.yourapp.generated.MyHostApi  // 导入生成的文件

class MainActivity: FlutterActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // 实现MyHostApi接口
        val myHostApi = object : MyHostApi {
            override fun echo(message: String): String {
                return "Echo: $message"
            }
        }
        MyHostApi.setHostApi(myHostApi)
    }
}

总结

以上是一个简单的示例,展示了如何在Flutter项目中使用Pigeon进行跨平台通信。你可以根据自己的需求扩展这个示例,添加更多的API和方法。

回到顶部