-
Notifications
You must be signed in to change notification settings - Fork 588
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
`DeadObjectException` is usually thrown when interacting with `BluetoothAdapter` or `BluetoothGatt` instance that was obtained before bluetooth being turned off. Prior to library version `1.3.0` all errors raised when interacting with `BluetoothGatt` or recieved by `BluetoothGattCallback` were closing the connection (were emitted by `RxBleDevice.establishConnection()`). After `1.3.0` only errors raised in `RxBleRadioOperationConnect` and recieved by `BluetoothGattCallback.onConnectionStateChange()` were closing the connection so it was possible that `DeadObjectException`s raised repetedly by subscribing to i.e. `RxBleConnection.readRssi()` would not close the connection. Added monitoring of BluetoothAdapter’s state to prevent `DeadObjectException`s and inform the user about the connection loss as soon as possible. Moved responsibility of checking the BluetoothAdapter’s state from Connector to DisconnectionRouter to have it in one place.
- Loading branch information
1 parent
34cae8c
commit d3e8f68
Showing
6 changed files
with
341 additions
and
307 deletions.
There are no files selected for viewing
93 changes: 93 additions & 0 deletions
93
...idble/src/main/java/com/polidea/rxandroidble/internal/connection/DisconnectionRouter.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package com.polidea.rxandroidble.internal.connection; | ||
|
||
|
||
import com.jakewharton.rxrelay.PublishRelay; | ||
import com.polidea.rxandroidble.RxBleAdapterStateObservable; | ||
import com.polidea.rxandroidble.exceptions.BleDisconnectedException; | ||
import com.polidea.rxandroidble.exceptions.BleException; | ||
import com.polidea.rxandroidble.exceptions.BleGattException; | ||
import com.polidea.rxandroidble.internal.DeviceModule; | ||
import com.polidea.rxandroidble.internal.util.RxBleAdapterWrapper; | ||
import javax.inject.Inject; | ||
import javax.inject.Named; | ||
import rx.Observable; | ||
import rx.functions.Func1; | ||
|
||
/** | ||
* A class that is responsible for routing all potential sources of disconnection to an Observable that emits only errors. | ||
*/ | ||
@ConnectionScope | ||
class DisconnectionRouter { | ||
|
||
private final PublishRelay<BleException> disconnectionErrorRelay = PublishRelay.create(); | ||
|
||
private final Observable disconnectionErrorObservable; | ||
|
||
@Inject | ||
DisconnectionRouter( | ||
@Named(DeviceModule.MAC_ADDRESS) final String macAddress, | ||
final RxBleAdapterWrapper adapterWrapper, | ||
final Observable<RxBleAdapterStateObservable.BleAdapterState> adapterStateObservable | ||
) { | ||
disconnectionErrorObservable = Observable.merge( | ||
disconnectionErrorRelay | ||
.flatMap(new Func1<BleException, Observable<?>>() { | ||
@Override | ||
public Observable<?> call(BleException e) { | ||
return Observable.error(e); | ||
} | ||
}), | ||
adapterStateObservable | ||
.map(new Func1<RxBleAdapterStateObservable.BleAdapterState, Boolean>() { | ||
@Override | ||
public Boolean call(RxBleAdapterStateObservable.BleAdapterState bleAdapterState) { | ||
return bleAdapterState.isUsable(); | ||
} | ||
}) | ||
.startWith(adapterWrapper.isBluetoothEnabled()) | ||
.filter(new Func1<Boolean, Boolean>() { | ||
@Override | ||
public Boolean call(Boolean isAdapterUsable) { | ||
return !isAdapterUsable; | ||
} | ||
}) | ||
.flatMap(new Func1<Boolean, Observable<?>>() { | ||
@Override | ||
public Observable<?> call(Boolean isAdapterUsable) { | ||
return Observable.error(new BleDisconnectedException(macAddress)); // TODO: Introduce BleDisabledException? | ||
} | ||
}) | ||
) | ||
.replay() | ||
.autoConnect(0); | ||
} | ||
|
||
/** | ||
* Method to be called whenever a connection braking exception happens. It will be routed to {@link #asObservable()}. | ||
* | ||
* @param disconnectedException the exception that happened | ||
*/ | ||
void onDisconnectedException(BleDisconnectedException disconnectedException) { | ||
disconnectionErrorRelay.call(disconnectedException); | ||
} | ||
|
||
/** | ||
* Method to be called whenever a BluetoothGattCallback.onConnectionStateChange() will get called with status != GATT_SUCCESS | ||
* | ||
* @param disconnectedGattException the exception that happened | ||
*/ | ||
void onGattConnectionStateException(BleGattException disconnectedGattException) { | ||
disconnectionErrorRelay.call(disconnectedGattException); | ||
} | ||
|
||
/** | ||
* Function returning an Observable that will only throw error in case of a disconnection | ||
* | ||
* @param <T> the type of returned observable | ||
* @return the Observable | ||
*/ | ||
<T> Observable<T> asObservable() { | ||
//noinspection unchecked | ||
return disconnectionErrorObservable; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.