Search code examples
androidbluetoothrxandroidble

How to establish connection and then read characteristics in one activity?


Currently modifying the sample code and I am encountering an error when try to establish a connection and then read a characteristic in one activity.

I am getting BleAlreadyConnectedException when attempting to read from the device. I am first connecting on onCreate.

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_device);

    // How to listen for connection state changes
    bleDevice.observeConnectionStateChanges()
            .compose(bindUntilEvent(DESTROY))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(this::onConnectionStateChange);

    if (isConnected()) {
        triggerDisconnect();
    } else {
        connectionSubscription = bleDevice.establishConnection(this, true)
                .compose(bindUntilEvent(PAUSE))
                .observeOn(AndroidSchedulers.mainThread())
                .doOnUnsubscribe(this::clearSubscription)
                .subscribe(this::onConnectionReceived, this::onConnectionFailure);
    }
}

and then trying to read a characteristic in onConnectionReceived...

    private void onConnectionReceived(RxBleConnection connection) { 
    Log.d(TAG, "onConnectionReceived");
    connectionObservable = bleDevice
            .establishConnection(this, false)
            .takeUntil(disconnectTriggerSubject)
            .compose(bindUntilEvent(PAUSE))
            .doOnUnsubscribe(this::clearSubscription)
            .compose(new ConnectionSharingAdapter());

    if (isConnected()) {
        connectionObservable
                .flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(uuid))
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(bytes -> {
                    Log.d(TAG, "onConnectionReceived:" + bytes);
                }, this::onReadFailure);
    }
}

How do you work around the double .establishConnection(this, false) with ConnectionSharingAdapter?


Solution

  • The thing is that you are connecting twice. You should rather:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_device);
    
      // How to listen for connection state changes
      bleDevice.observeConnectionStateChanges()
        .compose(bindUntilEvent(DESTROY))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(this::onConnectionStateChange);
    
      connectionObservable = bleDevice.establishConnection(this, true)
        .compose(bindUntilEvent(PAUSE))
        .takeUntil(disconnectTriggerSubject)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .doOnUnsubscribe(this::clearSubscription)
        .compose(new ConnectionSharingAdapter());
    
      if (isConnected()) {
          triggerDisconnect();
      } else {
          connectionObservable.subscribe(this::onConnectionReceived, this::onConnectionFailure);
      }
    }
    
    private void onConnectionReceived(RxBleConnection connection) { 
      Log.d(TAG, "onConnectionReceived");
      connection
        .flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(uuid))
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(bytes -> {
            Log.d(TAG, "onValueReceived:" + bytes);
        }, this::onReadFailure);
    }
    

    Full example is here.