Flutter低功耗蓝牙通信插件bluetooth_low_energy的使用

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

Flutter低功耗蓝牙通信插件bluetooth_low_energy的使用

简介

bluetooth_low_energy 是一个Flutter插件,用于控制低功耗蓝牙(BLE),支持中央设备(Central)和外围设备(Peripheral)角色。以下是该插件的主要功能和使用方法。

CentralManager API 支持情况

API Android iOS macOS Windows Linux
logLevel
state
stateChanged
authorize
showAppSettings
discovered
connectionStateChanged
mtuChanged
characteristicNotified
startDiscovery
stopDiscovery
retrieveConnectedPeripherals
connect
disconnect
requestMTU
getMaximumWriteLength
readRSSI
readCharacteristic
writeCharacteristic
setCharacteristicNotifyState
readDescriptor
writeDescriptor

PeripheralManager API 支持情况

API Android iOS macOS Windows Linux
logLevel
state
stateChanged
authorize
showAppSettings
connectionStateChanged
mtuChanged
characteristicReadRequested
characteristicWriteRequested
characteristicNotifyStateChanged
descriptorReadRequested
descriptorWriteRequested
addService
removeService
removeAllServices
startAdvertising
stopAdvertising
getMaximumNotifyLength
respondReadRequestWithValue
respondReadRequestWithError
respondWriteRequest
respondWriteRequestWithError
notifyCharacteristic

开始使用

添加依赖

pubspec.yaml 文件中添加 bluetooth_low_energy 依赖:

dependencies:
  bluetooth_low_energy: ^<latest-version>

注意: 低功耗蓝牙不适用于模拟器,请使用具有蓝牙功能的物理设备进行开发。

平台特定配置

Android

确保你的 android/app/build.gradle 文件中的 minSdk 设置为21或更高。

iOS 和 macOS

根据苹果文档,你必须在iOS 13及以上版本包含 NSBluetoothAlwaysUsageDescription,在iOS 13之前包含 NSBluetoothPeripheralUsageDescription

对于macOS,开发者需要配置应用沙盒以访问受限资源。

Windows

PeripheralManager#startAdvertising 不支持 name 参数。

Linux

PeripheralManager API 尚未实现,因为 bluez 不支持此功能。

示例代码

以下是一个完整的示例应用程序,展示了如何使用 bluetooth_low_energy 插件:

import 'dart:async';
import 'dart:developer';

import 'package:flutter/material.dart';
import 'package:logging/logging.dart';
import 'package:bluetooth_low_energy/bluetooth_low_energy.dart';

void main() {
  runZonedGuarded(onStartUp, onCrashed);
}

void onStartUp() async {
  Logger.root.onRecord.listen(onLogRecord);
  hierarchicalLoggingEnabled = true;

  // 初始化蓝牙管理器
  final centralManager = CentralManager();
  await centralManager.startDiscovery();

  runApp(const MyApp());
}

void onCrashed(Object error, StackTrace stackTrace) {
  Logger.root.shout('App crashed.', error, stackTrace);
}

void onLogRecord(LogRecord record) {
  log(
    record.message,
    time: record.time,
    sequenceNumber: record.sequenceNumber,
    level: record.level.value,
    name: record.loggerName,
    zone: record.zone,
    error: record.error,
    stackTrace: record.stackTrace,
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'BLE Example',
      theme: ThemeData.light().copyWith(
        materialTapTargetSize: MaterialTapTargetSize.padded,
      ),
      darkTheme: ThemeData.dark().copyWith(
        materialTapTargetSize: MaterialTapTargetSize.padded,
      ),
      home: const BLEHomePage(),
    );
  }
}

class BLEHomePage extends StatefulWidget {
  const BLEHomePage({super.key});

  @override
  State<BLEHomePage> createState() => _BLEHomePageState();
}

class _BLEHomePageState extends State<BLEHomePage> {
  final CentralManager _centralManager = CentralManager();
  List<DiscoveredPeripheral> _peripherals = [];

  @override
  void initState() {
    super.initState();
    _centralManager.discovered.listen((event) {
      setState(() {
        _peripherals.add(event);
      });
    });
    _centralManager.startDiscovery();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('BLE Devices'),
      ),
      body: ListView.builder(
        itemCount: _peripherals.length,
        itemBuilder: (context, index) {
          final peripheral = _peripherals[index];
          return ListTile(
            title: Text(peripheral.name ?? 'Unknown Device'),
            subtitle: Text(peripheral.identifier),
            onTap: () {
              Navigator.push(
                context,
                MaterialPageRoute(
                  builder: (context) => DeviceDetailPage(peripheral: peripheral),
                ),
              );
            },
          );
        },
      ),
    );
  }
}

class DeviceDetailPage extends StatefulWidget {
  final DiscoveredPeripheral peripheral;

  const DeviceDetailPage({super.key, required this.peripheral});

  @override
  State<DeviceDetailPage> createState() => _DeviceDetailPageState();
}

class _DeviceDetailPageState extends State<DeviceDetailPage> {
  late StreamSubscription<ConnectionState> _connectionStateSubscription;
  bool _isConnected = false;

  @override
  void initState() {
    super.initState();
    _connectToDevice();
  }

