Flutter蓝牙BLE开发完全指南(内含高级功能扩展)

发布于:2025-07-30 ⋅ 阅读:(20) ⋅ 点赞:(0)

Flutter蓝牙BLE开发完全指南

我将为您提供一个完整的Flutter蓝牙BLE实现方案,包含UI设计、权限处理、设备扫描、连接通信等完整功能。

完整实现方案

1. 添加依赖与权限配置

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter
  flutter_blue_plus: ^1.10.0
  permission_handler: ^10.4.0
  provider: ^6.0.5
  animated_text_kit: ^4.2.2
  percent_indicator: ^4.2.3

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"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>

Info.plist (iOS)

<key>NSBluetoothAlwaysUsageDescription</key>
<string>需要蓝牙权限来连接设备</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>需要蓝牙权限来连接设备</string>
<key>UIBackgroundModes</key>
<array>
  <string>bluetooth-central</string>
  <string>bluetooth-peripheral</string>
</array>

2. 蓝牙状态管理类

import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:provider/provider.dart';

class BluetoothProvider extends ChangeNotifier {
   
   
  List<ScanResult> scannedDevices = [];
  BluetoothDevice? connectedDevice;
  List<BluetoothService> services = [];
  BluetoothCharacteristic? targetCharacteristic;
  bool isScanning = false;
  bool isConnecting = false;
  bool isDiscovering = false;
  String connectionStatus = "未连接";
  List<List<int>> receivedData = [];

  Future<void> startScan() async {
   
   
    if (isScanning) return;
    
    scannedDevices.clear();
    isScanning = true;
    notifyListeners();
    
    try {
   
   
      await FlutterBluePlus.startScan(
        timeout: const Duration(seconds: 15),
        androidUsesFineLocation: true,
      );
      
      FlutterBluePlus.scanResults.listen((results) {
   
   
        scannedDevices = results;
        notifyListeners();
      });
    } catch (e) {
   
   
      print("扫描错误: $e");
      isScanning = false;
      notifyListeners();
    }
  }

  Future<void> stopScan() async {
   
   
    if (!isScanning) return;
    await FlutterBluePlus.stopScan();
    isScanning = false;
    notifyListeners();
  }

  Future<void> connectToDevice(BluetoothDevice device) async {
   
   
    if (isConnecting) return;
    
    isConnecting = true;
    connectionStatus = "连接中...";
    notifyListeners();
    
    try {
   
   
      await device.connect(autoConnect: false);
      connectedDevice = device;
      connectionStatus = "已连接";
      
      // 监听连接状态
      device.connectionState.listen((state) {
   
   
        if (state == BluetoothConnectionState.disconnected) {
   
   
          connectedDevice = null;
          services.clear();
          targetCharacteristic = null;
          connectionStatus = "已断开";
          notifyListeners();
        }
      });
      
      // 发现服务
      isDiscovering = true;
      notifyListeners();
      services = await device.discoverServices();
      isDiscovering = false;
      notifyListeners();
      
    } catch (e) {
   
   
      print("连接错误: $e");
      connectionStatus = "连接失败";
      isConnecting = false;
      notifyListeners();
    }
    
    isConnecting = false;
    notifyListeners();
  }

  Future<void> disconnectDevice() async {
   
   
    if (connectedDevice == null) return;
    
    try {
   
   
      await connectedDevice!.disconnect();
    } catch (e) {
   
   
      print("断开连接错误: $e");
    } finally {
   
   
      connectedDevice = null;
      services.clear();
      targetCharacteristic = null;
      connectionStatus = "已断开";
      notifyListeners();
    }
  }

  Future<void> setCharacteristic(BluetoothCharacteristic characteristic) async {
   
   
    targetCharacteristic = characteristic;
    
    // 设置通知监听
    await characteristic.setNotifyValue(true);
    characteristic.value.listen((value) {
   
   
      receivedData.add(value);
      notifyListeners();
    });
    
    notifyListeners();
  }

