Flutter蓝牙通信插件win_ble的使用

发布于 1周前 作者 wuwangju 来自 Flutter

Flutter蓝牙通信插件win_ble的使用

WinBle

win_ble version

使用WinBle插件可以在Flutter Windows项目和纯Dart项目(仅限Windows)中启用蓝牙低功耗(Bluetooth Low Energy)。下面将详细介绍如何使用WinBle进行蓝牙通信。

初始化WinBle

在Flutter Windows项目中初始化WinBle时,需要通过await WinServer.path获取服务器路径。对于纯Dart项目(仅限Windows),需要下载BleServer.exe文件并放置在同一文件夹中,更多细节请参考example_dart

// 在Flutter Windows中初始化
await WinBle.initialize(serverPath: await WinServer.path());

// 在纯Dart项目中初始化
await WinBle.initialize(serverPath: "BLEServer.exe文件路径");

使用完后记得释放资源:

WinBle.dispose();

扫描设备

开始扫描附近的蓝牙设备:

WinBle.startScanning();

StreamSubscription? scanStream = WinBle.scanStream.listen((event) {
  // 获取设备信息
});

停止扫描:

WinBle.stopScanning();

scanStream?.cancel();

连接与断开连接

连接到指定地址的设备:

await WinBle.connect(address);

StreamSubscription _connectionStream =
    WinBle.connectionStreamOf(device.address).listen((event) {
  // event为布尔值,true表示已连接,false表示已断开
});

断开连接:

await WinBle.disconnect(address);

获取最大MTU大小

await WinBle.getMaxMtuSize(address);

处理蓝牙无线电状态

获取蓝牙无线电状态:

WinBle.getBluetoothState();

监听无线电状态变化:

WinBle.bleState.listen((BleState state) {
  // 获取BleState (On, Off, Unknown, Disabled, Unsupported)
});

// 打开无线电
WinBle.updateBluetoothState(true);

// 关闭无线电
WinBle.updateBluetoothState(false);

配对选项

配对设备:

await WinBle.pair(address);

// 解除配对
await WinBle.unPair(address);

// 检查设备是否可以配对
bool canPair = await WinBle.canPair(address);

// 检查设备是否已配对
bool isPaired = await WinBle.isPaired(address);

其他方法

获取服务:

var services = await WinBle.discoverServices(address);

获取特征值:

List<BleCharacteristic> bleCharacteristics = await WinBle.discoverCharacteristics(address: address, serviceId: serviceID);

读取特征值:

List<int> data = await WinBle.read(address: address, serviceId: serviceID, characteristicId: charID);

写入特征值:

await WinBle.write(address: address, service: serviceID, characteristic: charID, data: data, writeWithResponse: writeWithResponse);

订阅特征值更新:

await WinBle.subscribeToCharacteristic(address: address, serviceId: serviceID, characteristicId: charID);

// 取消订阅
await WinBle.unSubscribeFromCharacteristic(address: address, serviceId: serviceID, characteristicId: charID);

// 监听特征值更新
StreamSubscription _characteristicValueStream = WinBle.characteristicValueStream.listen((event) {
  // 接收所有特征值事件
});

注意事项

  • 需要Windows版本 >= 10.0.15014。
  • 如果Windows发布构建在运行应用时打开命令提示符,请编辑/windows/runner/main.cpp文件,这是一个已知的Flutter问题。

示例代码

以下是一个完整的示例代码,展示了如何使用WinBle进行蓝牙设备扫描、连接和交互:

// ignore_for_file: avoid_print

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:win_ble/win_ble.dart';
import 'package:win_ble/win_file.dart';

