Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce getConnectedPeripherals to allow existing connections to be retrieved #765

Merged
merged 9 commits into from
May 21, 2022
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,15 @@ public static class Builder {

private ReplaySubject<RxBleDeviceMock> discoverableDevicesSubject;
private Set<RxBleDevice> bondedDevices;
private Set<RxBleDevice> connectedPeripherals;

/**
* Build a new {@link RxBleClientMock}.
*/
public Builder() {
this.discoverableDevicesSubject = ReplaySubject.create();
this.bondedDevices = new HashSet<>();
this.connectedPeripherals = new HashSet<>();
}

public Builder setDeviceDiscoveryObservable(@NonNull Observable<RxBleDeviceMock> discoverableDevicesObservable) {
Expand Down Expand Up @@ -73,6 +75,16 @@ public Builder addBondedDevice(@NonNull RxBleDevice rxBleDevice) {
return this;
}

/**
* Add a {@link RxBleDevice} to the list of connected devices.
*
* @param rxBleDevice device that the mocked client should contain. Use {@link RxBleDeviceMock.Builder} to create them.
*/
public Builder addConnectedPeripheral(@NonNull RxBleDevice rxBleDevice) {
connectedPeripherals.add(rxBleDevice);
return this;
}

/**
* Create the {@link RxBleClientMock} instance using the configured values.
*/
Expand Down Expand Up @@ -248,10 +260,12 @@ public List<BluetoothGattDescriptor> build() {
}

private Set<RxBleDevice> bondedDevices;
private Set<RxBleDevice> connectedPeripherals;
private ReplaySubject<RxBleDeviceMock> discoveredDevicesSubject;

private RxBleClientMock(Builder builder) {
bondedDevices = builder.bondedDevices;
connectedPeripherals = builder.connectedPeripherals;
discoveredDevicesSubject = builder.discoverableDevicesSubject;
}

Expand All @@ -273,6 +287,11 @@ public Set<RxBleDevice> getBondedDevices() {
return bondedDevices;
}

@Override
public Set<RxBleDevice> getConnectedPeripherals() {
return connectedPeripherals;
}

@Override
@SuppressWarnings("deprecation")
public Observable<RxBleScanResult> scanBleDevices(@Nullable UUID... filterServiceUUIDs) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,13 @@ public static void updateLogOptions(LogOptions logOptions) {
*/
public abstract Set<RxBleDevice> getBondedDevices();

/**
* A function returning a set of currently connected devices (NOTE: Connected to the phone, not necessarily application)
*
* @return set of currently connected devices
*/
public abstract Set<RxBleDevice> getConnectedPeripherals();

/**
* Returns an infinite observable emitting BLE scan results.
* Scan is automatically started and stopped based on the Observable lifecycle.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,17 @@
import com.polidea.rxandroidble2.internal.util.ClientStateObservable;
import com.polidea.rxandroidble2.internal.util.LocationServicesStatus;
import com.polidea.rxandroidble2.internal.util.RxBleAdapterWrapper;
import com.polidea.rxandroidble2.internal.util.BluetoothManagerWrapper;
import com.polidea.rxandroidble2.internal.util.ScanRecordParser;
import com.polidea.rxandroidble2.scan.BackgroundScanner;
import com.polidea.rxandroidble2.scan.ScanFilter;
import com.polidea.rxandroidble2.scan.ScanResult;
import com.polidea.rxandroidble2.scan.ScanSettings;

import io.reactivex.functions.Consumer;

import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
Expand All @@ -45,6 +45,7 @@
import io.reactivex.ObservableSource;
import io.reactivex.Scheduler;
import io.reactivex.functions.Action;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;

Expand All @@ -61,6 +62,7 @@ class RxBleClientImpl extends RxBleClient {
private final ClientComponent.ClientComponentFinalizer clientComponentFinalizer;
final Scheduler bluetoothInteractionScheduler;
final Map<Set<UUID>, Observable<RxBleScanResult>> queuedScanOperations = new HashMap<>();
private final BluetoothManagerWrapper bluetoothManagerWrapper;
private final RxBleAdapterWrapper rxBleAdapterWrapper;
private final Observable<BleAdapterState> rxBleAdapterStateObservable;
private final LocationServicesStatus locationServicesStatus;
Expand All @@ -69,7 +71,8 @@ class RxBleClientImpl extends RxBleClient {
private final CheckerScanPermission checkerScanPermission;

@Inject
RxBleClientImpl(RxBleAdapterWrapper rxBleAdapterWrapper,
RxBleClientImpl(BluetoothManagerWrapper bluetoothManagerWrapper,
RxBleAdapterWrapper rxBleAdapterWrapper,
ClientOperationQueue operationQueue,
Observable<BleAdapterState> adapterStateObservable,
ScanRecordParser scanRecordParser,
Expand All @@ -84,6 +87,7 @@ class RxBleClientImpl extends RxBleClient {
BackgroundScanner backgroundScanner,
CheckerScanPermission checkerScanPermission) {
this.operationQueue = operationQueue;
this.bluetoothManagerWrapper = bluetoothManagerWrapper;
this.rxBleAdapterWrapper = rxBleAdapterWrapper;
this.rxBleAdapterStateObservable = adapterStateObservable;
this.scanRecordParser = scanRecordParser;
Expand Down Expand Up @@ -123,6 +127,17 @@ public Set<RxBleDevice> getBondedDevices() {
return rxBleDevices;
}

@Override
public Set<RxBleDevice> getConnectedPeripherals() {
Set<RxBleDevice> rxBleDevices = new HashSet<>();
List<BluetoothDevice> bluetoothDevices = bluetoothManagerWrapper.getConnectedPeripherals();
for (BluetoothDevice bluetoothDevice : bluetoothDevices) {
rxBleDevices.add(getBleDevice(bluetoothDevice.getAddress()));
}

return rxBleDevices;
}

@Override
public Observable<ScanResult> scanBleDevices(final ScanSettings scanSettings, final ScanFilter... scanFilters) {
return Observable.defer(new Callable<ObservableSource<? extends ScanResult>>() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.polidea.rxandroidble2.internal.util;

import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;

import java.util.List;

import bleshadow.javax.inject.Inject;

public class BluetoothManagerWrapper {

private final BluetoothManager bluetoothManager;

@Inject
public BluetoothManagerWrapper(BluetoothManager bluetoothManager) {
this.bluetoothManager = bluetoothManager;
}

public List<BluetoothDevice> getConnectedPeripherals() {
return bluetoothManager.getConnectedDevices(BluetoothProfile.GATT_SERVER);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.polidea.rxandroidble2

import android.bluetooth.BluetoothDevice
import android.bluetooth.BluetoothManager
import com.polidea.rxandroidble2.internal.util.BluetoothManagerWrapper

class MockBluetoothManagerWrapper extends BluetoothManagerWrapper {

private List<BluetoothDevice> connectedPeripherals = new ArrayList<>()

MockBluetoothManagerWrapper() {
super(null)
}

MockBluetoothManagerWrapper(BluetoothManager bluetoothManager) {
super(bluetoothManager)
}

def addConnectedPeripheral(BluetoothDevice bluetoothDevice) {
connectedPeripherals.add(bluetoothDevice)
}

@Override
List<BluetoothDevice> getConnectedPeripherals() {
return connectedPeripherals
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class RxBleClientTest extends ElectricSpecification {
RxBleClient objectUnderTest
Context contextMock = Mock Context
ScanRecordParser scanRecordParserSpy = Spy ScanRecordParser
MockBluetoothManagerWrapper bluetoothManagerWrapperSpy = Spy MockBluetoothManagerWrapper
MockRxBleAdapterWrapper bleAdapterWrapperSpy = Spy MockRxBleAdapterWrapper
MockRxBleAdapterStateObservable adapterStateObservable = Spy MockRxBleAdapterStateObservable
MockLocationServicesStatus locationServicesStatusMock = Spy MockLocationServicesStatus
Expand Down Expand Up @@ -77,6 +78,7 @@ class RxBleClientTest extends ElectricSpecification {
mockOperationScan.run(_) >> Observable.never()
mockScanSetupBuilder.build(_, _) >> mockScanSetup
objectUnderTest = new RxBleClientImpl(
bluetoothManagerWrapperSpy,
bleAdapterWrapperSpy,
queue,
adapterStateObservable.asObservable(),
Expand Down Expand Up @@ -108,6 +110,18 @@ class RxBleClientTest extends ElectricSpecification {
assert results.size() == 2
}

def "should return connected devices"() {
given:
bluetoothPeripheralConnected("AA:AA:AA:AA:AA:AA")
bluetoothPeripheralConnected("BB:BB:BB:BB:BB:BB")

when:
def results = objectUnderTest.getConnectedPeripherals()

then:
assert results.size() == 2
}

@Unroll
def "should call ScanPreconditionVerifier.verify() prior to queueing scan operation"() {
given:
Expand Down Expand Up @@ -483,6 +497,13 @@ class RxBleClientTest extends ElectricSpecification {
bleAdapterWrapperSpy.addBondedDevice(mock)
}

def bluetoothPeripheralConnected(String address) {
def mock = Mock(BluetoothDevice)
mock.getAddress() >> address
mock.hashCode() >> address.hashCode()
bluetoothManagerWrapperSpy.addConnectedPeripheral(mock)
}

def "should throw UnsupportedOperationException if .getBleDevice() is called on system that has no Bluetooth capabilities"() {

given:
Expand Down