  Future<void> writeData(List<int> data) async {
   
   
    if (targetCharacteristic == null) return;
    
    try {
   
   
      await targetCharacteristic!.write(data);
    } catch (e) {
   
   
      print("写入错误: $e");
    }
  }
}

3. 主界面实现

import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:provider/provider.dart';
import 'bluetooth_provider.dart';

void main() {
   
   
  runApp(
    ChangeNotifierProvider(
      create: (context) => BluetoothProvider(),
      child: const MyApp(),
    ),
  );
}

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

  
  Widget build(BuildContext context) {
   
   
    return MaterialApp(
      title: 'Flutter蓝牙BLE',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        scaffoldBackgroundColor: Colors.grey[100],
        appBarTheme: const AppBarTheme(
          backgroundColor: Colors.deepPurple,
          foregroundColor: Colors.white,
        ),
      ),
      home: const BluetoothHomePage(),
    );
  }
}

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

  
  State<BluetoothHomePage> createState() => _BluetoothHomePageState();
}

class _BluetoothHomePageState extends State<BluetoothHomePage> {
   
   
  
  void initState() {
   
   
    super.initState();
    _checkPermissions();
  }

  Future<void> _checkPermissions() async {
   
   
    // 检查并请求权限
    final locationStatus = await Permission.location.request();
    final bluetoothStatus = await Permission.bluetooth.request();
    
    if (locationStatus.isDenied || bluetoothStatus.isDenied) {
   
   
      showDialog(
        context: context,
        builder: (context) => AlertDialog(
          title: const Text('权限不足'),
          content: const Text('需要位置和蓝牙权限才能扫描设备'),
          actions: [
            TextButton(
              onPressed: () => Navigator.pop(context),
              child: const Text('确定'),
            ),
          ],
        ),
      );
    }
  }

  
  Widget build(BuildContext context) {
   
   
    final bluetoothProvider = Provider.of<BluetoothProvider>(context);
    
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter蓝牙BLE'),
        actions: [
          IconButton(
            icon: const Icon(Icons.bluetooth),
            onPressed: () {
   
   
              if (bluetoothProvider.connectedDevice != null) {
   
   
                bluetoothProvider.disconnectDevice();
              } else {
   
   
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => const DeviceScanPage(),
                  ),
                );
              }
            },
          ),
        ],
      ),
      body: _buildBody(bluetoothProvider),
    );
  }

  Widget _buildBody(BluetoothProvider provider) {
   
   
    if (provider.connectedDevice == null) {
   
   
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.bluetooth_disabled, size: 100, color: Colors.grey),
            const SizedBox(height: 20),
            const Text(
              '未连接设备',
              style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 10),
            ElevatedButton(
              onPressed: () {
   
   
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => const DeviceScanPage(),
                  ),
                );
              },
              child: const Text('扫描设备'),
            ),
          ],
        ),
      );
    }
    
    return DefaultTabController(
      length: 3,
      child: Column(
        children: [
          _buildDeviceHeader(provider),
          const TabBar(
            tabs: [
              Tab(icon: Icon(Icons.devices), text: '设备信息'),
              Tab(icon: Icon(Icons.settings), text: '服务'),
              Tab(icon: Icon(Icons.message), text: '通信'),
            ],
          ),
          Expanded(
            child: TabBarView(
              children: [
                _buildDeviceInfo(provider),
                _buildServices(provider),
                _buildCommunication(provider),
              ],
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildDeviceHeader(BluetoothProvider provider) {
   
   
    return Container(
      padding: const EdgeInsets.all(16),
      color: Colors.deepPurple[50],
      child: Row(
        children: [
          const Icon(Icons.bluetooth_connected, color: Colors.deepPurple, size: 36),
          const SizedBox(width: 16),
          Expanded(
            child: Column(
              crossA

网站公告

今日签到

点亮在社区的每一天
去签到