Flutter Web蓝牙通信插件flutter_web_bluetooth的使用

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

Flutter Web蓝牙通信插件flutter_web_bluetooth的使用

Introduction

flutter_web_bluetooth 是一个Dart插件,用于支持Web Bluetooth API。它不仅限于Flutter项目,还可以与AngularDart等其他Dart项目兼容,并且能够很好地融入Dart原生项目中,以实现跨平台应用的Web端支持。

该库在非浏览器环境中(例如命令行工具或移动设备)也能编译,但其功能仅限于浏览器环境。有关概念验证的示例代码,请访问jeroen1602.github.io/flutter_web_bluetooth/

Limited Support

Web蓝牙API仍处于草案阶段,因此并非所有浏览器都完全支持它。请查阅canIUse.com了解各浏览器的支持情况。某些浏览器版本可能不提供API的所有特性。

Requirements

  • 浏览器和设备支持:确保你使用的浏览器和设备支持Web蓝牙API。对于Linux上的Chrome,可能需要启用特定标志位。
  • 安全上下文:必须通过HTTPS或本地主机访问,以确保API可用性。

Usage

检查浏览器是否支持Web蓝牙API

// 检查当前用户代理是否支持蓝牙API
final supported = FlutterWebBluetooth.instance.isBluetoothApiSupported;

检查蓝牙适配器是否可用

// 获取表示蓝牙适配器是否可用的流
final available = FlutterWebBluetooth.instance.isAvailable;

请求连接设备

在请求设备之前,你需要指定想要连接的服务。如果不指定具体服务,则无法发现这些服务!

// 定义要通信的服务UUID列表
final requestOptions = RequestOptionsBuilder.acceptAllDevices(optionalServices: [
  BluetoothDefaultServiceUUIDS.deviceInformation.uuid // 示例服务UUID
]);

try {
  final device = await FlutterWebBluetooth.instance.requestDevice(requestOptions);
} on UserCancelledDialogError {
  // 用户取消了对话框
} on DeviceNotFoundError {
  // 根据定义的选项,没有找到范围内的设备
}

发现服务并读取特征值

一旦获取到设备实例,你可以遍历它的服务,并查找感兴趣的特征值。

await device.connect();
final services = await device.discoverServices();
final service = services.firstWhere((service) => service.uuid == BluetoothDefaultServiceUUIDS.deviceInformation.uuid);
// 现在获取特征值
final characteristic = await service.getCharacteristic(BluetoothDefaultCharacteristicUUIDS.manufacturerNameString.uuid);
final value = characteristic.readValue(); // 返回的是ByteData对象
device.disconnect();

访问已配对设备

如果启用了“实验性Web平台特性”标志,可以通过监听设备流来获取用户已配对并授权的设备集合。

// 获取所有已配对设备的流
FlutterWebBluetooth.instance.devices.listen((devices) {
  // 处理已配对设备
});

自定义日志记录器

你可以覆盖库默认的日志记录器,以便自定义日志输出位置。

import 'package:flutter_web_bluetooth/web_bluetooth_logger.dart';

setWebBluetoothLogger(Logger("my logger"));

示例Demo

下面是一个简单的Flutter Web应用程序示例,展示了如何使用flutter_web_bluetooth插件:

