Flutter蓝牙通信插件flutter_blue_plugin的使用

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

Flutter蓝牙通信插件flutter_blue_plugin的使用

简介

flutter_blue_plugin 是一个用于Flutter的蓝牙插件,支持iOS和Android平台。它允许开发者扫描、连接到附近的蓝牙设备,并与这些设备进行交互。

Alpha版本注意

此库在生产应用中积极开发,API可能会随着版本更新而变化,请确保准备好应对可能的不兼容更改。此外,该插件必须在真实设备上测试。

跨平台蓝牙LE

通过FlutterBlue实例,您可以扫描并连接附近的设备(BluetoothDevice)。一旦连接到设备,可以通过发现服务(BluetoothService)、特性(BluetoothCharacteristic)和描述符(BluetoothDescriptor)来直接与之交互。

使用指南

获取实例

FlutterBlue flutterBlue = FlutterBlue.instance;

扫描设备

// 开始扫描
flutterBlue.startScan(timeout: Duration(seconds: 4));

// 监听扫描结果
var subscription = flutterBlue.scanResults.listen((results) {
    // 处理扫描结果
    for (ScanResult r in results) {
        print('${r.device.name} found! rssi: ${r.rssi}');
    }
});

// 停止扫描
flutterBlue.stopScan();

连接到设备

// 连接到设备
await device.connect();

// 断开连接
device.disconnect();

发现服务

List<BluetoothService> services = await device.discoverServices();
services.forEach((service) {
    // 处理服务
});

读写特性

// 读取所有特性
var characteristics = service.characteristics;
for(BluetoothCharacteristic c in characteristics) {
    List<int> value = await c.read();
    print(value);
}

// 写入特性
await c.write([0x12, 0x34]);

设置通知并监听变化

await characteristic.setNotifyValue(true);
characteristic.value.listen((value) {
    // 处理新值
});

示例代码

下面是一个完整的示例demo,展示了如何使用flutter_blue_plugin进行蓝牙设备的扫描、连接和服务发现:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Blue Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: FindDevicesScreen(),
    );
  }
}

class FindDevicesScreen extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Find Devices'),
      ),
      body: RefreshIndicator(
        onRefresh: () => _startScan(),
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              StreamBuilder<List<BluetoothDevice>>(
                stream: Stream.periodic(Duration(seconds: 2))
                    .asyncMap((_) => FlutterBlue.instance.connectedDevices),
                initialData: [],
                builder: (c, snapshot) => Column(
                  children: snapshot.data!
                      .map((d) => ListTile(
                            title: Text(d.name),
                            subtitle: Text(d.id.toString()),
                          ))
                      .toList(),
                ),
              ),
              StreamBuilder<List<ScanResult>>(
                stream: FlutterBlue.instance.scanResults,
                initialData: [],
                builder: (c, snapshot) => Column(
                  children: snapshot.data!
                      .map(
                        (r) => ScanResultTile(
                          result: r,
                          onTap: () => Navigator.of(context)
                              .push(MaterialPageRoute(builder: (context) {
                            r.device.connect();
                            return DeviceScreen(device: r.device);
                          })),
                        ),
                      )
                      .toList(),
                ),
              ),
            ],
          ),
        ),
      ),
      floatingActionButton: StreamBuilder<bool>(
        stream: FlutterBlue.instance.isScanning,
        initialData: false,
        builder: (c, snapshot) {
          if (snapshot.data!) {
            return FloatingActionButton(
              child: Icon(Icons.stop),
              onPressed: () => FlutterBlue.instance.stopScan(),
              backgroundColor: Colors.red,
            );
          } else {
            return FloatingActionButton(
              child: Icon(Icons.search),
              onPressed: () async {
                await FlutterBlue.instance.startScan(timeout: Duration(seconds: 4));
              },
            );
          }
        },
      ),
    );
  }

  Future<void> _startScan() async {
    await FlutterBlue.instance.startScan(timeout: Duration(seconds: 4)).drain();
  }
}

class DeviceScreen extends StatelessWidget {
  const DeviceScreen({Key? key, required this.device}) : super(key: key);

