Flutter蓝牙通信插件all_bluetooth的使用

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

Flutter蓝牙通信插件all_bluetooth的使用

all_bluetooth 是一个用于在Flutter应用中与蓝牙设备进行通信的插件。本文将详细介绍如何使用该插件,并提供完整的示例代码。

特性

  • 连接到蓝牙设备
  • 返回已配对设备列表
  • 获取蓝牙状态(开/关)作为未来值或流
  • 启动蓝牙服务器
  • 监听蓝牙连接状态
  • 监听蓝牙连接上的数据传输

开始使用

添加依赖

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

dependencies:
    all_bluetooth: ^<latest-version>

配置Android权限

AndroidManifest.xml 文件中添加以下权限:

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

您可以使用 permission_handler 包来请求这些权限。

创建实例

在您的应用程序中创建 AllBluetooth 实例:

final allBluetooth = AllBluetooth();

导入包

在您的 Dart 文件中导入 all_bluetooth 包:

import "package:all_bluetooth/all_bluetooth.dart";

使用方法

在开始之前,请注意大多数功能仅在有可用的蓝牙连接时才能工作。因此,始终确保您正在监听蓝牙连接状态的 listenForConnection 流。

在调用任何函数之前,您可以使用 isBluetoothOn 方法或 streamBluetoothState 流来检查蓝牙是否打开或关闭。

主要方法和流

  • closeConnection: 关闭蓝牙连接并释放所有资源。
  • connectToDevice: 使用设备地址连接到另一个蓝牙设备。
  • getBondedDevices: 返回已配对设备列表。
  • isBluetoothOn: 检查蓝牙是否打开。
  • startBluetoothServer: 打开服务器套接字以连接为服务器。
  • startDiscovery: 开始发现新设备。
  • stopDiscovery: 停止发现设备。
  • sendMessage: 发送消息给连接的设备。
  • discoverNewDevices: 监听新发现的设备。
  • listenForConnection: 监听蓝牙连接状态。
  • listenForData: 监听通过蓝牙连接传输的数据。
  • streamBluetoothState: 监听设备蓝牙状态。

示例代码

以下是一个完整的示例代码,展示了如何使用 all_bluetooth 插件:

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

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

final allBluetooth = AllBluetooth();

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

  @override
  Widget build(BuildContext context) => MaterialApp(
        debugShowCheckedModeBanner: false,
        home: StreamBuilder<ConnectionResult>(
          stream: allBluetooth.listenForConnection,
          builder: (context, snapshot) {
            final state = snapshot.data?.state ?? false;
            if (state == true) {
              final device = snapshot.data!.device;
              return ChatScreen(device: device!);
            }
            return const HomeScreen();
          },
        ),
      );
}

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  bool listeningForClient = false;

  final bondedDevices = ValueNotifier<List<BluetoothDevice>>([]);
  final scannedDevices = ValueNotifier<List<BluetoothDevice>>([]);

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

  @override
  Widget build(BuildContext context) {
    return StreamBuilder<bool>(
      stream: allBluetooth.streamBluetoothState,
      builder: (context, snapshot) {
        final bluetoothOn = snapshot.data ?? false;
        return Scaffold(
          floatingActionButton: switch (listeningForClient) {
            true => null,
            false => FloatingActionButton(
                backgroundColor: switch (bluetoothOn) {
                  true => Theme.of(context).primaryColor,
                  false => Colors.grey,
                },
                onPressed: switch (bluetoothOn) {
                  false => null,
                  true => () {
                      allBluetooth.startBluetoothServer();
                      setState(() {
                        listeningForClient = true;
                      });
                    },
                },
                child: const Icon(Icons.wifi_tethering),
              )
          },
          appBar: AppBar(
            title: const Text("Bluetooth Connect"),
          ),
          body: switch (listeningForClient) {
            true => Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    const Text("Waiting"),
                    const CircularProgressIndicator(),
                    FloatingActionButton(
                      onPressed: () {
                        setState(() {
                          listeningForClient = false;
                        });
                        allBluetooth.closeConnection();
                      },
                      child: const Icon(Icons.stop),
                    ),
                  ],
                ),
              ),
            false => Column(
                children: [
                  SingleChildScrollView(
                    scrollDirection: Axis.horizontal,
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          switch (bluetoothOn) {
                            true => "ON",
                            false => "off",
                          },
                          style: TextStyle(
                            color: bluetoothOn ? Colors.green : Colors.red,
                          ),
                        ),
                        ElevatedButton(
                          onPressed: switch (bluetoothOn) {
                            false => null,
                            true => () {
                                allBluetooth
                                    .getBondedDevices()
                                    .then((newDevices) {
                                  bondedDevices.value = newDevices;
                                });
                              },
                          },
                          child: const Text("Bonded Devices"),
                        ),
                        ElevatedButton(
                          onPressed: switch (bluetoothOn) {
                            false => null,
                            true => () {
                                allBluetooth.startDiscovery();
                              },
                          },
                          child: const Text("Discover"),
                        ),
                        ElevatedButton(
                          onPressed: switch (bluetoothOn) {
                            false => null,
                            true => () {
                                allBluetooth.stopDiscovery();
                                allBluetooth.discoverDevices.listen((event) {
                                  scannedDevices.value = [
                                    ...scannedDevices.value,
                                    event
                                  ];
                                });
                              },
                          },
                          child: const Text("Stop discover"),
                        ),
                      ],
                    ),
                  ),
                  if (!bluetoothOn)
                    const Center(child: Text("Turn bluetooth on"))
                  else
                    Expanded(
                      child: Column(
                        children: [
                          DeviceListWidget(
                            notifier: bondedDevices,
                            title: "Paired Devices",
                          ),
                          DeviceListWidget(
                            notifier: scannedDevices,
                            title: "Scanned Devices",
                          ),
                        ],
                      ),
                    ),
                ],
              ),
          },
        );
      },
    );
  }
}

