Frontside Build Status pub package

Flutter BLE library logo

FlutterBleLib

Flutter 中满足您所有低功耗蓝牙需求的库。内部利用 Polidea 的 MultiPlatformBleAdapter,该适配器运行在 RxAndroidBleRxBluetoothKit 之上。

BLE 模拟器

此库支持 BLEmulator,即 BLE 模拟器。通过模拟,可以开发而无需物理智能手机或 BLE 外围设备,并在自动化测试中使用生产环境中的 BLE 相关代码。

安装

要使用此插件,请将 flutter_ble_lib 添加为 pubspec.yaml 文件中的依赖项

Android

[project]/android/app/build.gradle 文件中的 minSDKVersion 设置为 18。

defaultConfig {
  ...
  minSdkVersion 18
  ...
}

低功耗蓝牙支持已在 API 18 中添加,因此该库要求 minSDKVersion 设置为 18。如果 BLE 不是您应用程序的核心,您可以覆盖它并在代码中处理支持检测。

注意:您无需将任何与 BLE 相关的权限添加到 AndroidManifest.xml,因为它们已在库的本地模块中声明。但是,您仍然需要在运行时请求 ACCESS_FINE_LOCATION 权限才能扫描外围设备。请参阅示例代码示例的 pubspec

iOS

转到 [project]/ios 目录并运行 pod install

Privacy – Bluetooth Always Usage Description 键添加到 [project]/ios/Runner/Info.plist 文件。

...
<key>NSBluetoothAlwaysUsageDescription</key>
<string>Your own description of the purpose.</string>
...

后台模式

要支持后台功能,请将 bluetooth-central 后台执行模式 键添加到 [project]/ios/Runner/Info.plist 文件。

...
<key>UIBackgroundModes</key>
<array>
  <string>bluetooth-central</string>
</array>
...

用法

该库围绕几个基本实体进行组织,它们是:

  • BleManager
  • Peripheral
  • Service
  • Characteristic
  • Descriptor

您必须创建一个 BleManager 实例并初始化底层的原生资源。使用该实例,您然后获取一个 Peripheral 实例,该实例可用于在外围设备上执行操作。

所有通过 Dart-Native 桥接的操作都是异步的,因此插件中的所有操作都返回 Future 或 Stream。

更多信息,请参阅 REFERENCE

注意:此库不会为您处理任何权限。根据 Android 开发者指南,要在 Android 上扫描外围设备,您需要 ACCESS_FINE_LOCATION 权限

初始化

BleManager bleManager = BleManager();
await bleManager.createClient(); //ready to go!
// your peripheral logic
bleManager.destroyClient(); //remember to release native resources when you're done!

以下代码片段假定库已初始化。

处理蓝牙适配器状态

enum BluetoothState {
  UNKNOWN,
  UNSUPPORTED,
  UNAUTHORIZED,
  POWERED_ON,
  POWERED_OFF,
  RESETTING,
}


bleManager.enableRadio(); //ANDROID-ONLY turns on BT. NOTE: doesn't check permissions
bleManager.disableRadio() //ANDROID-ONLY turns off BT. NOTE: doesn't check permissions
BluetoothState currentState = await bleManager.bluetoothState();
bleManager.observeBluetoothState().listen((btState) {
  print(btState);
  //do your BT logic, open different screen, etc.
});

扫描外围设备

bleManager.startPeripheralScan(
  uuids: [
    "F000AA00-0451-4000-B000-000000000000",
  ],
).listen((scanResult) {
  //Scan one peripheral and stop scanning
  print("Scanned Peripheral ${scanResult.peripheral.name}, RSSI ${scanResult.rssi}");
  bleManager.stopPeripheralScan();
});

上面的代码片段启动外围设备扫描,并在收到第一个结果后停止。它会过滤扫描结果,只保留那些广告服务具有指定 UUID 的结果。

注意:ScanResultisConnectableoverflowServiceUuids 字段仅限于 iOS,在 Android 上为 null

连接到已保存的外围设备

您可以尝试连接到具有已知 ID 的外围设备,即 iOS 上先前扫描的 UUID 或 Android 上的 MAC 地址,从而避免在应用程序中进行整个扫描操作。为此,您需要使用以下方法创建 Peripheral 实例:

Peripheral myPeripheral = bleManager.createUnsafePeripheral("< known id >");