  final BluetoothDevice device;

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(device.name),
        actions: <Widget>[
          StreamBuilder<BluetoothDeviceState>(
            stream: device.state,
            initialData: BluetoothDeviceState.connecting,
            builder: (c, snapshot) {
              VoidCallback? onPressed;
              String text;
              switch (snapshot.data) {
                case BluetoothDeviceState.connected:
                  onPressed = () => device.disconnect();
                  text = 'DISCONNECT';
                  break;
                case BluetoothDeviceState.disconnected:
                  onPressed = () => device.connect();
                  text = 'CONNECT';
                  break;
                default:
                  onPressed = null;
                  text = snapshot.data.toString().substring(21).toUpperCase();
                  break;
              }
              return ElevatedButton(
                  onPressed: onPressed,
                  child: Text(text));
            },
          )
        ],
      ),
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            StreamBuilder<BluetoothDeviceState>(
              stream: device.state,
              initialData: BluetoothDeviceState.connecting,
              builder: (c, snapshot) => ListTile(
                leading: (snapshot.data == BluetoothDeviceState.connected)
                    ? Icon(Icons.bluetooth_connected)
                    : Icon(Icons.bluetooth_disabled),
                title: Text('Device is ${snapshot.data.toString().split('.')[1]}.'),
                subtitle: Text('${device.id}'),
              ),
            ),
            StreamBuilder<List<BluetoothService>>(
              stream: device.services,
              initialData: [],
              builder: (c, snapshot) {
                if (snapshot.data == null) return Text('Empty');
                return Column(
                  children: snapshot.data!.map((service) {
                    return ListTile(
                      title: Text(service.uuid.toString()),
                    );
                  }).toList(),
                );
              },
            ),
          ],
        ),
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何使用Flutter蓝牙通信插件flutter_blue_plugin(注意:实际插件名为flutter_blue,这里假设你是指这个广泛使用的插件)的示例代码。这个示例展示了如何扫描蓝牙设备、连接到设备以及读写蓝牙特性(Characteristic)。

首先,确保你的pubspec.yaml文件中已经添加了flutter_blue依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_blue: ^0.13.0  # 请检查最新版本号

然后运行flutter pub get来获取依赖。

接下来是示例代码,展示如何使用flutter_blue插件:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Bluetooth Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: BluetoothScreen(),
    );
  }
}

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

class _BluetoothScreenState extends State<BluetoothScreen> {
  BluetoothDevice? _connectedDevice;
  BluetoothCharacteristic? _characteristic;
  BluetoothState _bluetoothState = BluetoothState.unknown;
  List<BluetoothDevice> _devices = [];

  @override
  void initState() {
    super.initState();
    FlutterBlue.instance.state.listen((state) {
      setState(() {
        _bluetoothState = state;
      });
      if (state == BluetoothState.on) {
        FlutterBlue.instance.startScan(timeout: Duration(seconds: 4)).listen((scanResult) {
          setState(() {
            _devices.add(scanResult.device);
          });
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Bluetooth Devices'),
      ),
      body: _buildBody(),
    );
  }

  Widget _buildBody() {
    if (_bluetoothState == BluetoothState.off) {
      return Center(
        child: Text('Bluetooth is off'),
      );
    }

    if (_bluetoothState == BluetoothState.turningOn) {
      return Center(
        child: CircularProgressIndicator(),
      );
    }

    if (_devices.isEmpty) {
      return Center(
        child: Text('No devices found. Make sure Bluetooth is on and try again.'),
      );
    }

    return Column(
      children: <Widget>[
        Expanded(
          child: ListView.builder(
            itemCount: _devices.length,
            itemBuilder: (_, index) {
              final device = _devices[index];
              return ListTile(
                title: Text(device.name ?? 'Unknown device'),
                subtitle: Text('Address: ${device.id}'),
                trailing: Icon(
                  device.isConnected ? Icons.check : Icons.bluetooth,
                  color: device.isConnected ? Colors.green : null,
                ),
                onTap: () async {
                  setState(() {
                    _devices.clear();
                  });

                  await device.connect();
                  await device.discoverServices();

                  setState(() {
                    _connectedDevice = device;
                  });

                  List<BluetoothService> services = device.services;
                  if (services.isNotEmpty) {
                    BluetoothService service = services.first;
                    List<BluetoothCharacteristic> characteristics = service.characteristics;
                    if (characteristics.isNotEmpty) {
                      setState(() {
                        _characteristic = characteristics.first;
                      });
                      await _characteristic!.setNotifyValue(true);
                      _characteristic!.value.listen((value) {
                        // Handle incoming data
                        print('Data: ${value.toUint8List()}');
                      });
                    }
                  }
                },
              );
            },
          ),
        ),
        if (_connectedDevice != null)
          ElevatedButton(
            onPressed: () async {
              if (_characteristic != null) {
                // Write data to characteristic
                Uint8List data = Uint8List.fromList([0x01, 0x02, 0x03]); // Example data
                await _characteristic!.write(data);
              }
            },
            child: Text('Write Data'),
          ),
      ],
    );
  }
}

代码说明:

  1. 依赖引入:在pubspec.yaml中引入flutter_blue插件。
  2. 状态管理:在_BluetoothScreenState中管理蓝牙状态、扫描到的设备和已连接的设备。
  3. 初始化:在initState中监听蓝牙状态变化,并在蓝牙开启时开始扫描设备。
  4. UI构建
    • 显示蓝牙状态(开/关/正在打开)。
    • 扫描到的设备列表,点击设备连接并发现服务。
    • 如果有连接的设备,提供一个按钮来写入数据到蓝牙特性。
  5. 数据读写:连接到设备后,发现服务并读取第一个特性的值,同时设置通知以监听数据变化。提供一个按钮来写入数据到该特性。

请注意,这个示例代码是简化的,实际应用中可能需要处理更多的错误情况和边缘情况。另外,根据具体的蓝牙设备和服务,可能需要调整代码以匹配特定的服务和特性UUID。

回到顶部