Flutter蓝牙设备标识插件bluetooth_identifiers的使用

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

Flutter蓝牙设备标识插件bluetooth_identifiers的使用

插件介绍

bluetooth_identifiers 是一个Flutter包,它将一些来自Bluetooth.com的“分配号码”进行了编码。通过这个插件,开发者可以更方便地获取蓝牙设备的相关标识信息,如UUID服务标识符和公司标识符。

Pub License Code size Open Issues

更多信息请参考 Bluetooth.com

使用方法

直接获取

可以直接通过整数或十六进制字面量来获取数据:

final UUIDAllocation uuidServiceId = BluetoothIdentifiers.uuidServiceIdentifiers[64753];
print(uuidServiceId); // 输出:UUIDAllocation(type: '16-bit UUID for Members', registrant: 'Google LLC')

final String companyIdentifier = BluetoothIdentifiers.companyIdentifiers[0x00E0];
print(companyIdentifier); // 输出:'Google'

键计算

从十六进制字符串计算键

final int key = int.parse('0x00E0', radix: 16);

从字节列表计算键

final int start = 0;
final Uint8List bytes = Uint8List.fromList([0, 224]);
final int key = bytes.buffer.asByteData().getUint16(start);

方便的扩展方法

通过十六进制字符串获取元素

final UUIDAllocation uuidServiceId = BluetoothIdentifiers.uuidServiceIdentifiers.elementForHex('0x00E0');
print(uuidServiceId); // 输出:UUIDAllocation(type: '16-bit UUID for Members', registrant: 'Google LLC')

通过字节列表获取元素

final Uint8List bytes = Uint8List.fromList([0, 224]);
final String companyIdentifier = BluetoothIdentifiers.companyIdentifiers.elementForByteArray(bytes);
print(companyIdentifier); // 输出:'Google'

获取键和元素

final MapEntry<int, UUIDAllocation> uuidServiceIDEntry = BluetoothIdentifiers.uuidServiceIdentifiers.entryForHex('0xFCF1');
print(uuidServiceIDEntry.key); // 输出:64753
print(uuidServiceIDEntry.value); // 输出:UUIDAllocation(type: '16-bit UUID for Members', registrant: 'Google LLC')

final Uint8List bytes = Uint8List.fromList([0, 224]);
final MapEntry<int, String> companyIdentifierEntry = BluetoothIdentifiers.companyIdentifiers.entryForByteArray(bytes);
print(companyIdentifierEntry.key); // 输出:224
print(companyIdentifierEntry.value); // 输出:'Google'

示例代码

下面是一个完整的示例代码,展示了如何在Flutter应用中使用bluetooth_identifiers插件:

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        colorScheme: const ColorScheme.light(
          primary: Colors.white,
          onPrimary: Colors.grey,
        ),
        inputDecorationTheme: const InputDecorationTheme(
          focusColor: Colors.grey,
          prefixIconColor: Colors.grey,
        ),
      ),
      initialRoute: InitialPage.routeName,
      routes: const {
        InitialPage.routeName: InitialPage.builder,
        CompanyIdentifiersPage.routeName: CompanyIdentifiersPage.builder,
        UUIDServiceIdentifiersPage.routeName: UUIDServiceIdentifiersPage.builder,
      },
    );
  }
}

class InitialPage extends StatelessWidget {
  const InitialPage._({Key? key}) : super(key: key);

  factory InitialPage.builder(BuildContext context) {
    return const InitialPage._();
  }

  static const String routeName = '/';

  static final Map<String, Function(NavigatorState)> _routes = {
    'Company Identifiers Search': (NavigatorState navigator) {
      navigator.pushNamed(CompanyIdentifiersPage.routeName);
    },
    'UUID Service Identifiers Search': (NavigatorState navigator) {
      navigator.pushNamed(UUIDServiceIdentifiersPage.routeName);
    },
  };

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Bluetooth Identifier Example App'),
      ),
      body: ListView.builder(
        itemCount: _routes.length,
        itemBuilder: (_, i) {
          final String key = _routes.keys.elementAt(i);
          return ListTile(
            title: Text(key),
            onTap: () => _routes[key]!(Navigator.of(context)),
          );
        },
      ),
    );
  }
}

