Frontside
Build Status
pub package

Flutter BLE library logo

FlutterBleLib

Flutter中所有低功耗蓝牙需求的库。内部利用Polidea的
MultiPlatformBleAdapter,
其运行在RxAndroidBle
RxBluetoothKit

蓝牙模拟器

此库支持BLEmulator,即蓝牙模拟器。
模拟允许在没有物理智能手机或蓝牙外设的情况下进行开发,并在自动化测试中使用产品的蓝牙相关代码。

安装

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

Android

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

defaultConfig {
  ...
  minSdkVersion 18
  ...
}

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

注意:您无需将任何与蓝牙相关的权限添加到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-原生桥传递的操作都是异步的,
因此插件中的所有操作都返回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 myPeripheral = bleManager.createUnsafePeripheral("< known id >");

获取Peripheral的实例。一旦有了外设的实例,您就可以继续连接。但请记住,
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对象,该对象是Characteristic,并带有附加的Uint8List value属性。

描述符操作

单个特征的描述符列表可以与服务中的特征列表类似地获得,无论是从Peripheral、Service还是Characteristic对象。描述符可以
通过提供必要的UUID,从Peripheral、Service或Characteristic中读取/写入描述符,或者直接从Descriptor对象读取/写入。

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

由Frontside促进

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

维护者

此库由Polidea维护

联系我们

了解更多关于Polidea的蓝牙服务.

维护人员

待办

许可证

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

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

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

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

更多来自Polidea

查看Polidea的其他蓝牙库

GitHub

https://github.com/i-atros/flutter_ble_lib