discoverServices method
Discover services, characteristics, and descriptors of the remote device
subscribeToServicesChanged
Android Only: If true, after discovering services we will subscribe to the Services Changed Characteristic (0x2A05) used for thedevice.onServicesReset
stream. Note: this behavior happens automatically on iOS and cannot be disabled
Implementation
Future<List<BluetoothService>> discoverServices(
{bool subscribeToServicesChanged = true, int timeout = 15}) async {
// check connected
if (isDisconnected) {
throw FlutterBluePlusException(ErrorPlatform.fbp, "discoverServices",
FbpErrorCode.deviceIsDisconnected.index, "device is not connected");
}
// Only allow a single ble operation to be underway at a time
_Mutex mtx = _MutexFactory.getMutexForKey("global");
await mtx.take();
List<BluetoothService> result = [];
try {
var responseStream = FlutterBluePlus._methodStream.stream
.where((m) => m.method == "OnDiscoveredServices")
.map((m) => m.arguments)
.map((args) => BmDiscoverServicesResult.fromMap(args))
.where((p) => p.remoteId == remoteId);
// Start listening now, before invokeMethod, to ensure we don't miss the response
Future<BmDiscoverServicesResult> futureResponse = responseStream.first;
// invoke
await FlutterBluePlus._invokeMethod('discoverServices', remoteId.str);
// wait for response
BmDiscoverServicesResult response = await futureResponse
.fbpEnsureAdapterIsOn("discoverServices")
.fbpEnsureDeviceIsConnected(this, "discoverServices")
.fbpTimeout(timeout, "discoverServices");
// failed?
if (!response.success) {
throw FlutterBluePlusException(_nativeError, "discoverServices",
response.errorCode, response.errorString);
}
result =
response.services.map((p) => BluetoothService.fromProto(p)).toList();
} finally {
mtx.give();
}
// in order to match iOS behavior on all platforms,
// we always listen to the Services Changed characteristic if it exists.
if (subscribeToServicesChanged) {
if (Platform.isIOS == false && Platform.isMacOS == false) {
BluetoothCharacteristic? c = _servicesChangedCharacteristic;
if (c != null &&
(c.properties.notify || c.properties.indicate) &&
c.isNotifying == false) {
await c.setNotifyValue(true);
}
}
}
return result;
}