Flutter高级蓝牙操作插件bluetooth_advanced的使用
Flutter高级蓝牙操作插件bluetooth_advanced的使用
如何使用
要使用 bluetooth_advanced
插件,请遵循以下步骤:
Step1: 添加插件依赖
在你的 pubspec.yaml
文件中添加插件:
dependencies:
bluetooth_advanced: [latest_version]
Step2: 导入插件
在你的 Dart 文件中导入插件:
import 'package:bluetooth_advanced/bluetooth_advanced.dart';
Step3: 初始化配置详情
在这里,重要的是设置与服务器设备相似的 UUID。这些 UUID 是用于识别蓝牙设备所提供服务的独特信息。你的应用程序将通过这些标准协议连接到该设备。
final _bluetoothAdvanced = BluetoothAdvanced();
print(await _bluetoothAdvanced.getDataCharactersticUUID());
print(await _bluetoothAdvanced.getServiceCharactersticUUID());
await _bluetoothAdvanced
.setServiceCharactersticUUID("0000baad-0000-1000-8000-00805f9b34fb");
await _bluetoothAdvanced
.setDataCharactersticUUID("0000BEEF-0000-1000-8000-00805F9B34FB");
Step4: 初始化蓝牙
这将返回一个流,你可以持续监听它:
_bluetoothAdvanced.initBluetooth();
Step5: 扫描设备
这将返回一个流,你可以持续监听扫描状态:
状态 | 描述 | 数据类型/格式 |
---|---|---|
SCANNING_STARTED | 开始扫描配对设备 | 字符串 |
SCANNING_FINISHED_WITH_NO_DEVICE | 未找到设备 | 字符串 |
[device_address], [device_name] | 返回设备地址和名称 | 字符串: “01:23:45:67:89:10,MyBluetoothDevice” |
_bluetoothAdvanced.scanDevices();
Step6: 连接设备
这将返回一个流,你可以持续监听连接状态:
状态 | 描述 | 数据类型/格式 |
---|---|---|
DEVICE_RECOGNIZING | 认识到了具有必要信息的设备 | 字符串 |
DEVICE_CONNECTING | 尝试连接设备 | 字符串 |
DEVICE_CONNECTED | 建立了与设备的连接 | 字符串 |
DEVICE_DISCONNECTED | 连接中断 | 字符串 |
DEVICE_CONNECTING_FAILED | 尝试连接失败 | 字符串 |
_bluetoothAdvanced.connectDevice().listen((event) {
switch (event.toString()) {
case STATE_RECOGNIZING:
break;
case STATE_CONNECTING:
break;
case STATE_CONNECTED:
setState(() {
isConnected = true;
});
break;
case STATE_DISCONNECTED:
setState(() {
isConnected = false;
});
break;
case STATE_CONNECTING_FAILED:
break;
default:
}
});
Step7: 监听数据
这将返回一个流,你可以持续监听数据接收状态:
状态 | 描述 | 数据类型/格式 |
---|---|---|
DEVICE_DATA_INITIATED | 尝试与设备进行数据握手 | 字符串 |
DEVICE_DATA_CONNECTING | 尝试与设备建立数据连接 | 字符串 |
DEVICE_DATA_CONNECTED | 建立了与设备的数据连接 | 字符串 |
DEVICE_DATA_AVAILABLE | 收到了可用的数据 | 字符串: “DEVICE_DATA_AVAILABLE:this is the data received” |
DEVICE_DATA_DISCONNECTED | 数据连接被撤销 | 字符串 |
_bluetoothAdvanced.listenData().listen((event) {
if (event.startsWith(DEVICE_DATA_AVAILABLE)) {
setState(() {
isData = true;
data = event.toString();
});
}
switch (event.toString()) {
case DEVICE_DATA_INITIATED:
printWrapped(DEVICE_DATA_INITIATED);
break;
case DEVICE_DATA_CONNECTING:
printWrapped(DEVICE_DATA_CONNECTING);
break;
case DEVICE_DATA_CONNECTED:
printWrapped(DEVICE_DATA_CONNECTED);
break;
case DEVICE_DATA_AVAILABLE:
printWrapped(DEVICE_DATA_AVAILABLE);
break;
case DEVICE_DATA_DISCONNECTED:
setState(() {
isData = false;
isConnected = false;
});
break;
default:
}
});
Step8: 撤销连接
这将撤销与设备的连接。如果你不调用此函数,它将在后台继续运行并持续接收数据。
_bluetoothAdvanced.dispose();
示例代码
以下是一个完整的示例代码:
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:bluetooth_advanced/bluetooth_advanced.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
List<Widget> list = [const Text('')];
final _bluetoothAdvanced = BluetoothAdvanced();
late StreamSubscription streamSubscription;
late StreamBuilder streamBuilder;
bool isConnected = false;
String? data;
bool isData = false;
[@override](/user/override)
void initState() {
super.initState();
initBluetoothConfig();
listentoDeviceData();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.cyan.shade900,
title: const Text('bluetooth_advanced'),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 2,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
StreamBuilder<Object>(
stream: _bluetoothAdvanced.scanDevices(),
builder: (BuildContext context, AsyncSnapshot<Object> snapshot) {
if (snapshot.hasError) {
return showError(snapshot.error);
} else if (snapshot.hasData) {
if (snapshot.data.toString() == SCANNING_FINISHED_WITH_NO_DEVICE) {
return deviceNotFound();
} else {
List<String> device = snapshot.data.toString().split(",");
return deviceFound(device[0], device[1]);
}
} else {
return deviceScanning();
}
},
),
StreamBuilder<String>(
stream: _bluetoothAdvanced.initBluetooth(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasError) {
return const Text("Error Occurred!");
} else if (snapshot.hasData) {
return Text("Starting Connection: ${snapshot.data}");
} else {
return const Text("Waiting for connection to start...");
}
},
),
isConnected && isData
? Text(data!)
: const Text('Waiting to be connected'),
],
),
),
const Spacer(),
bottomBar()
],
),
),
),
);
}
/* utilities functions */
void printWrapped(String text) {
final pattern = RegExp('.{1,300}');
pattern.allMatches(text).forEach((match) => print(match.group(0)));
}
Future<void> initBluetoothConfig() async {
try {
print(await _bluetoothAdvanced
.setServiceCharactersticUUID("0000baad-0000-1000-8000-00805f9b34fb"));
print(await _bluetoothAdvanced
.setDataCharactersticUUID("0000BEEF-0000-1000-8000-00805F9B34FB"));
print(await _bluetoothAdvanced.getDataCharactersticUUID());
print(await _bluetoothAdvanced.getServiceCharactersticUUID());
print(await (_bluetoothAdvanced.setScanPeriod(10000)));
await _bluetoothAdvanced.setNotificationText("new text");
await _bluetoothAdvanced.setNotificationTitle("new title");
} catch (e) {
print(e.toString());
}
if (!mounted) return;
}
listentoDeviceData() {
_bluetoothAdvanced.listenData().listen((event) {
if (event.startsWith(DEVICE_DATA_AVAILABLE)) {
setState(() {
isData = true;
data = event.toString();
});
}
switch (event.toString()) {
case DEVICE_DATA_INITIATED:
printWrapped(DEVICE_DATA_INITIATED);
break;
case DEVICE_DATA_CONNECTING:
printWrapped(DEVICE_DATA_CONNECTING);
break;
case DEVICE_DATA_CONNECTED:
printWrapped(DEVICE_DATA_CONNECTED);
break;
case DEVICE_DATA_AVAILABLE:
printWrapped(DEVICE_DATA_AVAILABLE);
break;
case DEVICE_DATA_DISCONNECTED:
setState(() {
isData = false;
isConnected = false;
});
break;
default:
}
});
}
/* widget function */
showError(Object? error) {
String errorMessage = 'Some Error Encountered';
if (error.runtimeType == PlatformException) {
PlatformException? platformException = error as PlatformException?;
errorMessage = platformException!.code;
} else {
errorMessage = error.toString();
}
return Card(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Error:',
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 8),
Text(errorMessage,
style: const TextStyle(
fontSize: 14, fontStyle: FontStyle.italic)),
],
)));
}
deviceScanning() {
return Card(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 20),
child: Row(
children: const [
Text("scanning devices",
style:
TextStyle(fontSize: 14, fontStyle: FontStyle.italic)),
SizedBox(width: 12),
SizedBox(
height: 22, width: 22, child: CircularProgressIndicator())
],
)));
}
deviceNotFound() {
return Card(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text("No Device found, Retry",
style:
TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 8),
const Text(
"""Troubleshoot: \n ► Try increasing the scan period.\n ► Check if the device is paired in bluetooth settings.\n ► Check if paired device has correct configurations like uuids""",
style:
TextStyle(fontSize: 14, fontStyle: FontStyle.italic)),
],
)));
}
deviceFound(String address, String name) {
return Card(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
child: Row(
children: [
isConnected
? const Icon(Icons.bluetooth_connected_rounded,
color: Colors.green)
: const Icon(Icons.bluetooth_rounded, color: Colors.grey),
const SizedBox(width: 10),
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(name,
style: const TextStyle(
fontSize: 20, fontWeight: FontWeight.bold)),
const SizedBox(height: 6),
Text(address,
style: const TextStyle(
fontSize: 14, fontStyle: FontStyle.italic))
]),
const Spacer(),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all<Color>(
isConnected ? Colors.green : Colors.lightBlue),
),
onPressed: () {
_bluetoothAdvanced.connectDevice().listen((event) {
switch (event.toString()) {
case STATE_RECOGNIZING:
break;
case STATE_CONNECTING:
break;
case STATE_CONNECTED:
setState(() {
isConnected = true;
});
break;
case STATE_DISCONNECTED:
setState(() {
isConnected = false;
});
break;
case STATE_CONNECTING_FAILED:
break;
default:
}
});
},
child: Text(
isConnected ? 'Connected' : 'Connect',
style:
const TextStyle(fontSize: 14, fontStyle: FontStyle.italic),
))
],
),
));
}
bottomBar() {
return Row(
crossAxisAlignment: CrossAxisAlignment.end,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Icon(Icons.info_outline_rounded, color: Colors.grey),
SizedBox(width: 10),
Text(
'Remember to turn on bluetooth\nand GPS first',
style: TextStyle(
fontStyle: FontStyle.italic, color: Colors.blueGrey),
),
],
),
const Spacer(),
ElevatedButton(
style: ButtonStyle(
padding: MaterialStateProperty.all<EdgeInsetsGeometry>(
const EdgeInsets.symmetric(vertical: 20)),
backgroundColor: MaterialStateProperty.all<Color>(
isConnected && isData ? Colors.cyan.shade900 : Colors.grey),
),
onPressed: () async {
await _bluetoothAdvanced.dispose();
},
child: const Icon(Icons.stop_circle)),
],
);
}
}
更多关于Flutter高级蓝牙操作插件bluetooth_advanced的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter高级蓝牙操作插件bluetooth_advanced的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter应用中使用bluetooth_advanced
插件进行高级蓝牙操作的示例代码。这个插件提供了更全面的蓝牙功能,包括扫描设备、连接设备、读写蓝牙特征值等。
首先,确保你已经在pubspec.yaml
文件中添加了bluetooth_advanced
依赖:
dependencies:
flutter:
sdk: flutter
bluetooth_advanced: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
示例代码
以下是一个基本的Flutter应用示例,它展示了如何使用bluetooth_advanced
插件进行蓝牙扫描和连接操作。
main.dart
import 'package:flutter/material.dart';
import 'package:bluetooth_advanced/bluetooth_advanced.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
BluetoothAdvanced _bluetoothAdvanced = BluetoothAdvanced();
List<BluetoothDevice> _devices = [];
BluetoothDevice? _connectedDevice;
@override
void initState() {
super.initState();
initBluetooth();
}
Future<void> initBluetooth() async {
bool isBluetoothEnabled = await _bluetoothAdvanced.isBluetoothEnabled();
if (!isBluetoothEnabled) {
// Handle Bluetooth not enabled case
return;
}
// Request location permission (required for Bluetooth scanning on Android)
bool hasLocationPermission = await _bluetoothAdvanced.requestLocationPermission();
if (!hasLocationPermission) {
// Handle permission denied case
return;
}
// Start scanning for devices
_bluetoothAdvanced.startDeviceScan(allowDuplicates: false).listen((devices) {
setState(() {
_devices = devices;
});
}, onError: (error) {
// Handle scan error
print('Scan error: $error');
}, onDone: () {
// Handle scan done (e.g., when stopDeviceScan is called)
print('Scan done');
});
}
Future<void> connectToDevice(BluetoothDevice device) async {
bool isConnected = await _bluetoothAdvanced.connectToDevice(device);
if (isConnected) {
setState(() {
_connectedDevice = device;
});
// Optionally, start discovering services, characteristics, etc.
discoverServices();
} else {
// Handle connection failure
print('Failed to connect to device: ${device.address}');
}
}
Future<void> discoverServices() async {
if (_connectedDevice != null) {
List<BluetoothService> services = await _bluetoothAdvanced.discoverServices(_connectedDevice!);
// Process discovered services
print('Discovered services: $services');
// Example: Get characteristics for the first service
if (services.isNotEmpty) {
List<BluetoothCharacteristic> characteristics = await _bluetoothAdvanced.getCharacteristics(services.first);
// Process characteristics
print('Characteristics: $characteristics');
}
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Bluetooth Advanced Example'),
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _devices.length,
itemBuilder: (context, index) {
BluetoothDevice device = _devices[index];
return ListTile(
title: Text(device.name ?? 'Unknown Device'),
subtitle: Text(device.address),
onTap: () => connectToDevice(device),
);
},
),
),
if (_connectedDevice != null)
Text('Connected Device: ${_connectedDevice!.name ?? _connectedDevice!.address}'),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// Stop scanning when FAB is pressed
_bluetoothAdvanced.stopDeviceScan();
},
tooltip: 'Stop Scanning',
child: Icon(Icons.stop),
),
),
);
}
}
注意事项
-
权限处理:在Android上,你需要处理位置权限请求,因为蓝牙扫描需要位置权限。在iOS上,蓝牙权限通常是自动处理的,但确保在
Info.plist
中添加了适当的蓝牙使用描述。 -
错误处理:在实际应用中,你应该添加更多的错误处理逻辑,以确保应用的健壮性。
-
平台特定代码:某些蓝牙操作可能需要在iOS和Android上分别处理,因此可能需要使用平台通道(Platform Channels)来编写特定于平台的代码。
-
依赖更新:由于插件和Flutter框架可能会更新,请确保你使用的是最新版本的
bluetooth_advanced
插件,并查看其文档以获取最新的API信息和最佳实践。
这个示例代码提供了一个基本的框架,你可以在此基础上扩展以实现更复杂的功能,如读写蓝牙特征值、订阅特征值通知等。