Flutter蓝牙通信插件my_bluetooth的使用
Flutter蓝牙通信插件my_bluetooth的使用
简介
my_bluetooth
是一个用于Flutter项目的插件,它简化了通过蓝牙与其他设备进行连接和数据传输的过程。该插件提供了易于使用的API,可以扫描、连接和交换数据。
功能
- 扫描附近的蓝牙设备
- 连接蓝牙设备
- 发送和接收数据
- 自定义连接和传输
支持平台
方法 | Android | iOS | 描述 |
---|---|---|---|
turnOn() |
✅ | 打开蓝牙 | |
adapterState |
✅ | ✅ | 获取适配器状态 |
bondedDevices |
✅ | 获取已配对设备 | |
discoveryState |
✅ | ✅ | 获取扫描状态 |
startScan() |
✅ | ✅ | 开始扫描附近设备 |
stopScan() |
✅ | 停止扫描 | |
lastScanResults |
✅ | 获取最后一次扫描结果 | |
scanResults |
✅ | 获取扫描结果 | |
connectionState |
✅ | ✅ | 设备连接状态 |
sendingState |
✅ | ✅ | 发送状态 |
connect() (iOS自动连接) |
✅ | ✅ | 连接设备 |
disconnect() |
✅ | ✅ | 断开连接 |
send data |
✅ | ✅ | 发送数据 |
权限
在使用此插件时,需要以下权限:
- Bluetooth
- Bluetooth scan
- Bluetooth connect
- access_fine_location
使用方法
1. 添加依赖
在 pubspec.yaml
文件中添加 my_bluetooth
依赖:
dependencies:
flutter:
sdk: flutter
my_bluetooth: ^latest_version
然后运行以下命令来获取依赖项:
flutter pub get
2. 导入包
在 Dart 文件中导入 my_bluetooth
包:
import 'package:my_bluetooth/my_bluetooth.dart';
3. iOS 设置
由于 iOS 的安全问题,需要在 ios/Runner/Info.plist
文件中添加以下内容:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>此应用始终需要蓝牙功能</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>此应用需要蓝牙外围设备功能</string>
<key>UISupportedExternalAccessoryProtocols</key>
<array>
<string>net.dsgl.nailpopPro.protocol</string>
<!-- 使用你自己的协议 -->
</array>
<key>UIBackgroundModes</key>
<array>
<string>bluetooth-central</string>
<string>external-accessory</string>
<string>fetch</string>
<string>remote-notification</string>
</array>
4. 示例代码
以下是一个完整的示例代码,展示了如何使用 my_bluetooth
插件进行蓝牙设备的扫描、连接和数据发送。
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:my_bluetooth/my_bluetooth.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
[@override](/user/override)
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
late final XFile? image;
final _myBluetooth = MyBluetooth();
MPBluetoothAdapterState _adapterState = MPBluetoothAdapterState.unknown;
late StreamSubscription<MPBluetoothAdapterState> _adapterStateStateSubscription;
bool _isScanning = false;
late StreamSubscription<bool> _isScanningSubscription;
MPConnectionStateEnum _connectState = MPConnectionStateEnum.disconnected;
late StreamSubscription<ConnectionStateResponse> _connectStateSubscription;
late StreamSubscription<List<BluetoothDevice>> _scanResultsSubscription;
List<BluetoothDevice> _scanResults = [];
[@override](/user/override)
void initState() {
super.initState();
// 监听蓝牙适配器状态变化
_adapterStateStateSubscription = _myBluetooth.adapterState.listen((state) {
_adapterState = state;
if (mounted) {
setState(() {});
}
}, onError: (e) {});
// 监听连接状态变化
_connectStateSubscription = _myBluetooth.connectionState.listen((state) {
_connectState = state.connectionState;
if (mounted) {
setState(() {});
}
}, onError: (e) {});
// 监听扫描状态变化
_isScanningSubscription = _myBluetooth.discoveryState.listen((state) {
_isScanning = state;
if (mounted) {
setState(() {});
}
}, onError: (e) {});
// 监听扫描结果
_scanResultsSubscription = _myBluetooth.scanResults.listen((results) {
_scanResults = results;
if (mounted) {
setState(() {});
}
}, onError: (e) {});
}
[@override](/user/override)
void dispose() {
// 取消所有订阅
_adapterStateStateSubscription.cancel();
_scanResultsSubscription.cancel();
_connectStateSubscription.cancel();
_isScanningSubscription.cancel();
super.dispose();
}
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app | My Bluetooth'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text("步骤 1. 打开/关闭蓝牙"),
Text("蓝牙适配器状态: ${_adapterState.toString()}"),
TextButton(
onPressed: () async {
await _myBluetooth.turnOn();
},
child: const Text("打开蓝牙")),
const Text("步骤 2: 扫描设备"),
Text("正在扫描: ${_isScanning.toString()}"),
const SizedBox(
height: 20,
),
const Text("步骤 3: 连接"),
Text("连接状态: $_connectState"),
TextButton(
onPressed: () async {
print(await _myBluetooth.disconnect());
},
child: const Text("断开连接")),
const SizedBox(
height: 20,
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 1,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
TextButton(
onPressed: () async {
var bondedDevices = await _myBluetooth.bondedDevices;
setState(() {
_scanResults = bondedDevices;
});
print("已配对设备数量: ${bondedDevices.length}");
},
child: const Text("获取已配对设备")),
TextButton(
onPressed: () async {
await _myBluetooth.startScan(withKeywords: [
// "Nailpop", "Nailpop Pro",
// "Snap# Kiosk", "DMP"
// "image box"
]);
},
child: const Text("开始扫描")),
TextButton(
onPressed: () async {
print(await _myBluetooth.stopScan());
},
child: const Text("停止扫描")),
],
),
),
SizedBox(
width: MediaQuery.of(context).size.width / 3 * 2,
height: 140,
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemCount: _scanResults.length,
itemBuilder: (BuildContext context, int index) {
final item = _scanResults[index];
return GestureDetector(
onTap: () async {
print("点击 ${item.remoteId}");
print(await _myBluetooth.connect(remoteId: item.remoteId));
},
child: Container(
margin: const EdgeInsets.symmetric(horizontal: 20),
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.blueAccent.withOpacity(0.2)),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"名称: ${item.platformName}",
style: const TextStyle(fontWeight: FontWeight.bold),
),
Text("ID: ${item.remoteId}"),
Text("配对状态: ${item.bondState}"),
Text("类型: ${item.type}"),
],
),
),
);
},
),
)
],
),
const Text(
"发送文本到设备",
style: TextStyle(fontWeight: FontWeight.w800),
),
TextButton(
onPressed: () async {
await _myBluetooth.sendText(value: "Hello World");
},
child: const Text("1 | 发送文本 'Hello World'")),
// 发送文件
const Text(
"如何发送文件?",
style: TextStyle(fontWeight: FontWeight.w800),
),
TextButton(
onPressed: () async {
final ImagePicker picker = ImagePicker();
image = await picker.pickImage(source: ImageSource.gallery);
print(image?.path);
},
child: const Text("步骤 1 | 选择文件")),
const SizedBox(
height: 10,
),
TextButton(
onPressed: () async {
if (image != null) {
print(await _myBluetooth.sendFile(pathImage: image?.path));
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("请先选择文件")));
}
},
child: const Text("步骤 3 | 发送文件")),
// 发送自定义命令
const Text(
"注意!!!你可以使用 'sendCmd' 函数发送任何数据。",
style: TextStyle(fontWeight: FontWeight.w500),
),
],
),
),
),
),
);
}
}
更多关于Flutter蓝牙通信插件my_bluetooth的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter蓝牙通信插件my_bluetooth的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个关于如何使用Flutter蓝牙通信插件my_bluetooth
的代码示例。请注意,由于my_bluetooth
并非一个广为人知的官方或广泛使用的插件,代码示例将基于假设的API设计。如果my_bluetooth
插件的API有所不同,请参考其官方文档进行调整。
首先,确保你已经在pubspec.yaml
文件中添加了my_bluetooth
依赖:
dependencies:
flutter:
sdk: flutter
my_bluetooth: ^x.y.z # 替换为实际版本号
然后运行flutter pub get
来获取依赖。
接下来,是一个使用my_bluetooth
插件进行蓝牙通信的基本示例:
import 'package:flutter/material.dart';
import 'package:my_bluetooth/my_bluetooth.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
MyBluetooth? _bluetooth;
List<BluetoothDevice> _devices = [];
BluetoothDevice? _connectedDevice;
@override
void initState() {
super.initState();
_initBluetooth();
}
Future<void> _initBluetooth() async {
_bluetooth = MyBluetooth();
// 请求蓝牙权限(假设API提供此方法)
bool hasPermission = await _bluetooth!.requestPermission();
if (!hasPermission) {
// 处理权限被拒绝的情况
return;
}
// 启用蓝牙(假设API提供此方法)
bool isEnabled = await _bluetooth!.isEnabled();
if (!isEnabled) {
await _bluetooth!.enable();
}
// 开始扫描设备(假设API提供此方法)
_bluetooth!.scanDevices().listen((List<BluetoothDevice> devices) {
setState(() {
_devices = devices;
});
});
}
Future<void> _connectToDevice(BluetoothDevice device) async {
setState(() {
_connectedDevice = device;
});
// 连接到设备(假设API提供此方法)
bool isConnected = await _bluetooth!.connectToDevice(device);
if (isConnected) {
// 处理连接成功的情况
print('Connected to ${device.name}');
} else {
// 处理连接失败的情况
print('Failed to connect to ${device.name}');
}
}
Future<void> _sendData(String data) async {
if (_connectedDevice != null) {
// 发送数据到设备(假设API提供此方法)
bool isSent = await _bluetooth!.sendData(_connectedDevice!, data);
if (isSent) {
print('Data sent: $data');
} else {
print('Failed to send data: $data');
}
} else {
print('No device connected');
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Flutter Bluetooth Communication'),
),
body: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: _devices.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_devices[index].name),
onTap: () => _connectToDevice(_devices[index]),
);
},
),
),
ElevatedButton(
onPressed: () async {
await _sendData('Hello, Bluetooth!');
},
child: Text('Send Data'),
),
],
),
),
);
}
}
// 假设的BluetoothDevice类
class BluetoothDevice {
String name;
String address; // 设备地址
BluetoothDevice({required this.name, required this.address});
}
注意:
- 上述代码是基于假设的API设计,
my_bluetooth
插件的实际API可能会有所不同。请参考插件的官方文档获取正确的API使用方法。 - 蓝牙权限请求、启用蓝牙、扫描设备、连接设备以及发送数据等操作通常需要异步处理,因此使用了
async
和await
关键字。 - 错误处理和用户交互(如权限被拒绝、蓝牙未启用、设备连接失败等情况)应根据实际需求进行完善。
BluetoothDevice
类是一个假设的类,实际使用时应根据插件提供的类进行替换。
希望这个示例能帮助你开始使用my_bluetooth
插件进行蓝牙通信。如果有任何问题或需要进一步的帮助,请随时提问。