Flutter蓝牙通信插件my_bluetooth的使用

Flutter蓝牙通信插件my_bluetooth的使用

简介

my_bluetooth 是一个用于Flutter项目的插件,它简化了通过蓝牙与其他设备进行连接和数据传输的过程。该插件提供了易于使用的API,可以扫描、连接和交换数据。

功能

  • 扫描附近的蓝牙设备
  • 连接蓝牙设备
  • 发送和接收数据
  • 自定义连接和传输

支持平台

方法 Android iOS 描述
turnOn() ✅ 打开蓝牙
adapterState ✅ ✅ 获取适配器状态
bondedDevices ✅ 获取已配对设备
discoveryState ✅ ✅ 获取扫描状态
startScan() ✅ ✅ 开始扫描附近设备
stopScan() ✅ 停止扫描
lastScanResults ✅ 获取最后一次扫描结果
scanResults ✅ 获取扫描结果
connectionState ✅ ✅ 设备连接状态
sendingState ✅ ✅ 发送状态
connect() (iOS自动连接) ✅ ✅ 连接设备
disconnect() ✅ ✅ 断开连接
send data ✅ ✅ 发送数据

权限

在使用此插件时,需要以下权限:

  • Bluetooth
  • Bluetooth scan
  • Bluetooth connect
  • access_fine_location

使用方法

1. 添加依赖

在 pubspec.yaml 文件中添加 my_bluetooth 依赖:

dependencies:
  flutter:
    sdk: flutter
  my_bluetooth: ^latest_version

然后运行以下命令来获取依赖项:

flutter pub get
2. 导入包

在 Dart 文件中导入 my_bluetooth 包:

import 'package:my_bluetooth/my_bluetooth.dart';
3. iOS 设置

由于 iOS 的安全问题,需要在 ios/Runner/Info.plist 文件中添加以下内容:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>此应用始终需要蓝牙功能</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>此应用需要蓝牙外围设备功能</string>
<key>UISupportedExternalAccessoryProtocols</key>
<array>
  <string>net.dsgl.nailpopPro.protocol</string>
  <!-- 使用你自己的协议 -->
</array>
<key>UIBackgroundModes</key>
<array>
  <string>bluetooth-central</string>
  <string>external-accessory</string>
  <string>fetch</string>
  <string>remote-notification</string>
</array>
4. 示例代码