获得外围设备实例后,您可以继续连接。但请记住,Android 在未先扫描的情况下可能仍然找不到外围设备

连接到外围设备

首先,您必须从 BleManager.startPeripheralScan() 获取一个 ScanResult

Peripheral peripheral = scanResult.peripheral;
peripheral.observeConnectionState(emitCurrentValue: true, completeOnDisconnect: true)
  .listen((connectionState) {
    print("Peripheral ${scanResult.peripheral.identifier} connection state is $connectionState");
  });
await peripheral.connect();
bool connected = await peripheral.isConnected();
await peripheral.disconnectOrCancelConnection();

上面的代码片段开始观察外围设备的连接状态,连接到它,检查它是否已连接,然后断开连接。

事务

没有反向操作且为异步的方法接受 String transactionId 作为可选参数,以便用户取消此类操作。返回到 Dart 的 Future 将以 BleError(BleErrorCode.operationCancelled…) 结束,但这只会丢弃操作结果,操作本身无论如何都会执行

例如,如果我决定不再想在选定的外围设备上运行发现

//assuming peripheral is connected
peripheral.discoverAllServicesAndCharacteristics(transactionId: "discovery");
//will return operation cancelled error after calling the below
bleManager.cancelTransaction("discovery");

具有相同 transactionId 的每个新操作都会导致前一个操作被取消并出错,如果它尚未完成。如果 transactionId 设置为 null 或根本未指定,则库会为该操作设置唯一的整数 transactionId

注意:请勿将整数设置为 transactionId,因为它们已被库使用。

获取特性

要操作外围设备,首先必须运行其服务和特性的发现。

//assuming peripheral is connected
await peripheral.discoverAllServicesAndCharacteristics();
List<Service> services = await peripheral.services(); //getting all services
List<Characteristic> characteristics1 = await peripheral.characteristics("F000AA00-0451-4000-B000-000000000000");
List<Characteristic> characteristics2 = await services.firstWhere(
  (service) => service.uuid == "F000AA00-0451-4000-B000-000000000000").characteristics();

//characteristics1 and characteristics2 have the same contents

表示特性的对象具有唯一的标识符,因此它们指向一个特定的特性,即使存在多个服务/特性 UUID 匹配。

操作特性

以下是写入特性的 3 种方法,它们都产生相同的结果,前提是只有一个具有指定 UUID 的服务和一个具有指定 UUID 的特性。

peripheral.writeCharacteristic(
  "F000AA00-0451-4000-B000-000000000000",
  "F000AA02-0451-4000-B000-000000000000",
  Uint8List.fromList([0]),
  false); //returns Characteristic to chain operations more easily

service.writeCharacteristic(
  "F000AA02-0451-4000-B000-000000000000",
  Uint8List.fromList([0]),
  false); //returns Characteristic to chain operations more easily

characteristic.write(Uint8List.fromList([0]), false); //returns void

Peripheral/Service 级别监控或读取特性会返回 CharacteristicWithValue 对象,该对象是带有附加 Uint8List value 属性的 Characteristic

描述符操作

来自单个特性的描述符列表可以通过与来自单个服务的特性列表类似的方式获得,从 Peripheral、Service 或 Characteristic 对象。可以通过提供必要的 UUID,或者从 Descriptor 对象,从 Peripheral、Service 或 Characteristic 读取/写入描述符。

注意:要启用特性的监控,您应该使用 characteristic.monitor()(peripheral/service).monitorCharacteristic(),而不是自己更改底层描述符的值。

由 Frontside 提供支持

Frontside 代表 Resideo 为此库提供了架构咨询和财务支持。

维护者

此库由 Polidea 维护

联系我们

了解更多关于 Polidea 的 BLE 服务.

维护者

待办

许可证

版权所有 2019 Polidea Sp. z o.o

根据 Apache 许可证 2.0(“许可证”)许可;除非符合许可证规定,否则不得使用本文件。您可以获取许可证的副本

https://apache.ac.cn/licenses/LICENSE-2.0

除非适用法律要求或书面同意,否则根据许可证分发的软件按“原样”分发,不附带任何明示或暗示的保证或条件。有关管辖权限和限制的特定语言,请参阅许可证。

来自 Polidea 的更多内容

查看 Polidea 的其他 BLE 库

GitHub

查看 Github