Files
runvisionpro_app/lib/bluetooth_connection_screen.dart
2026-02-26 16:45:47 +00:00

170 lines
5.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
import 'package:permission_handler/permission_handler.dart';
import 'dart:async';
class BluetoothConnectionScreen extends StatefulWidget {
const BluetoothConnectionScreen({super.key});
@override
State<BluetoothConnectionScreen> createState() => _BluetoothConnectionScreenState();
}
class _BluetoothConnectionScreenState extends State<BluetoothConnectionScreen> {
List<ScanResult> scanResults = [];
bool isScanning = false;
StreamSubscription? scanSubscription;
StreamSubscription? isScanningSubscription;
@override
void initState() {
super.initState();
// Monitorar se o sistema está escaneando
isScanningSubscription = FlutterBluePlus.isScanning.listen((scanning) {
if (mounted) {
setState(() {
isScanning = scanning;
});
}
});
// Ouvir os resultados do scan globalmente
scanSubscription = FlutterBluePlus.scanResults.listen((results) {
if (mounted) {
setState(() {
scanResults = results;
});
}
});
}
@override
void dispose() {
scanSubscription?.cancel();
isScanningSubscription?.cancel();
super.dispose();
}
Future<void> startScan() async {
// 1. Pedir permissões (necessário no Android)
Map<Permission, PermissionStatus> statuses = await [
Permission.bluetoothScan,
Permission.bluetoothConnect,
Permission.location,
].request();
if (statuses[Permission.bluetoothScan]!.isGranted &&
statuses[Permission.bluetoothConnect]!.isGranted &&
statuses[Permission.location]!.isGranted) {
setState(() {
scanResults.clear();
});
// 2. Iniciar o scan
try {
await FlutterBluePlus.startScan(timeout: const Duration(seconds: 15));
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Erro ao buscar: $e')),
);
}
}
} else {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Permissões negadas')),
);
}
}
}
Future<void> connectToDevice(BluetoothDevice device) async {
try {
await device.connect();
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Conectado a ${device.platformName.isEmpty ? 'Dispositivo' : device.platformName}')),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Falha ao conectar: $e')),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Conexão Bluetooth'),
backgroundColor: Colors.grey[850],
foregroundColor: Colors.white,
),
backgroundColor: Colors.grey[900],
body: Column(
children: [
const SizedBox(height: 20),
Center(
child: Column(
children: [
const Icon(
Icons.bluetooth,
size: 80,
color: Colors.white,
),
const SizedBox(height: 10),
ElevatedButton.icon(
onPressed: isScanning ? null : startScan,
icon: isScanning
? const SizedBox(width: 18, height: 18, child: CircularProgressIndicator(strokeWidth: 2, color: Colors.black))
: const Icon(Icons.search),
label: Text(isScanning ? 'Buscando...' : 'Procurar Dispositivos'),
style: ElevatedButton.styleFrom(
backgroundColor: Colors.white,
foregroundColor: Colors.black,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15),
textStyle: const TextStyle(fontSize: 18),
),
),
],
),
),
const SizedBox(height: 20),
Expanded(
child: scanResults.isEmpty && !isScanning
? const Center(
child: Text(
"Nenhum dispositivo encontrado.\nClique em procurar.",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white70),
),
)
: ListView.builder(
itemCount: scanResults.length,
itemBuilder: (context, index) {
final device = scanResults[index].device;
final name = device.platformName.isEmpty ? 'Desconhecido' : device.platformName;
return Card(
color: Colors.white10,
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
child: ListTile(
title: Text(name, style: const TextStyle(color: Colors.white)),
subtitle: Text(device.remoteId.toString(), style: const TextStyle(color: Colors.white70)),
trailing: const Icon(Icons.link, color: Colors.blue),
onTap: () => connectToDevice(device),
),
);
},
),
),
],
),
);
}
}