Flutter蓝牙通信插件my_bluetooth的使用

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

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. 蓝牙权限请求、启用蓝牙、扫描设备、连接设备以及发送数据等操作通常需要异步处理,因此使用了asyncawait关键字。
  3. 错误处理和用户交互(如权限被拒绝、蓝牙未启用、设备连接失败等情况)应根据实际需求进行完善。
  4. BluetoothDevice类是一个假设的类,实际使用时应根据插件提供的类进行替换。

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

回到顶部