Flutter蓝牙通信插件flutter_ttc_ble的使用

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

Flutter蓝牙通信插件flutter_ttc_ble的使用

flutter_ttc_ble

flutter_ttc_ble 是一个用于 Android 和 iOS 的 BLE(Bluetooth Low Energy)的 Flutter 插件。 你可以通过以下链接获取示例代码:flutter_ttc_ble_example

Getting Started

准备
  • Android:版本高于5.0(包含),需要位置权限并打开位置服务,位置权限可借助其他库,如 permission_handler。
  • iOS:版本高于10.0,在Info.plist中增加Privacy - Bluetooth Always Usage Description。
扫描设备
  • 初始化插件(使用0.0.5新增的 bleProxy 可以不用显式初始化)
FlutterTtcBle.init();
  • 开始扫描
//开启扫描
FlutterTtcBle.startLeScan((device) {
  //处理数据
});
  • 停止扫描
//停止扫描
FlutterTtcBle.stopLeScan();
连接设备 / 断开连接
  • 连接设备
//连接设备
FlutterTtcBle.connect(deviceId: device.deviceId);
  • 断开连接
//断开连接
FlutterTtcBle.disconnect(device.deviceId);
发送数据

与蓝牙设备通信的 UUID

const UUID_SERVICE = '00001000-0000-1000-8000-00805f9b34fb';
const UUID_WRITE = '00001001-0000-1000-8000-00805f9b34fb';
const UUID_NOTIFY = '00001002-0000-1000-8000-00805f9b34fb';

FlutterTtcBle.writeCharacteristic(
    deviceId: deviceId,
    serviceUuid: UUID_SERVICE,
    characteristicUuid: UUID_WRITE,
    value: data,
    writeType: CharacteristicWriteType.writeNoResponse);
接收数据
  • 通知事件中获取数据
BleCallback bleCallback = (message) {
  if (message is Map<dynamic, dynamic>) {
    if (message.containsKey('event')) {
      switch (message['event']) {
        case BLEEvent.CONNECTEDed: //与设备建立连接
          //开启数据通知,这样才能实时接收设备端的数据
          FlutterTtcBle.setCharacteristicNotification(
            deviceId: message['deviceId'],
            serviceUuid: UUID_SERVICE,
            characteristicUuid: UUID_NOTIFY,
            enable: true);
          break;

        case BLEEvent.DATA_AVAILABLE: //收到数据
          Uint8List data = (message['value'] as Uint8List);
          break;
      }
    }
  }
};

从0.0.5开始,可以使用 bleProxy 和 BleCallback2,无需再通过判断运行时的动态消息类型来区分蓝牙事件

class _CommPageState extends State<CommPage> with BleCallback2 {

  [@override](/user/override)
  void initState() {
    super.initState();
    print('CommPage initState()');
    _deviceId = widget.device.deviceId;
    //连接设备
    bleProxy.connect(deviceId: _deviceId);

    //监听蓝牙异步事件通知
    bleProxy.addBleCallback(this);
  }

  [@override](/user/override)
  void dispose() {
    print('CommPage -> dispose()');
    //取消监听蓝牙异步事件通知
    bleProxy.removeBleCallback(this);
    bleProxy.disconnect(deviceId: _deviceId); //断开连接
    super.dispose();
  }

  [@override](/user/override)
  void onDataReceived(String deviceId, String serviceUuid, String characteristicUuid, Uint8List data) {
    //收到数据
    String utf8String = "";
    try {
      utf8String = utf8.decode(data);
    } on Exception catch (e) {
      print(e);
    }

    String hexString = data.toHex();

    print('<- utf8String=$utf8String, hexString=$hexString');
  }
  
  //可以按需实现 BleCallback2 的其它方法
  ...
}

0.0.5版本新增一个内置的扫描页面,用于编写测试APP比较方便

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ScanScreen(
        title: 'TTC Flutter BLE Demo',
        onDeviceClick: (BuildContext context, BLEDevice device) {
          Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => CommPage(device: device)));
        },
      ),
    );
  }
}

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_ttc_ble/flutter_ttc_ble.dart';
import 'package:flutter_ttc_ble/scan_screen.dart';

