flutter 插件之 pigeon - 与宿主平台通信

Pigeon

Pigeon is a code generator tool to make communication between Flutter and the host platform type-safe, easier and faster.

Pigeon 是一个代码生成工具,让 Flutter 与宿主平台更简单、更快捷且类型安全地通信。非常类似于:Protocol Buffer

Pigeon 支持在 IOS 平台生成 Object-C 代码,在 Android 平台生成 Java 代码

插件地址:https://pub.flutter-io.cn/packages/pigeon

仓库地址:https://github.com/flutter/packages/tree/master/packages/pigeon/pigeons

示例地址:https://github.com/gaaclarke/pigeon_plugin_example

下面介绍 Pigeon(1.0.18) 使用方式(官方示例):

1. 创建插件工程,并安装 Pigeon

flutter create --template=plugin --platforms=android,ios -i swift -a kotlin day08_pigeon

通过 plugin 模板创建的项目中:

1. 有一个 example 文件夹,里面可以添加插件使用示例代码,方便测试插件

2. 在 pubspec.yaml 文件中,指定了各个平台真实实现的类名信息

1
2
3
4
5
6
7
8
flutter:
  plugin:
    platforms:
      android:
        package: com.example.day08_pigeon
        pluginClass: Day08PigeonPlugin
      ios:
        pluginClass: Day08PigeonPlugin

  因为 Pigeon 是一个代码生成工具,并不需要运行时支持,所以只需要在 dev_dependencies 中添加

2. 添加协议

在项目的根目录中添加 pigeons 目录,并在里面添加需要宿主平台支持的 API,命名为 messages.dart,该文件为通信协议文件

这里参考示例,获取自定义宿主平台版本号为例:

1
2
3
4
5
6
7
8
9
10
import 'package:pigeon/pigeon.dart';
 
class MyVersion {
  String? myVersionResult;
}
 
@HostApi()
abstract class ExampleApi {
  MyVersion getMyPlatformVersionResult();
}
3. 运行 flutter pub run pigeon 生成代码

可以手写命令行,也可以参考示例中的方法,建立一个 run_pigeon.sh 文件,把命令写在文件中,当 API 更新后,再运行这个文件就行

当命令执行完成后,会在 .sh 文件中配置的位置,创建相应的 java 和 object-c 代码

备注:windows 平台下无法直接运行 .sh 文件,可通过 git bash 来运行

1
2
3
4
5
6
7
8
flutter pub run pigeon \
  --input pigeons/messages.dart \
  --dart_out lib/messages.dart \
  --objc_header_out ios/Classes/messages.h \
  --objc_source_out ios/Classes/messages.m \
  --objc_prefix FLT \
  --java_out android/src/main/java/com/example/day08_pigeon/Messages.java \
  --java_package "com.example.day08_pigeon"
4. 实现宿主平台的 API

以 Android 平台为例,当 run_pigeon.sh 文件执行后,在项目中的 android/src/main 中,生成了 Java 文件 Messages.java,位置以 .sh 中 java_out 配置项为准

在 Java 文件中,会生成一个 public interface ExampleApi 接口,即在 messages.dart 中被标记为 @HostApi() 的抽象类,该接口为同名的协议接口

同时,在项目中的 android/src/main 中,生成了 Kotlin 文件,Day08PigeonPlugin.kt,该文件为与 Android 平台通信类

该类默认继承自 FlutterPlugin, MethodCallHandler

可在该类中直接添加协议接口实现(ExampleApi),也可以其它方式,比如创建新类来统一实现协议方法

这里以直接添加实现接口为例,添加 ExampleApi,并实现接口的所有方法和属性(由协议 messages.dart 定义)

同时,在该类的 FlutterPlugin 接口的 onAttachedToEngine,onDetachedFromEngine 方法中,通过调用 setup 方法来绑定 flutter 引擎具体调用的协议实现类对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.example.day08_pigeon
 
import androidx.annotation.NonNull
 
/// 导入生成的 Java 文件中的包
import com.example.day08_pigeon.Messages.MyVersion
import com.example.day08_pigeon.Messages.ExampleApi
 
import io.flutter.embedding.engine.plugins.FlutterPlugin
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
 
/** Day08PigeonPlugin */
class Day08PigeonPlugin: FlutterPlugin, MethodCallHandler, ExampleApi {
  /// The MethodChannel that will the communication between Flutter and native Android
  ///
  /// This local reference serves to register the plugin with the Flutter Engine and unregister it
  /// when the Flutter Engine is detached from the Activity
  private lateinit var channel : MethodChannel
 
  override fun onAttachedToEngine(@NonNull flutterPluginBinding: FlutterPlugin.FlutterPluginBinding) {
    channel = MethodChannel(flutterPluginBinding.binaryMessenger, "day08_pigeon")
    channel.setMethodCallHandler(this)
 
    /// 绑定
    ExampleApi.setup(flutterPluginBinding.binaryMessenger, this)
  }
 
  override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
    if (call.method == "getPlatformVersion") {
      result.success("Android ${android.os.Build.VERSION.RELEASE}")
    } else {
      result.notImplemented()
    }
  }
 
  override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
    channel.setMethodCallHandler(null)
 
    /// 解绑
    ExampleApi.setup(binding.binaryMessenger, null)
  }
 
  /// 协议实现
  override fun getMyPlatformVersionResult(): MyVersion {
    val myVersion = MyVersion()
    myVersion.myVersionResult = "123.456.789"
    return myVersion
  }
}
5. 在 example 中添加测试代码
在插件本身 lib 中导入 pigeon 生成的 messages.dart 库文件,并在 day08_pigeon.dart 添加访问库代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import 'dart:async';
import 'dart:io';
 
import 'package:flutter/services.dart';
 
import 'messages.dart';
 
class Day08Pigeon {
  static const MethodChannel _channel = MethodChannel('day08_pigeon');
 
  static Future<MyVersion> get myPlatformVersionResult async {
    if (Platform.isAndroid || Platform.isIOS) {
      var exampleApi = ExampleApi();
      return await exampleApi.getMyPlatformVersionResult();
    }
 
    throw PlatformException(code: 'not suport ${Platform.operatingSystem}');
  }
 
  static Future<String?> get platformVersion async {
    final String? version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
}

在 example 的 main.dart 中添加测试代码

1
2
3
4
5
6
7
8
9
try {
  var result = await Day08Pigeon.myPlatformVersionResult;
  var version = result.myVersionResult;
  if (kDebugMode) {
    print('my version = $version');
  }
} on PlatformException {
  platformVersion = 'Failed to get myPlatformVersionResult.';
}

完成!

 
 

 

posted @   wild-coffee  阅读(1555)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示