Flutter蓝牙的使用

import 'dart:async';
import 'dart:io';

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

logDog(String log) {
  debugPrint('BluetoothClient->$log');
}

///低功耗蓝牙插件 BLE
///不需要处理api返回的流中的onError和onDone方法,除了FlutterBluePlus.scanResults的onError
///对于ios,每一个相关api的调用都会显示系统的蓝牙弹窗
///可以通过remoteId直接连接,而不需要扫描
///自动重连和mtu不可同时设置
class BluetoothClient {
  ///监听log流
  void setupLog() {
    // if your terminal doesn't support color you'll see annoying logs like `\x1B[1;35m`
    FlutterBluePlus.setLogLevel(LogLevel.verbose, color: true);
    FlutterBluePlus.logs.listen((String s) {
      logDog(s);
    });
  }

  ///*****************************************************************************************蓝牙支持***/
  ///是否支持蓝牙
  Future<bool> isSupported() async {
    bool bl = await FlutterBluePlus.isSupported;
    logDog('是否支持蓝牙:$bl');
    return bl;
  }

  ///*****************************************************************************************蓝牙适配器开关***/
  ///打开蓝牙
  ///只有android支持,ios由用户自己控制
  Future<bool> turnOn() async {
    if (Platform.isAndroid) {
      await FlutterBluePlus.turnOn();
    }
    return true;
  }

  ///监听蓝牙打开状态
  ///对于ios初始化状态是 BluetoothAdapterState.unknown
  ///如果没有权限状态是 BluetoothAdapterState.unauthorized
  StreamSubscription<BluetoothAdapterState> adapterStateListener() {
    logDog('设置蓝牙打开状态监听');
    return FlutterBluePlus.adapterState.listen((BluetoothAdapterState state) {
      logDog('蓝牙打开状态变化:$state');
    });
  }

  ///取消监听蓝牙打开状态
  void cancelAdapterState(
      StreamSubscription<BluetoothAdapterState> subscription) async {
    logDog('取消蓝牙打开状态监听');
    await subscription.cancel();
  }

  ///当前的蓝牙是否是打开的
  Future<bool> isBluetoothOn() async {
    bool bl = FlutterBluePlus.adapterStateNow == BluetoothAdapterState.on;
    logDog('当前蓝牙是否打开状态:$bl');
    return bl;
  }

  ///阻塞线程等待蓝牙打开
  Future<bool> waitForBluetoothOn() async {
    logDog('阻塞线程等待蓝牙打开');
    await FlutterBluePlus.adapterState.where((val) => val == BluetoothAdapterState.on).first;
    return true;
  }

  ///*****************************************************************************************蓝牙设备搜索***/
  ///如果蓝牙没找到--------------
  ///如果添加扫描过滤器可以减少主线程的使用

  ///第一种:清除两次扫描中间的结果
  StreamSubscription<List<ScanResult>> onScanResultsListener(Function(List<ScanResult>) resultBack) {
    logDog('设置扫描结果监听 onScanResults');
    return FlutterBluePlus.onScanResults.listen((List<ScanResult> event) {
      logDog('收到扫描结果 onScanResults');
      resultBack(event);
      for (var element in event) {
        logDog('扫描到:${element.device.platformName} ${element.device.remoteId}');
      }
      if (event.isNotEmpty) {
        ScanResult r = event.last; //最近找到的设备
      }
    }, onError: (e) => logDog('蓝牙扫描结果异常:$e'));
  }

  ///第二种:获取当前扫描结果或上一次扫描结果
  StreamSubscription<List<ScanResult>> scanResultsListener() {
    logDog('设置扫描结果监听 scanResults');
    return FlutterBluePlus.scanResults.listen((List<ScanResult> event) {
      logDog('收到扫描结果 scanResults');
      for (var element in event) {
        logDog('扫描到:${element.device.platformName} ${element.device.remoteId}');
      }
    }, onError: (e) => logDog('蓝牙扫描结果异常:$e'));
  }

  ///自动取消监听蓝牙设备扫描结果
  void autoCancelScanResults(
      StreamSubscription<List<ScanResult>> subscription) {
    logDog('自动取消监听蓝牙设备扫描结果');
    FlutterBluePlus.cancelWhenScanComplete(subscription);
  }

  ///开始扫描
  ///需要蓝牙已打开,给予了权限,开启了定位服务
  Future startScan() async {
    logDog('打开蓝牙扫描');
    await FlutterBluePlus.startScan(
        androidUsesFineLocation: true,
        // withNames: ['MG','IPC'],
        withKeywords: ['MG','IPC','MC'],
        timeout: const Duration(seconds: 30) //60s后停止扫描
        );
  }

  ///关闭扫描
  Future stopScan() async {
    logDog('关闭蓝牙扫描');
    await FlutterBluePlus.stopScan();
  }

  ///设置扫描状态监听
  StreamSubscription<bool> scanningListener(Function(bool doesScanning) doesScanning){
    logDog('设置扫描状态监听');
    return FlutterBluePlus.isScanning.listen((event) {
      logDog('扫描状态:$event');
      doesScanning(event);
    });
  }

