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 BluetoothScreen extends StatefulWidget { const BluetoothScreen({super.key}); @override State createState() => _BluetoothScreenState(); } class _BluetoothScreenState extends State { List _scanResults = []; bool _isScanning = false; StreamSubscription? _scanResultsSubscription; StreamSubscription? _isScanningSubscription; @override void initState() { super.initState(); _scanResultsSubscription = FlutterBluePlus.scanResults.listen((results) { if (mounted) { setState(() { _scanResults = results; }); } }); _isScanningSubscription = FlutterBluePlus.isScanning.listen((state) { if (mounted) { setState(() { _isScanning = state; }); } }); } @override void dispose() { _scanResultsSubscription?.cancel(); _isScanningSubscription?.cancel(); super.dispose(); } Future startScan() async { // 1. Pedir permissões Map statuses = await [ Permission.bluetoothScan, Permission.bluetoothConnect, Permission.location, ].request(); if (statuses[Permission.bluetoothScan]!.isGranted && statuses[Permission.bluetoothConnect]!.isGranted) { try { // 2. Iniciar Scan await FlutterBluePlus.startScan( timeout: const Duration(seconds: 15), ); // Se não encontrar nada (ex: no emulador), avisa o usuário Future.delayed(const Duration(seconds: 5), () { if (mounted && _scanResults.isEmpty && _isScanning) { _showSnackBar("Nenhum dispositivo encontrado (Verifique se o Bluetooth/GPS estão ligados)", Colors.orange); } }); } catch (e) { _showSnackBar("Erro ao iniciar busca: $e", Colors.red); } } else { _showSnackBar("Permissões de Bluetooth negadas", Colors.orange); } } Future connectToDevice(BluetoothDevice device) async { try { String name = device.platformName.isEmpty ? 'Dispositivo' : device.platformName; _showSnackBar("Conectando a $name...", Colors.blue); await device.connect(); _showSnackBar("Conectado com sucesso!", Colors.green); } catch (e) { _showSnackBar("Falha ao conectar: $e", Colors.red); } } void _showSnackBar(String message, Color color) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), backgroundColor: color, duration: const Duration(seconds: 3), ), ); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Conexão Bluetooth'), backgroundColor: Colors.black87, 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.blue), 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: 24, vertical: 12), ), ), ], ), ), const SizedBox(height: 20), Expanded( child: _scanResults.isEmpty && !_isScanning ? const Center( child: Text( "Clique em Procurar para encontrar dispositivos.\n(Nota: Requer telemóvel físico para Bluetooth real)", textAlign: TextAlign.center, style: TextStyle(color: Colors.white54), ), ) : ListView.builder( itemCount: _scanResults.length, itemBuilder: (context, index) { final r = _scanResults[index]; final name = r.device.platformName.isEmpty ? "Dispositivo Desconhecido" : r.device.platformName; return Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), color: Colors.white10, child: ListTile( leading: const Icon(Icons.bluetooth, color: Colors.blue), title: Text( name, style: const TextStyle( color: Colors.white, fontWeight: FontWeight.bold, ), ), subtitle: Text( r.device.remoteId.toString(), style: const TextStyle(color: Colors.white70), ), trailing: ElevatedButton( onPressed: () => connectToDevice(r.device), child: const Text("Conectar"), ), ), ); }, ), ), ], ), ); } }