2024/08/18 使用當前最新版 flutter_blue_plus (1.32.12) 寫的無IDE建議或警告的藍牙掃描頁面。
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
class BLEHomePage extends StatefulWidget {
const BLEHomePage({super.key});
@override
BLEHomePageState createState() => BLEHomePageState();
}
class BLEHomePageState extends State<BLEHomePage> {
BluetoothDevice? connectedDevice;
List<ScanResult> devicesList = <ScanResult>[];
BluetoothCharacteristic? characteristic;
bool isScanning = false;
StreamSubscription<List<ScanResult>>? scanSubscription;
@override
void initState() {
super.initState();
startScan();
}
void startScan() async {
if (isScanning) return;
setState(() {
isScanning = true;
devicesList = [];
});
// 啟動掃描,並訂閱掃描結果 (使用 scanResults)
scanSubscription?.cancel();
scanSubscription = FlutterBluePlus.scanResults.listen((results) {
setState(() {
devicesList = results;
});
for (ScanResult r in results) {
if (r.device.platformName == "AI Glove" && connectedDevice == null) {
connectToDevice(r.device);
stopScan();
break;
}
}
}, onError: (error) {
// 處理掃描錯誤
if (kDebugMode) {
print('Error during scan: $error');
}
// 在使用 context 之前檢查 mounted
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Scanning error: $error')),
);
}
});
// 啟動掃描 (使用 startScan, without timeout)
await FlutterBluePlus.startScan();
// 設定掃描超時 (使用 Timer)
Timer(const Duration(seconds: 4), () {
stopScan();
});
}
void connectToDevice(BluetoothDevice device) async {
try {
await FlutterBluePlus.stopScan();
await device.connect();
setState(() {
connectedDevice = device;
isScanning = false;
});
List<BluetoothService> services = await device.discoverServices();
for (BluetoothService service in services) {
List<BluetoothCharacteristic> characteristics = service.characteristics;
for (BluetoothCharacteristic c in characteristics) {
if (c.properties.notify) {
characteristic = c;
await c.setNotifyValue(true);
// Use lastValueStream instead of value
c.lastValueStream.listen((value) {
// Do somethings
});
}
}
}
} catch (e) {
// 處理連接錯誤
if (kDebugMode) {
print('Error connecting to device: $e');
}
// 在使用 context 之前檢查 mounted
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Connection error: $e')),
);
}
}
}
void stopScan() {
if (!isScanning) return;
FlutterBluePlus.stopScan();
scanSubscription?.cancel();
setState(() {
isScanning = false;
});
}
@override
void dispose() {
FlutterBluePlus.stopScan();
scanSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('BLE'),
actions: [
IconButton(
icon: const Icon(Icons.refresh),
onPressed: isScanning ? null : startScan,
),
],
),
body: Center(
child: connectedDevice == null
? isScanning
? const CircularProgressIndicator() // 在掃描時顯示進度指示器
: const Text('No devices found. Please try scanning again.')
: Text('Connected to ${connectedDevice!.platformName}'),
),
floatingActionButton: FloatingActionButton(
onPressed: isScanning ? null : startScan,
child: const Icon(Icons.refresh),
),
);
}
}

Leave a comment