Flutter蓝牙通信插件flutter_bluetooth_plus的使用

Flutter蓝牙通信插件flutter_bluetooth_plus的使用

flutter_bluetooth_plus 是一个基于 flutter_bluetooth_basic 修改的 Flutter 插件,主要用于支持 Android POS 设备上的虚拟蓝牙打印机。该插件允许查找蓝牙设备并发送原始字节数据。它同时支持 Android 和 iOS 平台。

主要功能

  • 支持 Android 和 iOS。
  • 扫描蓝牙设备。
  • 发送原始 List<int> 字节数据到设备。

开始使用

完整的示例可以在 /example 文件夹中查看。以下是库的基本使用方法。

BluetoothManager bluetoothManager = BluetoothManager.instance;
BluetoothDevice _device;

bluetoothManager.startScan(timeout: Duration(seconds: 4));
bluetoothManager.state.listen((state) {
    switch (state) {
    case BluetoothManager.CONNECTED:
        // 连接成功时的操作
        break;
    case BluetoothManager.DISCONNECTED:
        // 断开连接时的操作
        break;
    default:
        break;
    }
});
// bluetoothManager.scanResults 是一个 Stream<List<BluetoothDevice>>,用于发送找到的设备。

// _device = <从 bluetoothManager.scanResults 中获取>

await bluetoothManager.connect(_device);

List<int> bytes = latin1.encode('Hello world!\n').toList();
await bluetoothManager.writeData(bytes);

await bluetoothManager.disconnect();

示例代码

以下是一个完整的示例代码,展示了如何使用 flutter_bluetooth_plus 插件进行蓝牙通信。