以下是一个完整的示例代码,展示了如何使用 my_bluetooth 插件进行蓝牙设备的扫描、连接和数据发送。

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:my_bluetooth/my_bluetooth.dart';

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

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final XFile? image;

  final _myBluetooth = MyBluetooth();

  MPBluetoothAdapterState _adapterState = MPBluetoothAdapterState.unknown;
  late StreamSubscription<MPBluetoothAdapterState> _adapterStateStateSubscription;

  bool _isScanning = false;
  late StreamSubscription<bool> _isScanningSubscription;

  MPConnectionStateEnum _connectState = MPConnectionStateEnum.disconnected;
  late StreamSubscription<ConnectionStateResponse> _connectStateSubscription;

  late StreamSubscription<List<BluetoothDevice>> _scanResultsSubscription;
  List<BluetoothDevice> _scanResults = [];

  [@override](/user/override)
  void initState() {
    super.initState();
    // 监听蓝牙适配器状态变化
    _adapterStateStateSubscription = _myBluetooth.adapterState.listen((state) {
      _adapterState = state;
      if (mounted) {
        setState(() {});
      }
    }, onError: (e) {});

    // 监听连接状态变化
    _connectStateSubscription = _myBluetooth.connectionState.listen((state) {
      _connectState = state.connectionState;
      if (mounted) {
        setState(() {});
      }
    }, onError: (e) {});

    // 监听扫描状态变化
    _isScanningSubscription = _myBluetooth.discoveryState.listen((state) {
      _isScanning = state;
      if (mounted) {
        setState(() {});
      }
    }, onError: (e) {});

    // 监听扫描结果
    _scanResultsSubscription = _myBluetooth.scanResults.listen((results) {
      _scanResults = results;
      if (mounted) {
        setState(() {});
      }
    }, onError: (e) {});
  }

  [@override](/user/override)
  void dispose() {
    // 取消所有订阅
    _adapterStateStateSubscription.cancel();
    _scanResultsSubscription.cancel();
    _connectStateSubscription.cancel();
    _isScanningSubscription.cancel();

    super.dispose();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Plugin example app | My Bluetooth'),
        ),
        body: Center(
          child: SingleChildScrollView(
            child: Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                const Text("步骤 1. 打开/关闭蓝牙"),
                Text("蓝牙适配器状态: ${_adapterState.toString()}"),
                TextButton(
                    onPressed: () async {
                      await _myBluetooth.turnOn();
                    },
                    child: const Text("打开蓝牙")),
                const Text("步骤 2: 扫描设备"),
                Text("正在扫描: ${_isScanning.toString()}"),
                const SizedBox(
                  height: 20,
                ),
                const Text("步骤 3: 连接"),
                Text("连接状态: $_connectState"),
                TextButton(
                    onPressed: () async {
                      print(await _myBluetooth.disconnect());
                    },
                    child: const Text("断开连接")),
                const SizedBox(
                  height: 20,
                ),
                Row(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Expanded(
                      flex: 1,
                      child: Column(
                        mainAxisSize: MainAxisSize.max,
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          TextButton(
                              onPressed: () async {
                                var bondedDevices = await _myBluetooth.bondedDevices;
                                setState(() {
                                  _scanResults = bondedDevices;
                                });
                                print("已配对设备数量: ${bondedDevices.length}");
                              },
                              child: const Text("获取已配对设备")),
                          TextButton(
                              onPressed: () async {
                                await _myBluetooth.startScan(withKeywords: [
                                  // "Nailpop", "Nailpop Pro",
                                  // "Snap# Kiosk", "DMP"
                                  // "image box"
                                ]);
                              },
                              child: const Text("开始扫描")),
                          TextButton(
                              onPressed: () async {
                                print(await _myBluetooth.stopScan());
                              },
                              child: const Text("停止扫描")),
                        ],
                      ),
                    ),
                    SizedBox(
                      width: MediaQuery.of(context).size.width / 3 * 2,
                      height: 140,
                      child: ListView.builder(
                        scrollDirection: Axis.horizontal,
                        shrinkWrap: true,
                        itemCount: _scanResults.length,
                        itemBuilder: (BuildContext context, int index) {
                          final item = _scanResults[index];
                          return GestureDetector(
                            onTap: () async {
                              print("点击 ${item.remoteId}");
                              print(await _myBluetooth.connect(remoteId: item.remoteId));
                            },
                            child: Container(
                              margin: const EdgeInsets.symmetric(horizontal: 20),
                              padding: const EdgeInsets.all(20),
                              decoration: BoxDecoration(
                                  color: Colors.blueAccent.withOpacity(0.2)),
                              child: Column(
                                mainAxisSize: MainAxisSize.min,
                                children: [
                                  Text(
                                    "名称: ${item.platformName}",
                                    style: const TextStyle(fontWeight: FontWeight.bold),
                                  ),
                                  Text("ID: ${item.remoteId}"),
                                  Text("配对状态: ${item.bondState}"),
                                  Text("类型: ${item.type}"),
                                ],
                              ),
                            ),
                          );
                        },
                      ),
                    )
                  ],
                ),

                const Text(
                  "发送文本到设备",
                  style: TextStyle(fontWeight: FontWeight.w800),
                ),
                TextButton(
                    onPressed: () async {
                      await _myBluetooth.sendText(value: "Hello World");
                    },
                    child: const Text("1 | 发送文本 'Hello World'")),

                // 发送文件
                const Text(
                  "如何发送文件?",
                  style: TextStyle(fontWeight: FontWeight.w800),
                ),
                TextButton(
                    onPressed: () async {
                      final ImagePicker picker = ImagePicker();
                      image = await picker.pickImage(source: ImageSource.gallery);

                      print(image?.path);
                    },
                    child: const Text("步骤 1 | 选择文件")),

                const SizedBox(
                  height: 10,
                ),
                TextButton(
                    onPressed: () async {
                      if (image != null) {
                        print(await _myBluetooth.sendFile(pathImage: image?.path));
                      } else {
                        ScaffoldMessenger.of(context).showSnackBar(
                            const SnackBar(content: Text("请先选择文件")));
                      }
                    },
                    child: const Text("步骤 3 | 发送文件")),

                // 发送自定义命令
                const Text(
                  "注意!!!你可以使用 'sendCmd' 函数发送任何数据。",
                  style: TextStyle(fontWeight: FontWeight.w500),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个关于如何使用Flutter蓝牙通信插件my_bluetooth的代码示例。请注意,由于my_bluetooth并非一个广为人知的官方或广泛使用的插件,代码示例将基于假设的API设计。如果my_bluetooth插件的API有所不同,请参考其官方文档进行调整。

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

dependencies:
  flutter:
    sdk: flutter
  my_bluetooth: ^x.y.z  # 替换为实际版本号

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

接下来,是一个使用my_bluetooth插件进行蓝牙通信的基本示例:

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

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

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

class _MyAppState extends State<MyApp> {
  MyBluetooth? _bluetooth;
  List<BluetoothDevice> _devices = [];
  BluetoothDevice? _connectedDevice;

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

  Future<void> _initBluetooth() async {
    _bluetooth = MyBluetooth();

    // 请求蓝牙权限(假设API提供此方法)
    bool hasPermission = await _bluetooth!.requestPermission();
    if (!hasPermission) {
      // 处理权限被拒绝的情况
      return;
    }

    // 启用蓝牙(假设API提供此方法)
    bool isEnabled = await _bluetooth!.isEnabled();
    if (!isEnabled) {
      await _bluetooth!.enable();
    }

    // 开始扫描设备(假设API提供此方法)
    _bluetooth!.scanDevices().listen((List<BluetoothDevice> devices) {
      setState(() {
        _devices = devices;
      });
    });
  }

  Future<void> _connectToDevice(BluetoothDevice device) async {
    setState(() {
      _connectedDevice = device;
    });

    // 连接到设备(假设API提供此方法)
    bool isConnected = await _bluetooth!.connectToDevice(device);
    if (isConnected) {
      // 处理连接成功的情况
      print('Connected to ${device.name}');
    } else {
      // 处理连接失败的情况
      print('Failed to connect to ${device.name}');
    }
  }

  Future<void> _sendData(String data) async {
    if (_connectedDevice != null) {
      // 发送数据到设备(假设API提供此方法)
      bool isSent = await _bluetooth!.sendData(_connectedDevice!, data);
      if (isSent) {
        print('Data sent: $data');
      } else {
        print('Failed to send data: $data');
      }
    } else {
      print('No device connected');
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Bluetooth Communication'),
        ),
        body: Column(
          children: [
            Expanded(
              child: ListView.builder(
                itemCount: _devices.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(_devices[index].name),
                    onTap: () => _connectToDevice(_devices[index]),
                  );
                },
              ),
            ),
            ElevatedButton(
              onPressed: () async {
                await _sendData('Hello, Bluetooth!');
              },
              child: Text('Send Data'),
            ),
          ],
        ),
      ),
    );
  }
}

// 假设的BluetoothDevice类
class BluetoothDevice {
  String name;
  String address; // 设备地址

  BluetoothDevice({required this.name, required this.address});
}

注意:

  1. 上述代码是基于假设的API设计,my_bluetooth插件的实际API可能会有所不同。请参考插件的官方文档获取正确的API使用方法。
  2. 蓝牙权限请求、启用蓝牙、扫描设备、连接设备以及发送数据等操作通常需要异步处理,因此使用了async和await关键字。
  3. 错误处理和用户交互(如权限被拒绝、蓝牙未启用、设备连接失败等情况)应根据实际需求进行完善。
  4. BluetoothDevice类是一个假设的类,实际使用时应根据插件提供的类进行替换。

希望这个示例能帮助你开始使用my_bluetooth插件进行蓝牙通信。如果有任何问题或需要进一步的帮助,请随时提问。

回到顶部