I am working with the plugin FLutter Blue, and I have a StreamBuilder with a list of devices found after the scan process. Every element of the list can be expanded (ExpansionTile).
I noticed that the scanning, even if I remove the timeout
parameter from the FlutterBlue.instance.startScan
call, somehow does not continue, because if I move another device near my smartphone it doesn't replace the device that was before on the top (I sorted the devices list for RSSI).
The only way to make it happen is to use FlutterBlue.instance.startScan(allowDuplicates: true)
.
At the same time, however, this leads to wildly really jumping results, so my idea, in order to better observe the behaviour of a specific device in the list, is to keep the device at the top if ExpansionTile is expanded/I clicked on it).
Anyway, I am not sure if this is the best solution, or if I should do something different with the FlutterBlue library. Anyone can help me?
This is my code:
@override
Widget build(BuildContext context) {
return Scaffold(
body: RefreshIndicator(
onRefresh: () async => await flutterBlueStartScan(),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
StreamBuilder<List<ScanResult>>(
stream: FlutterBlue.instance.scanResults,
initialData: [],
builder: (c, snapshot) => Column(
children: snapshot.data!
.map(
(r) => ScanResultTile(
result: r,
onTap: () => Navigator.of(context)
.push(MaterialPageRoute(builder: (context) {
r.device.connect();
return DeviceScreen(device: r.device);
})),
),
)
.toSet()
.toList()
..sort((a, b) => b.result.rssi.compareTo(a.result.rssi)),
),
),
],
),
),
),
floatingActionButton: StreamBuilder<bool>(
stream: FlutterBlue.instance.isScanning,
initialData: false,
builder: (c, snapshot) {
if (snapshot.data!) {
return FloatingActionButton(
child: Icon(Icons.stop),
onPressed: () => FlutterBlue.instance.stopScan(),
);
} else {
return FloatingActionButton(
child: Icon(Icons.search),
backgroundColor: primaryColor,
onPressed: () async {
return await flutterBlueStartScan();
});
}
},
),
);
}
where:
Future flutterBlueStartScan() async {
return await FlutterBlue.instance.startScan(allowDuplicates: true);
}
and:
class ScanResultTile extends StatelessWidget {
const ScanResultTile({Key? key, required this.result, this.onTap)
: super(key: key);
final ScanResult result;
final VoidCallback? onTap;
@override
Widget build(BuildContext context) {
return ExpansionTile(
title: _buildTitle(context),
leading: leading(result),
trailing: Text(result.rssi.toString()),
children: <Widget>[
_buildAdvertisementContent(context), //that contains more specific info about the device
Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
child: Text('CONNECT'),
onPressed: (result.advertisementData.connectable) ? onTap : null,
),
)
],
);
}
...