class ChatScreen extends StatefulWidget {
  final BluetoothDevice device;

  const ChatScreen({super.key, required this.device});

  @override
  State<ChatScreen> createState() => _ChatScreenState();
}

class _ChatScreenState extends State<ChatScreen> {
  final messageListener = ValueNotifier(<String>[]);
  final messageController = TextEditingController();

  @override
  void initState() {
    super.initState();
    allBluetooth.listenForData.listen((event) {
      if (event != null) {
        messageListener.value = [
          ...messageListener.value,
          event,
        ];
      }
    });
  }

  @override
  void dispose() {
    super.dispose();
    messageController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.device.name),
        actions: [
          ElevatedButton(
            onPressed: allBluetooth.closeConnection,
            child: const Text("CLOSE"),
          ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: Column(
          children: [
            Expanded(
              child: ValueListenableBuilder(
                  valueListenable: messageListener,
                  builder: (context, messages, child) {
                    return ListView.builder(
                      itemCount: messages.length,
                      itemBuilder: (context, index) {
                        final msg = messages[index];
                        return Padding(
                          padding: const EdgeInsets.symmetric(vertical: 5),
                          child: DecoratedBox(
                            decoration: BoxDecoration(
                              color: Theme.of(context).primaryColor,
                              borderRadius: BorderRadius.circular(10),
                            ),
                            child: Padding(
                              padding: const EdgeInsets.all(5),
                              child: Text(
                                msg,
                                style: const TextStyle(color: Colors.white),
                              ),
                            ),
                          ),
                        );
                      },
                    );
                  }),
            ),
            Row(
              children: [
                Expanded(
                  child: TextField(
                    controller: messageController,
                    decoration: const InputDecoration(
                      border: OutlineInputBorder(),
                    ),
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(12),
                  child: FloatingActionButton(
                    onPressed: () {
                      final message = messageController.text;
                      allBluetooth.sendMessage(message);
                      messageController.clear();
                      FocusScope.of(context).unfocus();
                    },
                    child: const Icon(Icons.send),
                  ),
                ),
              ],
            )
          ],
        ),
      ),
    );
  }
}

class DeviceListWidget extends StatelessWidget {
  final String title;
  final ValueNotifier<List<BluetoothDevice>> notifier;

