Flutter 3.47 鸿蒙三方库适配实战:从 0 到 1 处理 flutter_blue_classic

经典蓝牙(Bluetooth Classic)是打印机、POS 机、车载设备等外设的主要连接方式,与 BLE 是两套不同的协议栈。flutter_blue_classic 封装了设备发现、配对、RFCOMM 连接与数据读写。把它带到鸿蒙时,适配面既有方法通道也有事件流。

本文以 flutter_blue_classic 0.1.1 为例,记录我如何保留原有 Dart API、补齐 Flutter OH 插件入口、在鸿蒙端接入真实系统能力,并在 HarmonyOS API 26 真机上完成构建、安装、启动和按钮调用验证。

适配仓库: oh-flutter/flutter_blue_classic

适配分支: feat/ohos_flutter_blue_classic_0.1.1

适配 TAG: 0.1.1-ohos.2

一、先看最终效果

在这里插入图片描述

图 1:HarmonyOS API 26 真机启动 Demo。页面显示 flutter_blue_classic 0.1.1。

在这里插入图片描述

图 2:点击“读取适配器状态”后返回 BluetoothAdapterState.on——EventChannel 推送的真实蓝牙开关状态。

验证点实测结果证据
Flutter OH 3.47 工程构建通过entry-default-signed.hap
安装、启动(真机)通过图 1
adapterStateEventChannel 推送真实状态 on图 2
通道名修正为 blue_classic/*代码

二、这个库原来是怎么工作的

这条库的通道结构是方法 + 多条事件流:

Dart FlutterBlueClassic
  -> MethodChannel('blue_classic/methods')        # 命令面
  -> EventChannel('blue_classic/adapterState')    # 适配器状态流
  -> EventChannel('blue_classic/discoveryState')  # 扫描状态流
  -> EventChannel('blue_classic/scanResults')     # 扫描结果流
  -> Android BluetoothAdapter / iOS ExternalAccessory

命令面包括 isSupported、isEnabled、getAdapterState、startScan、stopScan、bondDevice、connect、write 等。

三、实际环境

Flutter 鸿蒙环境搭建不在本文重复展开,直接参考 Flutter OH 环境搭建指南。

组件版本
Flutter OH3.47.4-ohos-1.0.4
Dart3.13.3
DevEco Studio26.0.0 Release
HarmonyOS SDKAPI 26
测试设备华为畅享 90 Pro Max,HarmonyOS 7.0.0.105(API 26)
目标库flutter_blue_classic 0.1.1
flutter --version
hdc list targets

四、确认上游版本并同步到 AtomGit

上游包地址是 https://github.com/LenhartStephan/flutter_blue_classic,版本 0.1.1 使用 GPL-3.0 License。适配前我在 AtomGit 目标组织中搜索了同名库,没有找到可以直接使用的 OHOS 实现。

仓库适配提交为 e49f241,分支与 TAG 0.1.1-ohos.2 均指向该提交。

git clone https://atomgit.com/oh-flutter/flutter_blue_classic.git
cd flutter_blue_classic
git switch feat/ohos_flutter_blue_classic_0.1.1
git log --oneline -5

五、创建适配分支并检查工程结构

git switch -c feat/ohos_flutter_blue_classic_0.1.1

关键目录如下:

flutter_blue_classic/
├── lib/                                        # 原有 Dart API 和 MethodChannel
├── ohos/
│   ├── index.ets                               # OHOS 插件导出入口
│   └── src/main/ets/components/plugin/
│       └── FlutterBlueClassicPlugin.ets                           # 通道实现
├── example/lib/main.dart                        # 真机验证 Demo
├── example/ohos/                                # Flutter OH 宿主工程
├── pubspec.yaml                                # 声明 ohos 平台
└── README.OpenHarmony_CN.md                    # 鸿蒙适配说明

pubspec.yaml 中的关键声明是:

flutter:
  plugin:
    platforms:
      ohos:
        pluginClass: FlutterBlueClassicPlugin

pluginClass 必须和 ohos/index.ets 导出的类名一致,否则 Dart 端能编译,运行时却不会注册插件。

六、适配过程:注册通道并对齐语义

通道名是这里最大的坑——不是 flutter_blue_classic:

Dart 侧通道类型
blue_classic/methodsMethodChannel
blue_classic/adapterStateEventChannel
blue_classic/discoveryStateEventChannel
blue_classic/scanResultsEventChannel

蓝牙状态用事件流:

onListen(args: Any, events: EventSink): void {
  this.stateSink = events;
  access.on('stateChange', this.onStateChange);
  events.success(this.adapterStateName());   // 先推一次当前值
}

private readonly onStateChange = (state: access.BluetoothState): void => {
  this.stateSink?.success(this.adapterStateNameOf(state));
};
方法OpenHarmony 实现
adapterState / adapterStateNow / isEnabledaccess.getState() + stateChange 事件
bondedDevicesconnection.getPairedDevices() + getRemoteDeviceName()
bondDeviceconnection.pairDevice()
startScan / turnOn平台限制(经典蓝牙发现/开关未开放)

七、构建配置与签名

示例工程的目标 SDK 对齐到 26,与 @ohos/flutter_ohos 的最低要求一致:

{
  "name": "default",
  "compatibleSdkVersion": "26.0.0",
  "targetSdkVersion": "26.0.0",
  "runtimeOS": "HarmonyOS"
}

Demo 的 AppScope/app.json5 统一成 com.example.flutter_oh_demo,与 DevEco 调试签名对应。证书、p12、p7b 和密码没有提交到仓库,读者应在自己的 DevEco Studio 中生成调试签名。

八、通过 AtomGit 引入适配版

在另一个 Flutter OH 应用中使用时,建议锁定 TAG:

dependencies:
  flutter_blue_classic:
    git:
      url: https://atomgit.com/oh-flutter/flutter_blue_classic.git
      ref: 0.1.1-ohos.2
flutter pub get

然后在 pubspec.lock 检查 source: git、AtomGit 地址和 resolved-ref,确认没有解析到 pub.dev 的同名版本。

九、构建、安装和真机验证

cd example
flutter pub get
flutter analyze
flutter build hap --debug
hdc install -r build/ohos/hap/entry-default-signed.hap
hdc shell aa start -a EntryAbility -b com.example.flutter_oh_demo

构建输出为 ✓ Built build/ohos/hap/entry-default-signed.hap.,随后 hdc 报告安装成功并启动 Ability。真机上按本文的截图顺序逐一点击按钮完成验证。

十、适配结果和当前边界

蓝牙状态与配对已接入。限制如下:

  1. 经典蓝牙设备发现在鸿蒙公开 SDK 未对普通应用开放,startScan/stopScan 是安全无操作。
  2. 开关蓝牙需要 BLUETOOTH_SETTINGS(系统级),本实现不代用户切换系统开关,调用后直接回读当前状态。
  3. SPP 连接需要 RFCOMM socket,属系统级受限能力,本实现保留接口并在文档中标注。

十一、FAQ

Q1:适配器状态是怎么读取的?

  • 现象: 通道名必须与 Dart 侧完全一致:blue_classic/methods、blue_classic/adapterState 等,写成 flutter_blue_classic 时调用无法命中。
  • 解决方法: 按 Dart 源码注册 blue_classic/* 四条通道,适配器状态用 EventChannel 先推一次当前值、再跟随 stateChange 事件。
  • 验证结果: 真机返回 BluetoothAdapterState.on。

Q2:设备发现能力怎么处理?

  • 现象: 经典蓝牙设备发现在鸿蒙上不开放给三方应用。
  • 解决方法: 需要发现设备时改用 BLE 扫描(@ohos.bluetooth.ble);本库的已配对设备查询不受影响。
  • 验证结果: 已配对设备列表真机读取成功。

Q3:三条事件流分别负责什么?

  • 现象: adapterState 承载蓝牙开关状态,discoveryState/scanResults 服务于设备发现。
  • 解决方法: 状态展示依赖 adapterState;发现类功能待平台开放后在同一条 EventChannel 上补齐。
  • 验证结果: adapterState 真机实时推送验证通过。

十二、总结

flutter_blue_classic 0.1.1 已接入鸿蒙的蓝牙状态与配对能力:用 @ohos.bluetooth.access 读取开关状态并通过 EventChannel 实时推送,用 connection 查询配对设备与发起配对。经典蓝牙发现与 SPP 连接受平台限制。

十三、参考资料和仓库地址

欢迎加入CPF-Flutter 鸿蒙社区:https://atomgit.com/CPF-Flutter

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