Buduję aplikację na Androida, która ma określone wymagania dotyczące niskiego zużycia energii Bluetooth.RxAndroidBle utrzymywanie stałego połączenia + obsługa zapisu/powiadamiania
Muszę napisać do charakterystyki tylko do zapisu i otrzymywać odpowiedzi na osobnej charakterystyce powiadomienia i muszę to zrobić w wielu, wielu działaniach. Czy istnieje sposób Rx, aby wysłać żądanie na pierwszą cechę, czekać na odpowiedź na drugiej, a następnie przejść do innego wniosku?
Ponadto, aby udostępnić moją instancję RxAndroidBle, pomyślałem o zrobieniu jakiegoś BleManager Singleton, w którym odsłoniłbym Observables, więc mogę z łatwością zapisać się do nich w moim Presenterze. Po prostu chcę uniknąć konieczności kopiowania logiki połączenia dla każdego działania i (najlepiej) stałego połączenia. W ten sposób mogłem tylko odsłonić connectionObservable i zasubskrybować go, dzięki czemu mogę łatwo wysyłać żądania zapisu i otrzymywać powiadomienia, ale jestem pewien, że jest lepszy sposób na zrobienie tego.
To co mam teraz:
@Singleton
public class BleManager {
private PublishSubject<Void> disconnectTriggerSubject = PublishSubject.create();
private Observable<RxBleConnection> connectionObservable;
private boolean isConnected;
private final UUID CTRL_FROM_BRIDGE_UUID = UUID.fromString("someUUID");
private final UUID BLE_WRITE_CHARACTERISTIC_UUID = UUID.fromString("someOtherUUID");
private final RxBleClient bleClient;
private String mMacAddress;
private final Context context;
private RxBleDevice bleDevice;
@Inject
public BleManager(Context context, RxBleClient client) {
Timber.d("Constructing BleManager and injecting members");
this.context = context;
this.bleClient = client;
}
public void setMacAddress(String mMacAddress) {
this.mMacAddress = mMacAddress;
// Set the associated device on MacAddress change
bleDevice = bleClient.getBleDevice(this.mMacAddress);
}
public String getMacAddress() {
return mMacAddress;
}
public RxBleDevice getBleDevice() {
Preconditions.checkNotNull(mMacAddress);
return bleClient.getBleDevice(mMacAddress);
}
public Observable<RxBleScanResult> getScanSubscription() {
Preconditions.checkNotNull(context);
Preconditions.checkNotNull(bleClient);
return bleClient.scanBleDevices().distinct();
}
public Observable<RxBleConnection> getConnectionSubscription() {
Preconditions.checkNotNull(context);
Preconditions.checkNotNull(bleDevice);
if (connectionObservable == null) {
connectionObservable = bleDevice.establishConnection(context, false)
.takeUntil(disconnectTriggerSubject)
.observeOn(AndroidSchedulers.mainThread())
.doOnUnsubscribe(this::clearSubscription)
.compose(new ConnectionSharingAdapter());
}
return connectionObservable;
}
public Observable<byte[]> setupListeners() {
return connectionObservable.flatMap(rxBleConnection -> rxBleConnection.setupNotification(CTRL_FROM_BRIDGE_UUID))
.doOnNext(notificationObservable -> Timber.d("Notification Setup"))
.flatMap(notificationObservable -> notificationObservable)
.observeOn(AndroidSchedulers.mainThread());
}
private void triggerDisconnect() {
disconnectTriggerSubject.onNext(null);
}
public Observable<byte[]> writeBytes(byte[] bytes) {
return connectionObservable.flatMap(rxBleConnection -> rxBleConnection.writeCharacteristic(
BLE_WRITE_CHARACTERISTIC_UUID,
bytes)).observeOn(AndroidSchedulers.mainThread());
}
private boolean isConnected() {
return bleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.CONNECTED;
}
/**
* Will update the UI with the current state of the Ble Connection
*/
private void registerConnectionStateChange() {
bleDevice.observeConnectionStateChanges().observeOn(AndroidSchedulers.mainThread()).subscribe(connectionState -> {
isConnected = connectionState.equals(RxBleConnection.RxBleConnectionState.CONNECTED);
});
}
private void clearSubscription() {
connectionObservable = null;
}
}
Awesome, wypróbuję Twoje rozwiązanie i dam ci znać, jak to działa. Jest to bardzo doceniane, ponieważ jestem nowy w świecie Rx i wciąż się uczę! –
Czy próbowałeś zaproponowanego rozwiązania? Czy działało zgodnie z przeznaczeniem? –