使用flutter设计一个蓝牙控制界面,进入页面后,检查申请代码所需的权限,自动搜索显示蓝牙设备列表,有搜索进度显示,有控制按钮,有通讯输入框和发送功能,支持空安全,请列出代码和依赖控件
时间: 2024-03-01 09:52:26 浏览: 14
好的,我理解了你的要求。下面是一个简单的蓝牙控制界面的Flutter代码,包括搜索蓝牙设备、连接设备、发送数据等功能:
依赖控件:
```
dependencies:
flutter:
sdk: flutter
permission_handler: ^8.1.2
flutter_blue: ^0.8.0
```
代码实现:
```dart
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter_blue/flutter_blue.dart';
class BluetoothControlPage extends StatefulWidget {
@override
_BluetoothControlPageState createState() => _BluetoothControlPageState();
}
class _BluetoothControlPageState extends State<BluetoothControlPage> {
final FlutterBlue flutterBlue = FlutterBlue.instance;
List<BluetoothDevice> devices = [];
BluetoothDevice? device;
BluetoothCharacteristic? characteristic;
bool isConnecting = false;
bool isConnected = false;
bool isSending = false;
String message = "";
TextEditingController messageController = TextEditingController();
@override
void initState() {
super.initState();
checkPermissions();
}
@override
void dispose() {
messageController.dispose();
super.dispose();
}
Future<void> checkPermissions() async {
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
].request();
if (statuses[Permission.location] != PermissionStatus.granted) {
// 如果未授权,则提示用户授权
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text("需要位置权限"),
content: Text("请授权以搜索蓝牙设备"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("取消"),
),
TextButton(
onPressed: () async {
await openAppSettings();
Navigator.pop(context);
},
child: Text("去设置"),
),
],
),
);
} else {
startScan();
}
}
Future<void> startScan() async {
flutterBlue.scanResults.listen((results) {
// 扫描到设备时更新设备列表
setState(() {
devices = results.map((r) => r.device).toList();
});
});
await flutterBlue.startScan(timeout: Duration(seconds: 4));
flutterBlue.stopScan();
}
Future<void> connectDevice(BluetoothDevice d) async {
setState(() {
isConnecting = true;
});
await d.connect();
setState(() {
device = d;
isConnecting = false;
isConnected = true;
});
List<BluetoothService> services = await device!.discoverServices();
services.forEach((service) {
service.characteristics.forEach((c) {
if (c.uuid.toString() == "0000ffe1-0000-1000-8000-00805f9b34fb") {
characteristic = c;
}
});
});
if (characteristic == null) {
// 如果未找到特征,则提示用户
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text("未找到特征"),
content: Text("请确保设备已连接并正确配置"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("确定"),
),
],
),
);
}
}
Future<void> disconnectDevice() async {
await device?.disconnect();
setState(() {
device = null;
isConnected = false;
characteristic = null;
});
}
Future<void> sendMessage(String message) async {
if (characteristic == null) {
// 如果未找到特征,则提示用户
showDialog(
context: context,
builder: (_) => AlertDialog(
title: Text("未找到特征"),
content: Text("请确保设备已连接并正确配置"),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("确定"),
),
],
),
);
return;
}
setState(() {
isSending = true;
});
List<int> bytes = utf8.encode(message);
await characteristic!.write(bytes);
setState(() {
isSending = false;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("蓝牙控制"),
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: EdgeInsets.all(16),
child: Text(
"可用设备",
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
ListView.builder(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
itemCount: devices.length,
itemBuilder: (context, index) {
BluetoothDevice d = devices[index];
return ListTile(
title: Text(d.name.isEmpty ? "未知设备" : d.name),
subtitle: Text(d.id.toString()),
trailing: ElevatedButton(
onPressed: isConnecting
? null
: () async {
await connectDevice(d);
},
child: isConnecting
? SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: Text("连接"),
),
);
},
),
if (isConnected)
Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"控制",
style:
TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
Row(
children: [
ElevatedButton(
onPressed: isSending
? null
: () async {
await sendMessage("1");
},
child: isSending ? Text("发送中") : Text("开灯"),
),
SizedBox(
width: 16,
),
ElevatedButton(
onPressed: isSending
? null
: () async {
await sendMessage("0");
},
child: isSending ? Text("发送中") : Text("关灯"),
),
],
),
SizedBox(
height: 16,
),
TextField(
controller: messageController,
decoration: InputDecoration(
labelText: "发送数据",
border: OutlineInputBorder(),
),
),
SizedBox(
height: 16,
),
ElevatedButton(
onPressed: isSending
? null
: () async {
await sendMessage(messageController.text);
},
child: isSending ? Text("发送中") : Text("发送"),
),
SizedBox(
height: 16,
),
ElevatedButton(
onPressed: isConnecting
? null
: () async {
await disconnectDevice();
},
child: Text("断开连接"),
),
],
),
),
],
),
),
);
}
}
```
上面的代码实现了蓝牙设备搜索、连接和数据发送的基本功能,可以根据实际需求进行修改和完善。