由于业务需要,要做蓝牙打印机的适配,内部有类似的插件,但不适用于业务所要求的蓝牙打印机,所以就自己下手尝试了一下 Flutter Plugin 的开发。
Flutter Plugin 有什么用?类似我们 node 的 npm,Flutter 也有自己的 packages 库,Flutter 的 package 分两种,一种是纯 dart 的包,一种是与原生交互的插件,我们这里说的是与原生交互的 plugin 的开发,plugin 的开发与复用,能提高开发效率以及降低工程耦合度,为项目快速集成对应的能力。那 Flutter Plugin 是如何与原生交互的呢?
参考官网的解析:platform channels
以安卓为例,Flutter 与 Native,类似于一种 C/S模型 ,Flutter 为 Client 端,Native为 Server 端,两者通过 platform channel 进行消息通信,应用的 Flutter 部分通过channel 将消息发送到其应用程序的所在的宿主(安卓)应用,宿主监听平台通道,接收该消息后调用平台自身的 API 进行处理,并将处理通过 platform channel 返回给 Flutter部分。
Flutter 定义了三种 Channel 模型:
-
BasicMessageChannel:用于传递字符串与半结构化信息
-
MethodChanel:用于传递方法调用
-
EventChannel:用于数据流(event streams)的通信
这三中 Channel 之间互相独立,各有用途,但设计上非常相似,每种 Channel 均有三个重要成员变量:
-
name:String 类型,代表 channel 名字,也是这个 channel 的唯一标识符,因为一个项目中可能有多个 channel,要保证 channel 唯一性,可以考虑命名是组织名称 + 插件名称,例如:com.example.xxx/xpprinter
-
messager:BinaryMessager 类型,代表消息信使,是消息的发送与接收的工具
-
codec:MessageCodec 类型或 MethodCodec类型,代表消息的编解码器。
下面我们开始入手 plugin:
目录
Step1
Step2
Step 3
Step1
首先,我们要创建项目,可以在终端运行以下代码:
flutter create --template=plugin --platforms=android -a java --org=com.example.xxx xpprinter
-
--platforms:由于我们只做 android 平台,所以这里就加上了 "--platforms=android" ;如果你的是支持 ios 的,可以改为: "--platforms=ios" 或者 "--platforms=android,ios";
-
--org : --org 可以为我们制定应用 ID,这样也可以为我们自动生成这样的结构:
src
└── com
└── example
└── xxx
└── xpprinter
└── XpprinterPlugin.java
-
-a: 代表 android 平台选用什么样的语言开发
-
-i :代表 ios 平台使用什么语言开发,我们这里以安卓使用 java 为例
具体的 flutter create 参数设置可以参考文挡:《开发Packages和插件》。
Step2
执行完命令后,你可以看到创建的项目的目录是这样的:
我们首先来看 Android 目录下的 XpprinterPlugin:
-
onAttachedToEngine 主要用于连接时初始化 MethodChannel
-
onMethodCall ,用于监听 MethodChannel 的请求,并做对应的处理。
-
onDetachedFromEngine 主要用于断开连接时,清空 MethodChannel
在这个基础上我们继续看 lib 目录下的 xpprinter.dart 文件:
这里封装了一个类,在Xpprinter 类里面,首先定义了 _channel,这里创建了一个 xpprinter 的 MethodChannel,另外这里还有个 platformVersoin 的方法,这里面用了 MethodChannel的invokeMethod方法发起一次方法调用,向 native 端发起请求,而我们在 android 目录下面的监听处理的 onMethodCall 里面,有针对这个方法的入参进行了处理:
这里针对 getPlatformVersion 这个请求进行了处理,返回了安卓系统的固件版本号。这里就基本形成了一个简单的与 native 交互的一个请求与响应,那我们在项目里面怎么引用呢?
接下来我们来看 example 目录:
我们可以看到在 pubspec.yml 文件里面,我们引入了这个插件,当然如果正式环境里面这里的地址就写包的仓库地址即可,例如下图:
又或者放到flutter 的 packages 库上, 以下面这种方式引入也可以:
接下来我们继续看 example 里面 flutter 是怎么调用的:
在 dart 文件里面,初始化时调用了 Xpprinter 类中的 platformVersion 返回值为原先固件版本号,在 build 时显示该固件版本号,这样就完成了一次简单的 native 与 flutter 的交互。
Step3
发布项目到 flutter packages 库上或者发布到内部仓库。
下次下个项目就可以直接引入使用了。
发布项目到 flutter packages 可以参考:https://flutter.cn/docs/development/packages-and-plugins/developing-packages#publish