  Future<void> _connectToDevice() async {
    try {
      await widget.peripheral.connect();
      _connectionStateSubscription = widget.peripheral.connectionStateChanged.listen((state) {
        if (mounted) {
          setState(() {
            _isConnected = state == ConnectionState.connected;
          });
        }
      });
    } catch (e) {
      log('Failed to connect: $e');
    }
  }

  @override
  void dispose() {
    _connectionStateSubscription.cancel();
    widget.peripheral.disconnect();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.peripheral.name ?? 'Unknown Device'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(_isConnected ? 'Connected' : 'Disconnected'),
            ElevatedButton(
              onPressed: _isConnected ? null : () async {
                await widget.peripheral.connect();
                setState(() {
                  _isConnected = true;
                });
              },
              child: const Text('Connect'),
            ),
            ElevatedButton(
              onPressed: _isConnected ? () async {
                await widget.peripheral.disconnect();
                setState(() {
                  _isConnected = false;
                });
              } : null,
              child: const Text('Disconnect'),
            ),
          ],
        ),
      ),
    );
  }
}

这个示例展示了如何初始化蓝牙管理器、发现设备并连接到设备。你可以根据需要扩展此代码以实现更多功能,如读取和写入特征值等。


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

1 回复

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


当然,下面是一个关于如何在Flutter应用中使用bluetooth_low_energy插件进行低功耗蓝牙通信的示例代码。这个示例包括扫描设备、连接到设备、读取和写入特征值的基本操作。

首先,确保你的Flutter项目中已经添加了bluetooth_low_energy插件。你可以在你的pubspec.yaml文件中添加以下依赖:

dependencies:
  flutter:
    sdk: flutter
  bluetooth_low_energy: ^0.10.0  # 请确保使用最新版本

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

接下来是示例代码:

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

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

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

class BluetoothScreen extends StatefulWidget {
  @override
  _BluetoothScreenState createState() => _BluetoothScreenState();
}

class _BluetoothScreenState extends State<BluetoothScreen> {
  final BleManager bleManager = BleManager();
  List<DiscoveredDevice> devices = [];
  ConnectedDevice? connectedDevice;

  @override
  void initState() {
    super.initState();
    initBluetooth();
  }

  Future<void> initBluetooth() async {
    await bleManager.initialize();
    startScanning();
  }

  Future<void> startScanning() async {
    bleManager.startScanning().listen((scanResult) {
      setState(() {
        devices = devices.filter((device) => device.id != scanResult.device.id).toList();
        devices.add(scanResult.device);
      });
    }).onDone(() {
      print("Scanning stopped.");
    });
  }

  Future<void> connectToDevice(DiscoveredDevice device) async {
    connectedDevice = await device.connect();
    print("Connected to ${connectedDevice!.id}");
    await readCharacteristic(connectedDevice!);
  }

  Future<void> readCharacteristic(ConnectedDevice device) async {
    final service = await device.discoverServices();
    final characteristic = service.characteristics.firstOrNull;
    if (characteristic != null) {
      final value = await characteristic.read();
      print("Characteristic value: ${value.toHex()}");
    }
  }

  Future<void> writeCharacteristic(ConnectedDevice device, Uint8List data) async {
    final service = await device.discoverServices();
    final characteristic = service.characteristics.firstOrNull;
    if (characteristic != null) {
      await characteristic.write(data);
      print("Characteristic written: ${data.toHex()}");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bluetooth Low Energy Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            Text('Discovered Devices:'),
            Expanded(
              child: ListView.builder(
                itemCount: devices.length,
                itemBuilder: (context, index) {
                  final device = devices[index];
                  return ListTile(
                    title: Text(device.name ?? 'Unknown'),
                    subtitle: Text(device.id),
                    onTap: () => connectToDevice(device),
                  );
                },
              ),
            ),
            if (connectedDevice != null) {
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Connected Device:'),
                  Text(connectedDevice!.id),
                  ElevatedButton(
                    onPressed: () async {
                      final data = Uint8List.fromList([0x01, 0x02, 0x03]);
                      await writeCharacteristic(connectedDevice!, data);
                    },
                    child: Text('Write Characteristic'),
                  ),
                ],
              )
            }
          ],
        ),
      ),
    );
  }
}

说明

  1. 初始化蓝牙:在initState方法中调用bleManager.initialize()来初始化蓝牙。
  2. 扫描设备:调用bleManager.startScanning()开始扫描附近的蓝牙设备,并将扫描到的设备添加到devices列表中。
  3. 连接设备:点击列表中的设备项时,调用connectToDevice方法连接到该设备。
  4. 读取特征值:连接成功后,调用readCharacteristic方法读取第一个特征值(示例中假设只有一个特征值)。
  5. 写入特征值:提供一个按钮,点击后调用writeCharacteristic方法向特征值写入数据。

注意事项

  • 确保在AndroidManifest.xmlInfo.plist中添加了必要的蓝牙权限。
  • 在实际使用中,可能需要处理更多的错误情况和边缘情况,例如设备连接失败、特征值读取/写入失败等。
  • bluetooth_low_energy插件的API可能会随着版本更新而变化,请参考最新的官方文档。

希望这个示例代码能帮助你理解如何在Flutter中使用bluetooth_low_energy插件进行低功耗蓝牙通信。

回到顶部