You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求Flutter实现BLE设备文件下载及数据交互响应代码方案

Flutter BLE设备文件下载及数据响应处理方案

依赖配置

在pubspec.yaml中添加BLE操作依赖:

dependencies:
  flutter_blue_plus: ^1.13.18
  path_provider: ^2.1.1

核心实现代码

import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'dart:io';
import 'package:path_provider/path_provider.dart';

class BLEDataDownloader {
  BluetoothDevice? _connectedDevice;
  BluetoothCharacteristic? _txChar; // 发送数据特征
  BluetoothCharacteristic? _rxChar; // 接收数据特征
  File? _targetFile;
  List<int> _fileBuffer = [];
  bool _isDownloading = false;

  // 扫描并连接指定设备
  Future<void> connectDevice(String targetDeviceId) async {
    final flutterBlue = FlutterBluePlus.instance;
    // 开始扫描
    flutterBlue.startScan(timeout: const Duration(seconds: 5));
    flutterBlue.scanResults.listen((results) {
      for (final result in results) {
        if (result.device.id.toString() == targetDeviceId) {
          flutterBlue.stopScan();
          _establishConnection(result.device);
          break;
        }
      }
    });
  }

  // 建立设备连接并绑定特征
  Future<void> _establishConnection(BluetoothDevice device) async {
    await device.connect();
    _connectedDevice = device;

    // 发现设备服务
    final services = await device.discoverServices();
    for (final service in services) {
      // 替换为你的BLE服务UUID
      if (service.uuid.toString() == "0000ffe0-0000-1000-8000-00805f9b34fb") {
        for (final char in service.characteristics) {
          // 替换为你的BLE通信特征UUID
          if (char.uuid.toString() == "0000ffe1-0000-1000-8000-00805f9b34fb") {
            if (char.properties.write) _txChar = char;
            if (char.properties.notify) {
              _rxChar = char;
              await char.setNotifyValue(true);
              // 监听设备返回数据
              char.value.listen(_parseIncomingData);
            }
          }
        }
      }
    }
  }

  // 解析并分类处理设备返回数据
  void _parseIncomingData(List<int> rawData) {
    // 根据设备协议解析帧类型(示例:第2字节为帧类型标识)
    final frameType = rawData[1];

    switch (frameType) {
      case 0x01: // 文件下载确认帧
        _initFileDownload();
        break;
      case 0x02: // 文件数据帧
        _appendFileData(rawData);
        break;
      case 0x03: // 下载完成帧
        _completeFileDownload();
        break;
      default:
        print("未知帧类型: $frameType");
    }
  }

  // 初始化文件下载
  Future<void> _initFileDownload() async {
    final docDir = await getApplicationDocumentsDirectory();
    _targetFile = File("${docDir.path}/recorder_data.bin");
    _fileBuffer.clear();
    _isDownloading = true;
    // 向设备发送确认响应
    await _txChar?.write([0x01, 0x00]);
  }

  // 处理文件数据块
  void _appendFileData(List<int> dataFrame) {
    if (!_isDownloading) return;
    // 根据协议提取有效数据段(示例:从第4字节开始,长度为第3字节值)
    final dataLength = dataFrame[2];
    final fileChunk = dataFrame.sublist(4, 4 + dataLength);
    _fileBuffer.addAll(fileChunk);
    // 向设备发送数据接收确认
    _txChar?.write([0x02, 0x00]);
  }

  // 完成文件下载
  Future<void> _completeFileDownload() async {
    if (_targetFile != null && _fileBuffer.isNotEmpty) {
      await _targetFile?.writeAsBytes(_fileBuffer);
      print("文件已保存至: ${_targetFile?.path}");
    }
    _isDownloading = false;
    _fileBuffer.clear();
    // 向设备发送下载完成确认
    await _txChar?.write([0x03, 0x00]);
  }

  // 向设备发送文件下载请求
  Future<void> requestFileDownload() async {
    // 替换为设备协议规定的下载请求帧
    await _txChar?.write([0x00, 0x01, 0x00, 0x00]);
  }

  // 断开连接
  Future<void> disconnect() async {
    await _connectedDevice?.disconnect();
    _connectedDevice = null;
    _txChar = null;
    _rxChar = null;
  }
}

权限配置

Android(AndroidManifest.xml)

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

iOS(Info.plist)

<key>NSBluetoothAlwaysUsageDescription</key>
<string>需要蓝牙连接行驶记录仪下载数据</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>需要蓝牙连接行驶记录仪下载数据</string>

关键说明

  • 替换代码中的服务UUID和特征UUID为你的BLE设备实际值
  • 根据设备通信协议调整_parseIncomingData中的帧解析逻辑(帧头位置、类型标识、数据段提取规则等)
  • 命令帧内容需与现有Java实现保持一致,确保设备能识别请求

内容的提问来源于stack exchange,提问作者Abdurrahman yeşilyurt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 02:30:33