semesterprojekt-bluetooth-p.../lib/screens/bluetooth_screen_serialtemp...

163 lines
4.9 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_serial/flutter_bluetooth_serial.dart';
import './bluetooth_device_list_entry.dart';
class BluetoothScreen extends StatefulWidget {
/// If true, discovery starts on page start, otherwise user must press action button.
final bool start;
const BluetoothScreen({this.start = true});
@override
_BluetoothScreen createState() => new _BluetoothScreen();
}
class _BluetoothScreen extends State<BluetoothScreen> {
StreamSubscription<BluetoothDiscoveryResult>? _streamSubscription;
List<BluetoothDiscoveryResult> results =
List<BluetoothDiscoveryResult>.empty(growable: true);
bool isDiscovering = false;
_BluetoothScreen();
@override
void initState() {
super.initState();
isDiscovering = widget.start;
if (isDiscovering) {
_startDiscovery();
}
}
void _restartDiscovery() {
setState(() {
results.clear();
isDiscovering = true;
});
_startDiscovery();
}
void _startDiscovery() {
_streamSubscription =
FlutterBluetoothSerial.instance.startDiscovery().listen((r) {
setState(() {
final existingIndex = results.indexWhere(
(element) => element.device.address == r.device.address);
if (existingIndex >= 0)
results[existingIndex] = r;
else
results.add(r);
});
});
_streamSubscription!.onDone(() {
setState(() {
isDiscovering = false;
});
});
}
// @TODO . One day there should be `_pairDevice` on long tap on something... ;)
@override
void dispose() {
// Avoid memory leak (`setState` after dispose) and cancel discovery
_streamSubscription?.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: isDiscovering
? Text('Discovering devices')
: Text('Discovered devices'),
actions: <Widget>[
isDiscovering
? FittedBox(
child: Container(
margin: new EdgeInsets.all(16.0),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
)
: IconButton(
icon: Icon(Icons.replay),
onPressed: _restartDiscovery,
)
],
),
body: ListView.builder(
itemCount: results.length,
itemBuilder: (BuildContext context, index) {
BluetoothDiscoveryResult result = results[index];
final device = result.device;
final address = device.address;
return BluetoothDeviceListEntry(
device: device,
rssi: result.rssi,
onTap: () {
Navigator.of(context).pop(result.device);
},
onLongPress: () async {
try {
bool bonded = false;
if (device.isBonded) {
print('Unbonding from ${device.address}...');
await FlutterBluetoothSerial.instance
.removeDeviceBondWithAddress(address);
print('Unbonding from ${device.address} has succed');
} else {
print('Bonding with ${device.address}...');
bonded = (await FlutterBluetoothSerial.instance
.bondDeviceAtAddress(address))!;
print(
'Bonding with ${device.address} has ${bonded ? 'succed' : 'failed'}.');
}
setState(() {
results[results.indexOf(result)] = BluetoothDiscoveryResult(
device: BluetoothDevice(
name: device.name ?? '',
address: address,
type: device.type,
bondState: bonded
? BluetoothBondState.bonded
: BluetoothBondState.none,
),
rssi: result.rssi);
});
} catch (ex) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Error occured while bonding'),
content: Text("${ex.toString()}"),
actions: <Widget>[
new TextButton(
child: new Text("Close"),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
},
);
},
),
);
}
}