Skip to content

Commit 7a632ae

Browse files
Fixed race condition in scan peripherals (#490)
* Fixed race condition in scan peripherals Under certain circumstances a problem can be reported by the native side very quickly. Since monitoring for callbacks started after the call, those responses could be delivered before anyone would start to listen.
1 parent 938ddb9 commit 7a632ae

File tree

1 file changed

+30
-23
lines changed

1 file changed

+30
-23
lines changed

lib/src/bridge/scanning_mixin.dart

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,49 @@
11
part of _internal;
22

33
mixin ScanningMixin on FlutterBLE {
4-
Stream<dynamic> _scanEvents;
4+
Stream<ScanResult> _scanEvents;
55

66
void _prepareScanEventsStream() {
7-
_scanEvents =
8-
const EventChannel(ChannelName.scanningEvents).receiveBroadcastStream();
7+
_scanEvents = const EventChannel(ChannelName.scanningEvents)
8+
.receiveBroadcastStream()
9+
.handleError(
10+
(errorJson) => throw BleError.fromJson(jsonDecode(errorJson.details)),
11+
test: (error) => error is PlatformException,
12+
)
13+
.map(
14+
(scanResultJson) =>
15+
ScanResult.fromJson(jsonDecode(scanResultJson), _manager),
16+
);
917
}
1018

1119
Stream<ScanResult> startDeviceScan(
1220
int scanMode,
1321
int callbackType,
1422
List<String> uuids,
1523
bool allowDuplicates,
16-
) async* {
17-
_methodChannel.invokeMethod(
18-
MethodName.startDeviceScan,
19-
<String, dynamic>{
20-
ArgumentName.scanMode: scanMode,
21-
ArgumentName.callbackType: callbackType,
22-
ArgumentName.uuids: uuids,
23-
ArgumentName.allowDuplicates: allowDuplicates,
24-
},
25-
);
26-
24+
) {
2725
if (_scanEvents == null) {
2826
_prepareScanEventsStream();
2927
}
3028

31-
yield* _scanEvents.handleError(
32-
(errorJson) {
33-
throw BleError.fromJson(jsonDecode(errorJson.details));
34-
},
35-
test: (error) => error is PlatformException,
36-
).map((scanResultJson) => ScanResult.fromJson(
37-
jsonDecode(scanResultJson),
38-
_manager,
39-
));
29+
StreamController<ScanResult> streamController = StreamController.broadcast(
30+
onListen: () => _methodChannel.invokeMethod(
31+
MethodName.startDeviceScan,
32+
<String, dynamic>{
33+
ArgumentName.scanMode: scanMode,
34+
ArgumentName.callbackType: callbackType,
35+
ArgumentName.uuids: uuids,
36+
ArgumentName.allowDuplicates: allowDuplicates,
37+
},
38+
),
39+
onCancel: () => stopDeviceScan(),
40+
);
41+
42+
streamController
43+
.addStream(_scanEvents, cancelOnError: true)
44+
.then((_) => streamController?.close());
45+
46+
return streamController.stream;
4047
}
4148

4249
Future<void> stopDeviceScan() async {

0 commit comments

Comments
 (0)