class UUIDServiceIdentifiersPage extends StatelessWidget {
  const UUIDServiceIdentifiersPage._({Key? key}) : super(key: key);

  factory UUIDServiceIdentifiersPage.builder(BuildContext context) {
    return const UUIDServiceIdentifiersPage._();
  }

  static const String routeName = '/uuid_service_identifiers';
  static const _searchResultNotFound = 'SEARCH RESULT NOT FOUND';
  static const _itemNotFound = 'NOT FOUND';

  @override
  Widget build(BuildContext context) {
    return DigestSearchPage(
      itemBuilder: (_, i) {
        final UUIDAllocation? id = BluetoothIdentifiers.uuidServiceIdentifiers[i];

        return FixedSizeTile(
          tileColor: Colors.blueGrey,
          leading: '0x${i.toRadixString(16).padLeft(4, '0')}',
          leadingStyle: const TextStyle(color: Colors.white),
          trailing: MapEntry(
            id?.type ?? _itemNotFound,
            id?.registrant,
          ),
          trailingStyle: TextStyle(
            color: id == null ? Colors.red : Colors.white,
          ),
        );
      },
      errorResultBuilder: (_, e) {
        const TextStyle style = TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.red,
        );

        return FixedSizeTile(
          tileColor: Colors.red.withAlpha(0x20),
          trailing: MapEntry(e.toString(), null),
          leadingStyle: style,
          trailingStyle: style,
        );
      },
      searchDigestBuilder: (_, key) {
        final MapEntry<int, UUIDAllocation?> result;

        if (key is String) {
          result = BluetoothIdentifiers.uuidServiceIdentifiers.entryForHex(key);
        } else if (key is int) {
          result = MapEntry(
            key,
            BluetoothIdentifiers.uuidServiceIdentifiers[key],
          );
        } else {
          throw Exception('Unhandled key type $key');
        }

        final String keyDescription = '0x${result.key.toRadixString(16).padLeft(4, '0')}';
        final Color themeColor = result.value != null ? Colors.green : Colors.red;
        final TextStyle style = TextStyle(color: themeColor);

        return FixedSizeTile(
          tileColor: themeColor.withAlpha(0x20),
          leading: keyDescription,
          trailing: MapEntry(
            result.value?.type ?? _searchResultNotFound,
            result.value?.registrant,
          ),
          leadingStyle: style,
          trailingStyle: style,
        );
      },
    );
  }
}

class CompanyIdentifiersPage extends StatelessWidget {
  const CompanyIdentifiersPage._({Key? key}) : super(key: key);

  factory CompanyIdentifiersPage.builder(BuildContext context) {
    return const CompanyIdentifiersPage._();
  }

  static const String routeName = '/company_identifiers';
  static const _searchResultNotFound = 'SEARCH RESULT NOT FOUND';
  static const _itemNotFound = 'NOT FOUND';

  @override
  Widget build(BuildContext context) {
    return DigestSearchPage(
      itemBuilder: (_, i) {
        final String? id = BluetoothIdentifiers.companyIdentifiers[i];

        return FixedSizeTile(
          tileColor: Colors.blueGrey,
          leading: '0x${i.toRadixString(16).padLeft(4, '0')}',
          leadingStyle: const TextStyle(color: Colors.white),
          trailing: MapEntry(id ?? _itemNotFound, null),
          trailingStyle: TextStyle(
            color: id == null ? Colors.red : Colors.white,
          ),
        );
      },
      errorResultBuilder: (_, e) {
        const TextStyle style = TextStyle(
          fontWeight: FontWeight.bold,
          color: Colors.red,
        );

        return FixedSizeTile(
          tileColor: Colors.red.withAlpha(0x20),
          center: e.toString(),
          centerStyle: style,
        );
      },
      searchDigestBuilder: (_, key) {
        final MapEntry<int, String?> result;

        if (key is String) {
          result = BluetoothIdentifiers.companyIdentifiers.entryForHex(key);
        } else if (key is int) {
          result = MapEntry(
            key,
            BluetoothIdentifiers.companyIdentifiers[key],
          );
        } else {
          throw Exception('Unhandled key type $key');
        }

        final String keyDescription = '0x${result.key.toRadixString(16).padLeft(4, '0')}';

        final Color themeColor = result.value != null ? Colors.green : Colors.red;
        final TextStyle style = TextStyle(color: themeColor);

        return FixedSizeTile(
          tileColor: themeColor.withAlpha(0x20),
          leading: keyDescription,
          trailing: MapEntry(result.value ?? _searchResultNotFound, null),
          leadingStyle: style,
          trailingStyle: style,
        );
      },
    );
  }
}

