我正在构建一个对低功耗蓝牙有特定要求的 Android 应用程序。
我需要写入只写特性并接收单独通知特性的响应,并且我需要在许多活动中执行此操作。是否有一种 Rx 方式可以在第一个特征上发送请求,等待第二个特征的答案,然后继续进行另一个请求?
此外,为了分享我的 RxAndroidBle 实例,我想过做一些 BleManager Singleton 来公开 Observables,这样我就可以在我的 Presenter 中轻松订阅它们。我只是想避免必须为每个活动复制连接逻辑并拥有(理想情况下)持久连接。这样我只能公开 connectionObservable 并订阅它,因此我可以轻松发送写入请求并获取通知,但我确信有更好的方法来做到这一点。
这就是我现在所拥有的:
@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;
}
}