import 'communication.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ScanScreen(
        title: 'TTC Flutter BLE Demo',
        onDeviceClick: (BuildContext context, BLEDevice device) {
          Navigator.push(
              context,
              MaterialPageRoute(
                  builder: (context) => CommPage(device: device)));
        },
        onConnectDevicesClick: null/*(context, devices) {

        }*/,
      ),
    );
  }
}

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

1 回复

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


当然,以下是一个使用 flutter_ttc_ble 插件进行蓝牙通信的 Flutter 代码示例。这个示例将展示如何扫描蓝牙设备、连接到设备以及读取和写入特征值。

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

dependencies:
  flutter:
    sdk: flutter
  flutter_ttc_ble: ^最新版本号 # 替换为最新版本号

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

示例代码

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

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

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

class _MyAppState extends State<MyApp> {
  FlutterTtcBle _ble = FlutterTtcBle();
  List<BluetoothDevice> _devices = [];
  BluetoothDevice _connectedDevice;
  BluetoothCharacteristic _characteristic;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter TTC BLE Demo'),
        ),
        body: Column(
          children: [
            Expanded(
              child: ListView.builder(
                itemCount: _devices.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(_devices[index].name),
                    onTap: () async {
                      await _connectToDevice(_devices[index]);
                    },
                  );
                },
              ),
            ),
            ElevatedButton(
              onPressed: _scanDevices,
              child: Text('Scan Devices'),
            ),
            if (_connectedDevice != null)
              Column(
                children: [
                  Text('Connected Device: ${_connectedDevice.name}'),
                  ElevatedButton(
                    onPressed: _discoverServices,
                    child: Text('Discover Services'),
                  ),
                  if (_characteristic != null)
                    Column(
                      children: [
                        ElevatedButton(
                          onPressed: () async {
                            await _readCharacteristic(_characteristic);
                          },
                          child: Text('Read Characteristic'),
                        ),
                        ElevatedButton(
                          onPressed: () async {
                            await _writeCharacteristic(_characteristic, 'Hello BLE');
                          },
                          child: Text('Write Characteristic'),
                        ),
                      ],
                    ),
                ],
              ),
          ],
        ),
      ),
    );
  }

  Future<void> _scanDevices() async {
    setState(() {
      _devices = [];
    });
    var result = await _ble.scanForDevices(withServices: []);
    setState(() {
      _devices = result;
    });
  }

  Future<void> _connectToDevice(BluetoothDevice device) async {
    var connectionResult = await _ble.connectToDevice(device.id);
    if (connectionResult) {
      setState(() {
        _connectedDevice = device;
      });
    }
  }

  Future<void> _discoverServices() async {
    if (_connectedDevice != null) {
      var services = await _ble.discoverServices(_connectedDevice.id);
      // 在这里处理服务,找到需要的特征值
      // 假设我们找到了一个特征值并保存到 _characteristic
      // 这里只是一个示例,你需要根据实际需求处理服务和特征值
      _characteristic = services[0].characteristics[0];
    }
  }

  Future<void> _readCharacteristic(BluetoothCharacteristic characteristic) async {
    var value = await _ble.readCharacteristic(characteristic.uuid);
    print('Characteristic Value: $value');
  }

  Future<void> _writeCharacteristic(
      BluetoothCharacteristic characteristic, String value) async {
    var data = Uint8List.fromList(value.codeUnits);
    await _ble.writeCharacteristic(characteristic.uuid, data);
  }
}

注意事项

  1. 权限处理:在实际应用中,你需要处理 Android 和 iOS 的蓝牙权限。这通常需要在 AndroidManifest.xmlInfo.plist 中添加相应的权限声明。

  2. 错误处理:示例代码中没有包含错误处理逻辑。在实际应用中,你应该添加适当的错误处理,例如处理蓝牙扫描失败、连接失败等情况。

  3. 特征值和服务处理:示例代码中假设你已经知道要连接的特征值和服务,但在实际应用中,你可能需要遍历服务和特征值,找到你需要的那个。

  4. 插件版本:确保你使用的是 flutter_ttc_ble 的最新版本,因为插件的 API 可能会随着版本更新而变化。

  5. 蓝牙状态:在实际应用中,你可能还需要检查设备的蓝牙状态,并在必要时提示用户开启蓝牙。

这个示例提供了一个基本的框架,你可以根据实际需求进行扩展和修改。

回到顶部