import "dart:async";
import "package:flutter/material.dart";
import "package:flutter_web_bluetooth/flutter_web_bluetooth.dart";

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: StreamBuilder<bool>(
        stream: FlutterWebBluetooth.instance.isAvailable,
        initialData: false,
        builder: (context, snapshot) {
          final available = snapshot.data ?? false;
          return Scaffold(
            appBar: AppBar(title: Text('Flutter Web Bluetooth Example')),
            body: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: <Widget>[
                  Text(
                    'Bluetooth is ${available ? 'available' : 'not available'}',
                  ),
                  ElevatedButton(
                    onPressed: () async {
                      if (available) {
                        try {
                          final device = await FlutterWebBluetooth.instance.requestDevice(
                            RequestOptionsBuilder.acceptAllDevices(optionalServices: ['0000180a-0000-1000-8000-00805f9b34fb']), // 设备信息服务UUID
                          );
                          print('Connected to device: ${device.name}');
                        } catch (e) {
                          print('Failed to connect: $e');
                        }
                      }
                    },
                    child: Text('Connect to a Bluetooth Device'),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

此示例创建了一个简单的UI,用于检查蓝牙是否可用,并提供了一个按钮来尝试连接到附近的蓝牙设备。当点击按钮时,它会弹出一个选择设备的对话框,用户可以选择要连接的设备。如果成功连接,将在控制台打印出设备名称。


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

1 回复

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


当然,以下是一个使用Flutter Web蓝牙通信插件flutter_web_bluetooth的示例代码。这个示例展示了如何扫描附近的蓝牙设备,连接到某个设备,并读取其服务、特征和值。

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

dependencies:
  flutter:
    sdk: flutter
  flutter_web_bluetooth: ^x.y.z  # 请使用最新版本号

然后,运行flutter pub get来安装依赖。

接下来,编写Flutter代码:

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: BluetoothApp(),
    );
  }
}

class BluetoothApp extends StatefulWidget {
  @override
  _BluetoothAppState createState() => _BluetoothAppState();
}

class _BluetoothAppState extends State<BluetoothApp> {
  List<BluetoothDevice> devices = [];
  BluetoothRemoteGATTServer? server;
  BluetoothRemoteGATTService? service;
  BluetoothRemoteGATTCharacteristic? characteristic;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Web Bluetooth Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            ElevatedButton(
              onPressed: scanDevices,
              child: Text('Scan Devices'),
            ),
            SizedBox(height: 20),
            if (devices.isNotEmpty)
              ListView.builder(
                itemCount: devices.length,
                itemBuilder: (context, index) {
                  return ListTile(
                    title: Text(devices[index].name ?? 'Unknown Device'),
                    subtitle: Text(devices[index].id),
                    trailing: ElevatedButton(
                      onPressed: () => connectToDevice(devices[index]),
                      child: Text('Connect'),
                    ),
                  );
                },
              ),
            SizedBox(height: 20),
            if (server != null)
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Connected to: ${server!.device.name ?? 'Unknown Device'}'),
                  ElevatedButton(
                    onPressed: listServices,
                    child: Text('List Services'),
                  ),
                  if (service != null)
                    Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Text('Selected Service: ${service!.uuid}'),
                        ElevatedButton(
                          onPressed: listCharacteristics,
                          child: Text('List Characteristics'),
                        ),
                        if (characteristic != null)
                          Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text('Selected Characteristic: ${characteristic!.uuid}'),
                              ElevatedButton(
                                onPressed: readCharacteristicValue,
                                child: Text('Read Value'),
                              ),
                            ],
                          ),
                      ],
                    ),
                ],
              ),
          ],
        ),
      ),
    );
  }

  Future<void> scanDevices() async {
    setState(() {
      devices = [];
    });
    try {
      var requestDeviceOptions = BluetoothRequestDeviceOptions(
        filters: [
          BluetoothDeviceFilter(
            namePrefix: '', // 设置为空字符串以扫描所有设备
          ),
        ],
        optionalServices: [],
      );
      var devices = await navigator.bluetooth.requestDevice(requestDeviceOptions);
      setState(() {
        this.devices = devices;
      });
    } catch (e) {
      print('Error scanning devices: $e');
    }
  }

  Future<void> connectToDevice(BluetoothDevice device) async {
    try {
      server = await device.gatt.connect();
      print('Connected to ${device.name}');
    } catch (e) {
      print('Error connecting to device: $e');
    }
  }

  Future<void> listServices() async {
    if (server == null) return;
    try {
      var services = await server!.primaryServices();
      print('Services: ${services.map((s) => s.uuid).join(', ')}');
      // 假设选择第一个服务进行后续操作
      setState(() {
        service = services.firstOrNull;
      });
    } catch (e) {
      print('Error listing services: $e');
    }
  }

  Future<void> listCharacteristics() async {
    if (service == null) return;
    try {
      var characteristics = await service!.characteristics();
      print('Characteristics: ${characteristics.map((c) => c.uuid).join(', ')}');
      // 假设选择第一个特征进行后续操作
      setState(() {
        characteristic = characteristics.firstOrNull;
      });
    } catch (e) {
      print('Error listing characteristics: $e');
    }
  }

  Future<void> readCharacteristicValue() async {
    if (characteristic == null) return;
    try {
      var value = await characteristic!.readValue();
      print('Characteristic value: ${new TextDecoder().decode(value)}');
    } catch (e) {
      print('Error reading characteristic value: $e');
    }
  }
}

注意事项

  1. 代码中使用了navigator.bluetooth,这是flutter_web_bluetooth插件提供的API。
  2. 在Web平台上,蓝牙权限和可用性可能受到浏览器的限制,因此请确保在支持Web蓝牙的浏览器(如Chrome)上运行此代码。
  3. 由于隐私和安全原因,浏览器可能需要用户明确授予访问蓝牙设备的权限。
  4. 代码中的错误处理仅用于演示,在实际应用中你可能需要更详细的错误处理和用户反馈。

这个示例展示了如何使用flutter_web_bluetooth插件进行蓝牙通信的基本流程,包括扫描设备、连接设备、读取服务和特征值。根据具体需求,你可以进一步扩展这些功能。

回到顶部