  ///是否正在扫描
  bool isScanning() {
    bool bl = FlutterBluePlus.isScanningNow;
    logDog('是否正在扫描设备:$bl');
    return bl;
  }

  ///*****************************************************************************************蓝牙设备连接***/
  ///监听设备连接状态
  StreamSubscription<BluetoothConnectionState> connectionStateListener(
      BluetoothDevice device,Function() isConnected) {
    logDog('开始监听设备连接状态');
    return device.connectionState.listen((BluetoothConnectionState state) {
      logDog('设备连接状态:${device.platformName} : $state');
      isConnected.call();
      if (state == BluetoothConnectionState.disconnected) {
        //1.这里面一般做重连 2.必须重新探索服务
        logDog(
            '设备断开原因:${device.disconnectReason?.code} ${device.disconnectReason?.description}');
      }
    });
  }

  ///自动取消监听设备连接状态
  void autoCancelConnectionState(BluetoothDevice device,
      StreamSubscription<BluetoothConnectionState> subscription) async {
    logDog('自动取消监听设备连接状态');
    device.cancelWhenDisconnected(subscription, delayed: true, next: true);
  }

  ///主动取消监听设备连接状态
  void cancelConnectionState(
      StreamSubscription<BluetoothConnectionState> subscription) async {
    logDog('主动取消监听设备连接状态');
    await subscription.cancel();
  }

  ///连接设备
  void connect(BluetoothDevice device) async {
    logDog('开始设备连接');
    await device.connect();
  }

  ///断开连接设备
  void disconnect(BluetoothDevice device) async {
    logDog('断开设备连接');
    await device.disconnect();
  }

  ///获取已经连接成功的设备
  List<BluetoothDevice> connectedDevices() {
    logDog('获取已经连接成功的设备');
    List<BluetoothDevice> devs = FlutterBluePlus.connectedDevices;
    for (var d in devs) {
      logDog('获取已经连接成功的设备条目:${d.remoteId}');
    }
    return devs;
  }

  ///*****************************************************************************************mtu***/
  ///设置mtu,android一般是512,但是ios是自动协商的
  void setMtu(BluetoothDevice device) async {
    logDog('设置mtu');
    final subscription = device.mtu.listen((int mtu) {
      //ios初始值是23,但是会立即提高这个值
      logDog('mtu值:$mtu');
    });
    device.cancelWhenDisconnected(subscription);
    if (Platform.isAndroid) {
      await device.requestMtu(512);
    }
  }

  ///*****************************************************************************************探索服务***/
  ///每一次重连都需要探索服务
  void discoverServices(BluetoothDevice device) async {
    logDog('探索服务');
    List<BluetoothService> services = await device.discoverServices();
    services.forEach((service) {
      logDog('探索服务条目:${service.remoteId}');
    });
  }

  ///读取 Characteristics
  void readCharacteristics(BluetoothService service) async {
    logDog('读取Characteristics');
    var characteristics = service.characteristics;
    for (BluetoothCharacteristic c in characteristics) {
      if (c.properties.read) {
        List<int> value = await c.read();
        logDog('读取Characteristics 条目 $value');
      }
    }
  }

  ///写入 Characteristics
  ///allowLongWrite 忽略mtu进行长数据写入,设备必须支持 long writ ble协议
  void writeCharacteristics(BluetoothCharacteristic c, List<int> value,
      {bool allowLongWrite = false}) async {
    logDog('写入Characteristics');
    await c.write(value, allowLongWrite: allowLongWrite);
  }

  ///监听 Characteristics 通过 onValueReceived
  void onValueReceivedListener(
      BluetoothDevice device, BluetoothCharacteristic c) {
    logDog('监听 Characteristics 通过 onValueReceived');
    final subscription = c.onValueReceived.listen((value) {
      //此回调收到数据的前提 1.c.read() 调用 2.c.setNotifyValue(true) 调用
      logDog('onValueReceived收到:$value');
    });
    device.cancelWhenDisconnected(subscription);
  }

  ///监听 Characteristics 通过 lastValueStream ,onValueReceived 的替代方案
  void lastValueStreamListener(
      BluetoothDevice device, BluetoothCharacteristic c) {
    logDog('监听 Characteristics 通过 lastValueStream');
    final subscription = c.lastValueStream.listen((value) {
      //此回调收到数据的前提 1.c.read() 调用 2.c.setNotifyValue(true) 调用 3.c.write() 调用
      logDog('lastValueStream 收到:$value');
    });
    device.cancelWhenDisconnected(subscription);
  }

  ///允许蓝牙设备主动发起通知
  void setNotifyValue(BluetoothCharacteristic c, bool notify) async {
    logDog('是否允许蓝牙设备主动发起通知:$notify');
    await c.setNotifyValue(notify);
  }

  ///Characteristics 服务变化监听
  void onServicesReset(BluetoothDevice device) {
    logDog('Characteristics 服务变化监听');
    device.onServicesReset.listen((event) async {
      logDog('服务变化 onServicesReset');
      //必须重新调用探索服务
      await device.discoverServices();
    });
  }
}

 

posted @ 2025-05-26 09:44  呢哇哦比较  阅读(367)  评论(0)    收藏  举报