scan method
Starts a scan for Bluetooth Low Energy devices and returns a stream of the ScanResult results as they are received.
timeout calls stopStream after a specified Duration. You can also get a list of ongoing results in the scanResults stream. If scanning is already in progress, this will throw an Exception.
Implementation
Stream<ScanResult> scan({
ScanMode scanMode = ScanMode.lowLatency,
List<Guid> withServices = const [],
List<Guid> withDevices = const [],
Duration? timeout,
bool allowDuplicates = false,
}) async* {
var settings = protos.ScanSettings.create()
..androidScanMode = scanMode.value
..allowDuplicates = allowDuplicates
..serviceUuids.addAll(withServices.map((g) => g.toString()).toList());
if (_isScanning.value == true) {
throw Exception('Another scan is already in progress.');
}
// Emit to isScanning
_isScanning.add(true);
final killStreams = <Stream>[];
killStreams.add(_stopScanPill);
if (timeout != null) {
killStreams.add(Rx.timer(null, timeout));
}
// Clear scan results list
_scanResults.add(<ScanResult>[]);
try {
await _channel.invokeMethod('startScan', settings.writeToBuffer());
} catch (e) {
print('Error starting scan.');
_stopScanPill.add(null);
_isScanning.add(false);
throw e;
}
yield* FlutterBlue.instance._methodStream
.where((m) => m.method == "ScanResult")
.map((m) => m.arguments)
.takeUntil(Rx.merge(killStreams))
.doOnDone(stopScan)
.map((buffer) => new protos.ScanResult.fromBuffer(buffer))
.map((p) {
final result = new ScanResult.fromProto(p);
final list = _scanResults.value;
int index = list.indexOf(result);
if (index != -1) {
list[index] = result;
} else {
list.add(result);
}
_scanResults.add(list);
return result;
});
}