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 createState() => _BluetoothConnectionScreenState(); } class _BluetoothConnectionScreenState extends State { List 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 startScan() async { // 1. Pedir permissões (necessário no Android) Map 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 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), ), ); }, ), ), ], ), ); } }