void main() {
  runApp(const MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()));
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  StreamSubscription? scanStream;
  StreamSubscription? connectionStream;
  StreamSubscription? bleStateStream;

  bool isScanning = false;
  BleState bleState = BleState.Unknown;

  void initialize() async {
    await WinBle.initialize(
      serverPath: await WinServer.path(),
      enableLog: true,
    );
    print("WinBle Initialized: ${await WinBle.version()}");
  }

  @override
  void initState() {
    initialize();
    connectionStream = WinBle.connectionStream.listen((event) {
      print("Connection Event : " + event.toString());
    });

    scanStream = WinBle.scanStream.listen((event) {
      setState(() {
        final index = devices.indexWhere((element) => element.address == event.address);
        if (index != -1) {
          final name = devices[index].name;
          devices[index] = event;
          if (event.name.isEmpty || event.name == 'N/A') {
            devices[index].name = name;
          }
        } else {
          devices.add(event);
        }
      });
    });

    bleStateStream = WinBle.bleState.listen((BleState state) {
      setState(() {
        bleState = state;
      });
    });
    super.initState();
  }

  String bleStatus = "";
  String bleError = "";

  List<BleDevice> devices = [];

  startScanning() {
    WinBle.startScanning();
    setState(() {
      isScanning = true;
    });
  }

  stopScanning() {
    WinBle.stopScanning();
    setState(() {
      isScanning = false;
    });
  }

  onDeviceTap(BleDevice device) {
    Navigator.push(
      context,
      MaterialPageRoute(builder: (context) => DeviceInfo(device: device)),
    );
  }

  @override
  void dispose() {
    scanStream?.cancel();
    connectionStream?.cancel();
    bleStateStream?.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Win BLe"),
        centerTitle: true,
        actions: [
          kButton("Ble Status : ${bleState.toString().split('.').last}", () {}),
        ],
      ),
      body: SizedBox(
        child: Column(
          children: [
            const SizedBox(height: 10),
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                kButton("Start Scan", () {
                  startScanning();
                }),
                kButton("Stop Scan", () {
                  stopScanning();
                }),
                kButton(
                    bleState == BleState.On ? "Turn off Bluetooth" : "Turn on Bluetooth", () {
                  if (bleState == BleState.On) {
                    WinBle.updateBluetoothState(false);
                  } else {
                    WinBle.updateBluetoothState(true);
                  }
                }),
              ],
            ),
            const Divider(),
            Column(
              children: [
                Text(bleStatus),
                Text(bleError),
              ],
            ),
            Expanded(
              child: devices.isEmpty
                  ? noDeviceFoundWidget()
                  : ListView.builder(
                      itemCount: devices.length,
                      itemBuilder: (BuildContext context, int index) {
                        BleDevice device = devices[index];
                        return InkWell(
                          onTap: () {
                            stopScanning();
                            onDeviceTap(device);
                          },
                          child: Card(
                            child: ListTile(
                              title: Text("${device.name.isEmpty ? "N/A" : device.name} ( ${device.address} )"),
                              subtitle: Text("Rssi : ${device.rssi} | AdvTpe : ${device.advType}"),
                            ),
                          ),
                        );
                      },
                    ),
            ),
          ],
        ),
      ),
    );
  }

  Widget kButton(String txt, VoidCallback onTap) {
    return ElevatedButton(
      onPressed: onTap,
      child: Text(txt, style: const TextStyle(fontSize: 20)),
    );
  }

  Widget noDeviceFoundWidget() {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        isScanning
            ? const CircularProgressIndicator()
            : InkWell(
                onTap: () {
                  startScanning();
                },
                child: const Icon(Icons.bluetooth, size: 100, color: Colors.grey),
              ),
        const SizedBox(height: 10),
        Text(isScanning ? "Scanning Devices ... " : "Click to start scanning")
      ],
    );
  }
}

此代码展示了如何使用WinBle插件进行蓝牙设备扫描、连接和交互。希望这些信息对你有所帮助!如果有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter蓝牙通信插件win_ble的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter蓝牙通信插件win_ble的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用win_ble插件进行蓝牙通信的示例代码。win_ble是一个用于Windows平台的Flutter蓝牙低功耗(BLE)通信插件。请确保你的开发环境已经设置好,并且你的Flutter项目已经正确配置以支持Windows平台。

1. 添加依赖

首先,在你的pubspec.yaml文件中添加win_ble依赖:

dependencies:
  flutter:
    sdk: flutter
  win_ble: ^x.y.z  # 请替换为最新版本号

然后运行flutter pub get来安装依赖。

2. 配置插件

确保你的CMakeLists.txt(如果你使用的是CMake)和windows文件夹下的其他配置文件已经正确设置以支持蓝牙功能。

3. 使用插件

以下是一个简单的示例,展示如何使用win_ble插件来扫描蓝牙设备并连接到第一个找到的设备:

import 'package:flutter/material.dart';
import 'package:win_ble/win_ble.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BleDemo(),
    );
  }
}

class BleDemo extends StatefulWidget {
  @override
  _BleDemoState createState() => _BleDemoState();
}

class _BleDemoState extends State<BleDemo> {
  late BluetoothManager bluetoothManager;

  @override
  void initState() {
    super.initState();
    bluetoothManager = BluetoothManager.instance;
    bluetoothManager.initialize();
  }

  Future<void> scanDevices() async {
    setState(() {
      // 可以在这里更新UI,比如显示扫描中的提示
    });

    try {
      List<BluetoothDevice> devices = await bluetoothManager.scanForDevices(
        allowDuplicates: false,
        timeout: Duration(seconds: 10),
      );

      if (devices.isNotEmpty) {
        BluetoothDevice device = devices.first;
        connectToDevice(device);
      } else {
        // 没有找到设备时的处理
        print("No devices found");
      }
    } catch (e) {
      print("Scanning failed: $e");
    }

    setState(() {
      // 扫描结束后的UI更新
    });
  }

  Future<void> connectToDevice(BluetoothDevice device) async {
    try {
      BluetoothRemoteDevice remoteDevice = await device.connect();
      // 连接到设备后的处理
      print("Connected to: ${remoteDevice.name}");
      // 可以在这里继续发现服务、特征值等操作
    } catch (e) {
      print("Connection failed: $e");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Bluetooth Demo'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Press the button to scan for BLE devices.'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: scanDevices,
              child: Text('Scan for Devices'),
            ),
          ],
        ),
      ),
    );
  }
}

注意事项

  1. 权限:确保你的应用具有访问蓝牙设备的权限。在Windows上,这通常意味着用户需要在系统设置中手动启用蓝牙功能,并且你的应用需要请求相应的权限。

  2. 异步操作:蓝牙操作通常是异步的,因此你需要在代码中处理这些异步操作,例如使用asyncawait关键字。

  3. 错误处理:蓝牙通信可能会因为各种原因失败,例如设备不可达、权限被拒绝等。因此,确保在代码中添加适当的错误处理逻辑。

  4. 插件版本:随着Flutter和插件的更新,API可能会有所变化。因此,请查阅最新的win_ble文档以获取最新的使用方法和API变更。

这个示例代码提供了一个基本的框架,你可以根据需要进行扩展和修改。希望这能帮助你开始在Flutter中使用win_ble插件进行蓝牙通信。

回到顶部