connect method
Establishes a connection to the Bluetooth Device.
timeout
if timeout occurs, cancel the connection request and throw exception
mtu
Android only. Request a larger mtu right after connection, if set.
autoConnect
reconnect whenever the device is found
- if true, this function always returns immediately.
- you must listen to connectionState
to know when connection occurs.
- auto connect is turned off by calling disconnect
- auto connect results in a slower connection process compared to a direct connection
because it relies on the internal scheduling of background scans.
Implementation
Future<void> connect({
Duration timeout = const Duration(seconds: 35),
int? mtu = 512,
bool autoConnect = false,
}) async {
// If you hit this assert, you must set `mtu:null`, i.e `device.connect(mtu:null, autoConnect:true)`
// and you'll have to call `requestMtu` yourself. `autoConnect` is not compatibile with `mtu`.
assert(
(mtu == null) || !autoConnect, "mtu and auto connect are incompatible");
// make sure no one else is calling disconnect
_Mutex dmtx = _MutexFactory.getMutexForKey("disconnect");
bool dtook = await dmtx.take();
// Only allow a single ble operation to be underway at a time
_Mutex mtx = _MutexFactory.getMutexForKey("global");
await mtx.take();
try {
// remember auto connect value
if (autoConnect) {
FlutterBluePlus._autoConnect.add(remoteId);
}
var request = BmConnectRequest(
remoteId: remoteId,
autoConnect: autoConnect,
);
var responseStream = FlutterBluePlus._methodStream.stream
.where((m) => m.method == "OnConnectionStateChanged")
.map((m) => m.arguments)
.map((args) => BmConnectionStateResponse.fromMap(args))
.where((p) => p.remoteId == remoteId);
// Start listening now, before invokeMethod, to ensure we don't miss the response
Future<BmConnectionStateResponse> futureState = responseStream.first;
// invoke
bool changed =
await FlutterBluePlus._invokeMethod('connect', request.toMap());
// we return the disconnect mutex now so that this
// connection attempt can be canceled by calling disconnect
dtook = dmtx.give();
// only wait for connection if we weren't already connected
if (changed && !autoConnect) {
BmConnectionStateResponse response = await futureState
.fbpEnsureAdapterIsOn("connect")
.fbpTimeout(timeout.inSeconds, "connect")
.catchError((e) async {
if (e is FlutterBluePlusException &&
e.code == FbpErrorCode.timeout.index) {
await FlutterBluePlus._invokeMethod(
'disconnect', remoteId.str); // cancel connection attempt
}
throw e;
});
// failure?
if (response.connectionState == BmConnectionStateEnum.disconnected) {
if (response.disconnectReasonCode == bmUserCanceledErrorCode) {
throw FlutterBluePlusException(ErrorPlatform.fbp, "connect",
FbpErrorCode.connectionCanceled.index, "connection canceled");
} else {
throw FlutterBluePlusException(_nativeError, "connect",
response.disconnectReasonCode, response.disconnectReasonString);
}
}
}
} finally {
if (dtook) {
dmtx.give();
}
mtx.give();
}
// request larger mtu
if (isConnected && mtu != null) {
await requestMtu(mtu);
}
}