以上代码创建了一个简单的Flutter应用程序,用户可以通过选择不同的页面来搜索蓝牙设备的UUID服务标识符或公司标识符。希望这些内容能帮助您更好地理解和使用bluetooth_identifiers插件。


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

1 回复

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


当然,以下是如何在Flutter项目中使用bluetooth_identifiers插件来获取蓝牙设备标识的示例代码。这个插件允许你获取设备的蓝牙地址和其他相关信息,这对于需要识别特定蓝牙设备的应用非常有用。

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

dependencies:
  flutter:
    sdk: flutter
  bluetooth_identifiers: ^最新版本号  # 请替换为实际发布的最新版本号

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

接下来,在你的Flutter项目中,你可以使用以下代码来获取蓝牙设备的标识信息。注意,由于蓝牙操作可能需要用户权限,因此在实际应用中,你还需要处理权限请求。

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

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

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

class _MyAppState extends State<MyApp> {
  String? deviceAddress;
  String? deviceName;

  @override
  void initState() {
    super.initState();
    _getBluetoothDeviceIdentifiers();
  }

  Future<void> _getBluetoothDeviceIdentifiers() async {
    try {
      // 检查蓝牙权限(此步骤可能依赖于平台,具体实现可能有所不同)
      // 例如,在Android上可能需要请求LOCATION权限,因为蓝牙扫描可能被视为位置数据的一部分。
      // 这里假设权限已经获得。

      // 获取蓝牙适配器实例(此插件可能提供自己的方法或直接使用系统的)
      // 注意:bluetooth_identifiers插件可能不会直接提供获取适配器的方法,
      // 这里只是一个示例流程,具体实现需要参考插件文档。
      // BluetoothAdapter adapter = await BluetoothAdapter.defaultAdapter;

      // 由于bluetooth_identifiers的API可能直接提供获取设备标识的方法,
      // 我们假设它有一个名为getBluetoothDeviceIdentifiers的静态方法。
      // 具体的API调用需要参考插件的实际文档。
      // 下面的代码是一个假设性的示例。
      BluetoothDeviceIdentifiers identifiers =
          await BluetoothDeviceIdentifiers.getIdentifiers();

      // 设置状态以更新UI
      setState(() {
        deviceAddress = identifiers.address;
        deviceName = identifiers.name; // 假设插件提供了设备名称
      });
    } catch (e) {
      print("Error getting Bluetooth device identifiers: $e");
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Bluetooth Device Identifiers'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('Device Address: $deviceAddress'),
              SizedBox(height: 20),
              Text('Device Name: $deviceName'),
            ],
          ),
        ),
      ),
    );
  }
}

注意

  1. 上面的代码是一个假设性的示例,因为bluetooth_identifiers插件的具体API可能会有所不同。你需要参考插件的实际文档来调用正确的方法。
  2. 蓝牙操作可能需要特定的权限和设置,特别是在Android和iOS上。确保你已经处理了所有必要的权限请求和设置。
  3. 在生产环境中,添加适当的错误处理和用户反馈是很重要的。

由于bluetooth_identifiers插件的具体实现和API可能会随着版本更新而变化,强烈建议查阅最新的官方文档和示例代码。

回到顶部