  const DeviceListWidget({
    required this.notifier,
    required this.title,
    super.key,
  });

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: ValueListenableBuilder(
          valueListenable: notifier,
          builder: (context, value, child) {
            return Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text(
                      title,
                      style: const TextStyle(
                        decoration: TextDecoration.underline,
                        fontWeight: FontWeight.bold,
                        fontSize: 16,
                      ),
                    ),
                    Text(value.length.toString()),
                  ],
                ),
                Flexible(
                  fit: FlexFit.loose,
                  child: ListView.builder(
                    physics: const BouncingScrollPhysics(),
                    itemCount: value.length,
                    itemBuilder: (ctx, index) {
                      final device = value[index];
                      return ListTile(
                        title: Text(device.name),
                        subtitle: Text(device.address),
                        onTap: () async {
                          allBluetooth.connectToDevice(device.address);
                        },
                      );
                    },
                  ),
                ),
              ],
            );
          }),
    );
  }
}

以上代码展示了如何使用 all_bluetooth 插件来实现蓝牙设备的发现、连接和通信。希望这个示例能帮助您更好地理解和使用该插件。如果您有任何问题或建议,请随时联系插件作者。


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

1 回复

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


当然,以下是一个使用Flutter蓝牙通信插件all_bluetooth的基本代码示例。这个示例展示了如何初始化插件、扫描蓝牙设备、连接到一个设备以及读写数据。请注意,实际使用中需要根据具体需求进行错误处理和功能扩展。

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

dependencies:
  flutter:
    sdk: flutter
  all_bluetooth: ^最新版本号

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

接下来是示例代码:

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

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

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late BluetoothService _bluetoothService;
  List<BluetoothDevice> _devices = [];
  BluetoothDevice? _connectedDevice;

  @override
  void initState() {
    super.initState();
    _bluetoothService = BluetoothService.instance;
    _bluetoothService.init().then((_) {
      // 开始扫描设备
      startScanningDevices();
    });
  }

  void startScanningDevices() async {
    _devices.clear();
    setState(() {});
    try {
      _bluetoothService.startScanning().listen((List<BluetoothDevice> devices) {
        setState(() {
          _devices = devices;
        });
      });
    } catch (e) {
      print("Error scanning devices: $e");
    }
  }

  void connectToDevice(BluetoothDevice device) async {
    try {
      _connectedDevice = await _bluetoothService.connectToDevice(device);
      print("Connected to ${_connectedDevice?.name}");
      // 开始监听设备的数据
      startListeningToDeviceData();
    } catch (e) {
      print("Error connecting to device: $e");
    }
  }

  void startListeningToDeviceData() async {
    if (_connectedDevice != null) {
      _connectedDevice!.inputStream!.listen((Uint8List data) {
        String receivedData = String.fromCharCodes(data);
        print("Received data: $receivedData");
      });
    }
  }

  void sendDataToDevice(String data) async {
    if (_connectedDevice != null) {
      Uint8List dataToSend = Uint8List.fromList(data.codeUnits);
      _connectedDevice!.outputStream!.write(dataToSend);
      print("Sent data: $data");
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Bluetooth Communication'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            children: [
              Text('Scanned Devices:'),
              Expanded(
                child: ListView.builder(
                  itemCount: _devices.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text(_devices[index].name ?? 'Unknown'),
                      onTap: () => connectToDevice(_devices[index]),
                    );
                  },
                ),
              ),
              ElevatedButton(
                onPressed: _connectedDevice != null ? () => sendDataToDevice('Hello Device!') : null,
                child: Text('Send Data'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

注意事项:

  1. 权限:确保在Android和iOS平台上都申请了蓝牙相关的权限。
  2. 插件初始化_bluetoothService.init() 需要在开始使用蓝牙功能之前调用。
  3. 错误处理:实际应用中应添加更多的错误处理逻辑,例如处理连接失败、设备断开等情况。
  4. 平台差异:不同平台(Android和iOS)上蓝牙通信的实现可能有所不同,请仔细阅读all_bluetooth插件的文档以了解平台特定的差异。

这个示例代码提供了一个基本的框架,你可以在此基础上根据你的具体需求进行扩展和修改。

回到顶部