import 'dart:convert';

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

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

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

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  BluetoothManager bluetoothManager = BluetoothManager.instance;

  bool _connected = false;
  BluetoothDevice _device;
  String tips = 'no device connect';

  [@override](/user/override)
  void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback((_) => initBluetooth());
  }

  // 初始化蓝牙
  Future<void> initBluetooth() async {
    bluetoothManager.startScan(timeout: Duration(seconds: 4));

    bool isConnected = await bluetoothManager.isConnected;

    bluetoothManager.state.listen((state) {
      print('当前设备状态: $state');

      switch (state) {
        case BluetoothManager.CONNECTED:
          setState(() {
            _connected = true;
            tips = '连接成功';
          });
          break;
        case BluetoothManager.DISCONNECTED:
          setState(() {
            _connected = false;
            tips = '断开连接';
          });
          break;
        default:
          break;
      }
    });

    if (!mounted) return;

    if (isConnected) {
      setState(() {
        _connected = true;
      });
    }
  }

  // 连接设备
  void _onConnect() async {
    if (_device != null && _device.address != null) {
      await bluetoothManager.connect(_device);
    } else {
      setState(() {
        tips = '请选择设备';
      });
      print('请选择设备');
    }
  }

  // 断开连接
  void _onDisconnect() async {
    await bluetoothManager.disconnect();
  }

  // 发送数据
  void _sendData() async {
    List<int> bytes = latin1.encode('Hello world!\n\n\n').toList();

    // 设置编码表为西欧。需要添加 import 'dart:typed_data';
    // List<int> bytes = Uint8List.fromList(List.from('\x1Bt'.codeUnits)..add(6));
    // 包含特殊字符的文本
    // bytes += latin1.encode('blåbærgrød\n\n\n');

    await bluetoothManager.writeData(bytes);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: RefreshIndicator(
        onRefresh: () =>
            bluetoothManager.startScan(timeout: Duration(seconds: 4)),
        child: SingleChildScrollView(
          child: Column(
            children: [
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  Padding(
                    padding: EdgeInsets.symmetric(vertical: 10, horizontal: 10),
                    child: Text(tips),
                  ),
                ],
              ),
              Divider(),
              StreamBuilder<List<BluetoothDevice>>(
                stream: bluetoothManager.scanResults,
                initialData: [],
                builder: (c, snapshot) => Column(
                  children: snapshot.data
                      .map((d) => ListTile(
                            title: Text(d.name ?? ''),
                            subtitle: Text(d.address),
                            onTap: () async {
                              setState(() {
                                _device = d;
                              });
                            },
                            trailing:
                                _device != null && _device.address == d.address
                                    ? Icon(
                                        Icons.check,
                                        color: Colors.green,
                                      )
                                    : null,
                          ))
                      .toList(),
                ),
              ),
              Divider(),
              Container(
                padding: EdgeInsets.fromLTRB(20, 5, 20, 10),
                child: Column(
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        OutlineButton(
                          child: Text('连接'),
                          onPressed: _connected ? null : _onConnect,
                        ),
                        SizedBox(width: 10.0),
                        OutlineButton(
                          child: Text('断开连接'),
                          onPressed: _connected ? _onDisconnect : null,
                        ),
                      ],
                    ),
                    OutlineButton(
                      child: Text('发送测试数据'),
                      onPressed: _connected ? _sendData : null,
                    ),
                  ],
                ),
              )
            ],
          ),
        ),
      ),
      floatingActionButton: StreamBuilder<bool>(
        stream: bluetoothManager.isScanning,
        initialData: false,
        builder: (c, snapshot) {
          if (snapshot.data) {
            return FloatingActionButton(
              child: Icon(Icons.stop),
              onPressed: () => bluetoothManager.stopScan(),
              backgroundColor: Colors.red,
            );
          } else {
            return FloatingActionButton(
                child: Icon(Icons.search),
                onPressed: () =>
                    bluetoothManager.startScan(timeout: Duration(seconds: 4)));
          }
        },
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何使用Flutter蓝牙通信插件flutter_bluetooth_plus的示例代码。这个示例展示了如何扫描蓝牙设备、连接到设备以及读写数据。

1. 添加依赖

首先,在pubspec.yaml文件中添加flutter_bluetooth_plus依赖:

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

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

2. 导入插件

在你的Dart文件中导入插件:

import 'package:flutter_bluetooth_plus/flutter_bluetooth_plus.dart';

3. 请求权限

在Android上,你需要请求位置权限来扫描蓝牙设备。在AndroidManifest.xml中添加以下权限:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>

然后在Flutter代码中请求权限:

import 'package:permission_handler/permission_handler.dart';

Future<void> requestPermissions() async {
  var status = await Permission.locationWhenInUse.status;
  if (!status.isGranted) {
    Map<Permission, PermissionStatus> statuses = await Permission.requestMultiple([
      Permission.locationWhenInUse,
      Permission.bluetooth,
      Permission.bluetoothScan,
      Permission.bluetoothConnect,
    ]);
  }
}

4. 扫描蓝牙设备

Future<void> scanDevices() async {
  FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

  bluetooth.startScan(allowDuplicates: false).listen((device) {
    print("Device found: ${device.name}, Address: ${device.address}");
    // 在这里你可以存储或显示扫描到的设备
  }).onDone(() {
    print("Scan done");
  }).onError((error) {
    print("Scan error: $error");
  });

  // 停止扫描(例如,5秒后)
  Future.delayed(Duration(seconds: 5), () {
    bluetooth.stopScan();
  });
}

5. 连接到设备

Future<void> connectToDevice(String deviceAddress) async {
  FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

  try {
    await bluetooth.connect(deviceAddress);
    print("Connected to device: $deviceAddress");
  } catch (e) {
    print("Failed to connect: $e");
  }
}

6. 读写数据

Future<void> writeDataToDevice(String deviceAddress, Uint8List data) async {
  FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

  try {
    await bluetooth.write(deviceAddress, BluetoothService.uuid('0000180d-0000-1000-8000-00805f9b34fb'), BluetoothCharacteristic.uuid('00002a37-0000-1000-8000-00805f9b34fb'), data);
    print("Data written successfully");
  } catch (e) {
    print("Failed to write data: $e");
  }
}

Future<void> readDataFromDevice(String deviceAddress) async {
  FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

  try {
    Uint8List data = await bluetooth.read(deviceAddress, BluetoothService.uuid('0000180d-0000-1000-8000-00805f9b34fb'), BluetoothCharacteristic.uuid('00002a37-0000-1000-8000-00805f9b34fb'));
    print("Data read: ${data.map((byte) => byte.toRadixString(16).padStart(2, '0')).join('')}");
  } catch (e) {
    print("Failed to read data: $e");
  }
}

7. 断开连接

Future<void> disconnectFromDevice(String deviceAddress) async {
  FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

  try {
    await bluetooth.disconnect(deviceAddress);
    print("Disconnected from device: $deviceAddress");
  } catch (e) {
    print("Failed to disconnect: $e");
  }
}

完整示例

将上述代码片段整合到一个完整的示例中:

import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_plus/flutter_bluetooth_plus.dart';
import 'package:permission_handler/permission_handler.dart';

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

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  [@override](/user/override)
  void initState() {
    super.initState();
    requestPermissions();
    scanDevices();
  }

  Future<void> requestPermissions() async {
    var status = await Permission.locationWhenInUse.status;
    if (!status.isGranted) {
      Map<Permission, PermissionStatus> statuses = await Permission.requestMultiple([
        Permission.locationWhenInUse,
        Permission.bluetooth,
        Permission.bluetoothScan,
        Permission.bluetoothConnect,
      ]);
    }
  }

  Future<void> scanDevices() async {
    FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

    bluetooth.startScan(allowDuplicates: false).listen((device) {
      print("Device found: ${device.name}, Address: ${device.address}");
      // 假设我们连接到第一个找到的设备
      if (!mounted) return;
      setState(() {
        _deviceAddress = device.address;
      });
      Future.delayed(Duration(seconds: 1), () {
        bluetooth.stopScan();
        connectToDevice(_deviceAddress);
      });
    }).onDone(() {
      print("Scan done");
    }).onError((error) {
      print("Scan error: $error");
    });
  }

  late String _deviceAddress = "";

  Future<void> connectToDevice() async {
    FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

    try {
      await bluetooth.connect(_deviceAddress);
      print("Connected to device: $_deviceAddress");
      // 连接成功后,可以读写数据
      Uint8List dataToWrite = Uint8List.fromList([0x01, 0x02, 0x03]);
      writeDataToDevice(_deviceAddress, dataToWrite);
      readDataFromDevice(_deviceAddress);
    } catch (e) {
      print("Failed to connect: $e");
    }
  }

  Future<void> writeDataToDevice(Uint8List data) async {
    FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

    try {
      await bluetooth.write(_deviceAddress, BluetoothService.uuid('0000180d-0000-1000-8000-00805f9b34fb'), BluetoothCharacteristic.uuid('00002a37-0000-1000-8000-00805f9b34fb'), data);
      print("Data written successfully");
    } catch (e) {
      print("Failed to write data: $e");
    }
  }

  Future<void> readDataFromDevice() async {
    FlutterBluetoothPlus bluetooth = FlutterBluetoothPlus();

    try {
      Uint8List data = await bluetooth.read(_deviceAddress, BluetoothService.uuid('0000180d-0000-1000-8000-00805f9b34fb'), BluetoothCharacteristic.uuid('00002a37-0000-1000-8000-00805f9b34fb'));
      print("Data read: ${data.map((byte) => byte.toRadixString(16).padStart(2, '0')).join('')}");
    } catch (e) {
      print("Failed to read data: $e");
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context)
回到顶部