From 600cfe7bf6fe6d24d25e6e6de8108cf1caea1fb0 Mon Sep 17 00:00:00 2001 From: Julian Falcionelli Date: Mon, 31 Dec 2018 10:50:19 +0100 Subject: [PATCH 1/2] Added Bluetooth Manager. --- app/src/main/AndroidManifest.xml | 7 + .../bluetooth/base/BluetoothConstants.java | 13 + .../base/BluetoothDeviceManager.java | 380 ++++++++++++++++++ .../bluetooth/base/BluetoothDeviceState.java | 19 + .../bluetooth/base/BluetoothManager.java | 50 +++ .../bluetooth/base/BluetoothManagerImpl.java | 320 +++++++++++++++ .../bluetooth/base/BluetoothState.java | 19 + .../bluetooth/base/BluetoothUtils.java | 48 +++ .../base/exceptions/BleException.java | 39 ++ .../bluetooth/base/model/BleOperation.java | 82 ++++ .../base/model/BleOperationType.java | 22 + .../MyBluetoothDevicesConstants.java | 16 + .../myDevice/MyOwnBluetoothDeviceManager.java | 11 + .../MyOwnBluetoothDeviceManagerImpl.java | 42 ++ .../exceptions/MyOwnBluetoothException.java | 14 + .../myapp/ui/util/RxSchedulersUtils.java | 91 +++++ 16 files changed, 1173 insertions(+) create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothConstants.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceManager.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceState.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManager.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothState.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/exceptions/BleException.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperationType.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManager.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManagerImpl.java create mode 100644 app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/exceptions/MyOwnBluetoothException.java diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 60c8217..7c47f96 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,6 +34,13 @@ + + + + + + + mBleOperations = new ArrayList<>(); + private BluetoothGatt mBtGatt; + private boolean mConnectionReady = false; + private boolean mBleOperationInProgress = false; + private BehaviorSubject> mBluetoothOperationIdPS = + BehaviorSubject.create(); + private BehaviorSubject mBluetoothOperationResultsPS = + BehaviorSubject.create(); + private BehaviorSubject mBluetoothDeviceStatusPS = BehaviorSubject.create(); + private BluetoothGattCallback mBluetoothGattCallback = new BluetoothGattCallback() { + + @Override + public void onCharacteristicWrite(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic, + int status) { + Log.d(TAG, "New CharacteristicWrite"); + + // Result of a characteristic write operation + if (status == BluetoothGatt.GATT_SUCCESS) { + mBluetoothOperationResultsPS.onNext(characteristic); + // TODO Handler Errors too (Maybe Object with all the Info ?) + } + + performNextOperation(); + } + + @Override + public void onCharacteristicRead(BluetoothGatt gatt, + BluetoothGattCharacteristic characteristic, + int status) { + Log.d(TAG, "New CharacteristicRead"); + + // Result of a characteristic read operation + if (status == BluetoothGatt.GATT_SUCCESS) { + mBluetoothOperationResultsPS.onNext(characteristic); + // TODO Handler Errors too (Maybe Object with all the Info ?) + } + + performNextOperation(); + } + + @Override + public void onDescriptorWrite(BluetoothGatt gatt, + BluetoothGattDescriptor descriptor, + int status) { + Log.d(TAG, "New DescriptorWrite"); + performNextOperation(); + } + + @Override + public void onDescriptorRead(BluetoothGatt gatt, + BluetoothGattDescriptor descriptor, + int status) { + Log.d(TAG, "New DescriptorRead"); + performNextOperation(); + } + + @Override + public void onConnectionStateChange(BluetoothGatt gatt, + int status, + int newState) { + Log.d(TAG, "onConnectionStateChange"); + switch (newState) { + case STATE_DISCONNECTED: + Log.d(TAG, "onConnectionStateChange STATE_DISCONNECTED"); + mBtGatt = null; + mConnectionReady = false; + mBleOperationInProgress = false; + mBluetoothDeviceStatusPS.onNext(BluetoothDeviceState.DISCONNECTED); + break; + case STATE_CONNECTED: + Log.d(TAG, "onConnectionStateChange STATE_CONNECTED"); + mBtGatt.discoverServices(); + mBluetoothDeviceStatusPS.onNext(BluetoothDeviceState.CONNECTED); + break; + default: + Log.d(TAG, "onConnectionStateChange OTHER"); + break; + } + } + + @Override + public void onServicesDiscovered(BluetoothGatt gatt, + int status) { + Log.d(TAG, "onServicesDiscovered"); + if (status == GATT_SUCCESS) { + mConnectionReady = true; + onBTServicesDiscovered(); + performNextOperation(); + } + } + }; + + @SuppressLint("CheckResult") + public BluetoothDeviceManager(BluetoothManager bluetoothManager, Context context, + String deviceMacAddress) { + mContext = context; + mDeviceMacAddress = deviceMacAddress; + mBluetoothManager = bluetoothManager; + + mBluetoothManager.observeBluetoothStatus() + .compose(RxSchedulersUtils.observeObservableOnIO()) + .subscribe(status -> { + if (status == BluetoothState.BLUETOOTH_OFF) { + clearStates(); + Log.d(TAG, "Bluetooth Status: " + String.valueOf(status)); + } + } + , error -> { + }); + } + + public Observable observeDeviceState() { + return mBluetoothDeviceStatusPS; + } + + public void dump() { + BluetoothDevice bluetoothDevice = getPairedDevice(mDeviceMacAddress); + + if (bluetoothDevice == null) { + return; // Nothing + } + + BluetoothUtils.dumpBluetoothDevice(bluetoothDevice); + } + + private BluetoothDevice getPairedDevice(String mac) { + for (BluetoothDevice bluetoothDevice : mBluetoothManager.getPairedDevices().blockingGet()) { + if (bluetoothDevice.getAddress().equals(mac)) { + return bluetoothDevice; + } + } + + return null; + } + + protected Completable write(UUID service, UUID charUuid, byte[] data, boolean highPriority) { + return checkConnection() + .andThen(Completable.fromAction(() -> { + addOperationToQueue( + BleOperation.newWriteOperation(service, charUuid, data, highPriority)); + checkQueue(); + })) + .subscribeOn(BLUETOOTH_SINGLE_SCHEDULER); + } + + private void doWrite(BleOperation bleOperation) { + BluetoothGattService gattService = mBtGatt.getService(bleOperation.getService()); + BluetoothGattCharacteristic characteristic = gattService.getCharacteristic( + bleOperation.getCharUuid()); + characteristic.setValue(bleOperation.getData()); + + if (mBtGatt.writeCharacteristic(characteristic)) { + Log.d(TAG, "Performing write"); + } else { + Log.d(TAG, "Couldn't perform write!"); + } + } + + protected Single read(UUID service, UUID charUuid) { + return read(service, charUuid, false); + } + + protected Single read(UUID service, UUID charUuid, + boolean highPriority) { + //TODO Replicate to Write Flow + BleOperation bleOperation = BleOperation.newReadOperation(service, charUuid, highPriority); + + return checkConnection() + .andThen(Completable.fromAction(() -> { + addOperationToQueue(bleOperation); + checkQueue(); + })) + .andThen(mBluetoothOperationIdPS + .filter(operationIds -> operationIds.first == bleOperation.getId()) + .firstOrError() + .flatMap(operationIds -> mBluetoothOperationResultsPS + .filter(bluetoothGattCharacteristic -> + bluetoothGattCharacteristic.getInstanceId() + == operationIds.second) + .doOnNext(resultPepe -> Log.i(TAG, + "New Read Result: " + resultPepe.toString())) + .firstOrError())) + .subscribeOn(BLUETOOTH_SINGLE_SCHEDULER); + } + + private void doRead(BleOperation bleOperation) { + BluetoothGattService gattService = mBtGatt.getService(bleOperation.getService()); + BluetoothGattCharacteristic characteristic = gattService.getCharacteristic( + bleOperation.getCharUuid()); + + //TODO Replicate to Write Flow + mBluetoothOperationIdPS.onNext( + new Pair<>(bleOperation.getId(), characteristic.getInstanceId())); + + if (mBtGatt.readCharacteristic(characteristic)) { + Log.d(TAG, "Performing read"); + } else { + Log.d(TAG, "Couldn't perform read!"); + } + } + + protected Completable subscribe(UUID service, UUID charUuid, boolean enable, + boolean highPriority) { + return checkConnection() + .andThen(Completable.fromAction(() -> { + addOperationToQueue( + BleOperation.newSubscribeOperation(service, charUuid, enable, + highPriority)); + checkQueue(); + })) + .subscribeOn(BLUETOOTH_SINGLE_SCHEDULER); + } + + private void doSubscribe(BleOperation bleOperation) { + Log.d(TAG, "doSubscribe"); + BluetoothGattService gattService = mBtGatt.getService(bleOperation.getService()); + BluetoothGattCharacteristic characteristic = gattService.getCharacteristic( + bleOperation.getCharUuid()); + if (mBtGatt.setCharacteristicNotification(characteristic, bleOperation.isEnable())) { + BluetoothGattDescriptor descriptor = characteristic.getDescriptor( + UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")); //TODO Check this + if (descriptor != null) { + byte[] value = + bleOperation.isEnable() ? BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE + : BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE; + descriptor.setValue(value); + + if (mBtGatt.writeDescriptor(descriptor)) { + Log.d(TAG, "Performing subscription"); + } else { + Log.d(TAG, "Couldn't perform subscription!"); + } + } + } + } + + private Completable checkConnection() { + return mBluetoothManager.turnOn() + .doOnError(error -> Log.d(TAG, "Error Turning ON BT")) + .andThen(Completable.fromAction(this::startConnection)); + } + + private synchronized void startConnection() + throws BleException.BluetoothDeviceUnpairedException { + if (mBtGatt == null) { + BluetoothDevice bluetoothDevice = getPairedDevice(mDeviceMacAddress); + if (bluetoothDevice == null) { // Device got unpaired + Log.d(TAG, "Device got unpaired"); + throw new BleException.BluetoothDeviceUnpairedException(); + } + + mBtGatt = bluetoothDevice.connectGatt(mContext, false, mBluetoothGattCallback); + } + } + + protected void onBTServicesDiscovered() { + // Do something ? + } + + private synchronized void addOperationToQueue(BleOperation bleOperation) { + int position = 0; + + for (int i = 0; i < mBleOperations.size(); i++) { + if (!mBleOperations.get(0).isHighPriority()) { // Keep High Priority Operations at top + break; + } + + position++; + } + + mBleOperations.add(position, bleOperation); + } + + private synchronized void checkQueue() { + if (!mBleOperationInProgress) { + performNextOperation(); + } + } + + @SuppressLint("CheckResult") + private synchronized void performNextOperation() { + if (!mConnectionReady) { + return; // Connection Not Ready + } + + if (mBleOperations.size() == 0) { + mBleOperationInProgress = false; + return; + } + + mBleOperationInProgress = true; + + Completable.fromAction(() -> performOperation(mBleOperations.remove(0))) + .subscribeOn(BLUETOOTH_SINGLE_SCHEDULER) + .subscribe( + () -> Log.d(TAG, "Performing BT Operation"), + error -> Log.w(TAG, "Error performing BT Operation") + ); + } + + private synchronized void performOperation(BleOperation bleOperation) { + switch (bleOperation.getType()) { + case TYPE_READ: + doRead(bleOperation); + break; + case TYPE_WRITE: + doWrite(bleOperation); + break; + case TYPE_SUBSCRIBE: + doSubscribe(bleOperation); + break; + } + } + + protected void clearStates() { + if (mBtGatt != null) { + mBtGatt.close(); + mBtGatt = null; + } + + mBleOperations = new ArrayList<>(); + mConnectionReady = false; + mBleOperationInProgress = false; + } +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceState.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceState.java new file mode 100644 index 0000000..b5f9b85 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceState.java @@ -0,0 +1,19 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import static co.lateralview.myapp.infraestructure.manager.bluetooth.base.BluetoothDeviceState + .CONNECTED; +import static co.lateralview.myapp.infraestructure.manager.bluetooth.base.BluetoothDeviceState + .DISCONNECTED; + +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; + +@Retention(SOURCE) +@IntDef({CONNECTED, DISCONNECTED}) +public @interface BluetoothDeviceState { + int CONNECTED = 0; + int DISCONNECTED = 1; +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManager.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManager.java new file mode 100644 index 0000000..9517f11 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManager.java @@ -0,0 +1,50 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base; + +import android.bluetooth.BluetoothDevice; + +import java.util.List; + +import io.reactivex.Completable; +import io.reactivex.Observable; +import io.reactivex.Single; + +/** + * BLE Generic Operations: + * - Turn On / Off + * - Discover Devices + * - Pairing / Unpairing + * + * Once you got your device paired you must use a BluetoothDeviceManager Instance to perform I/O + * events. + */ +public interface BluetoothManager { + // Status + Single getBluetoothStatus(); + + Observable observeBluetoothStatus(); + + // Turn On / Off + Completable turnOn(); + + Completable turnOff(); + + // Devices + Single> getPairedDevices(); + + // Discovery + Completable startDiscovery(); + + Completable stopDiscovery(); + + Observable observeBluetoothDiscovery(); + + // Actions + Completable pairDevice(BluetoothDevice bluetoothDevice); + + void unpair(String deviceMacAddress); + + Completable discoverAndPairDevice(String deviceMacAddress); + + // Stop / Clear states + void stop(); +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java new file mode 100644 index 0000000..b1719e5 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java @@ -0,0 +1,320 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base; + +import android.bluetooth.BluetoothAdapter; +import android.bluetooth.BluetoothDevice; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.util.Log; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import co.lateralview.myapp.infraestructure.manager.bluetooth.base.exceptions.BleException; +import io.reactivex.Completable; +import io.reactivex.Observable; +import io.reactivex.Single; +import io.reactivex.subjects.BehaviorSubject; +import io.reactivex.subjects.PublishSubject; + +public class BluetoothManagerImpl implements BluetoothManager { + private static final String TAG = "BluetoothManagerImpl"; + + // Forever PS + private PublishSubject mBluetoothStatusPS = PublishSubject.create(); + private final BroadcastReceiver mBluetoothStatusReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + + if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { + final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, + BluetoothAdapter.ERROR); + switch (state) { + case BluetoothAdapter.STATE_OFF: + mBluetoothStatusPS.onNext(BluetoothState.BLUETOOTH_OFF); + break; + case BluetoothAdapter.STATE_TURNING_OFF: + break; + case BluetoothAdapter.STATE_ON: + mBluetoothStatusPS.onNext(BluetoothState.BLUETOOTH_ON); + break; + case BluetoothAdapter.STATE_TURNING_ON: + break; + } + } + } + }; + private PublishSubject mBluetoothDeviceDiscoveryPS = + PublishSubject.create(); + private final BroadcastReceiver mBTDiscoveryReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + // When discovery finds a device + if (BluetoothDevice.ACTION_FOUND.equals(action)) { + // Get the BluetoothDevice object from the Intent + BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); + mBluetoothDeviceDiscoveryPS.onNext(device); + } + } + }; + // One Time PS + private BehaviorSubject mBluetoothDevicePairingPS; + private final BroadcastReceiver mBTPairingReceiver = new BroadcastReceiver() { + public void onReceive(Context context, Intent intent) { + String action = intent.getAction(); + // When discovery finds a device + if (BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)) { + + int state = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1); + + if (state == BluetoothDevice.BOND_BONDING) { + //bonding process is still working + //essentially this means that the Confirmation Dialog is still visible + return; // Do Nothing + } + + if (state == BluetoothDevice.BOND_BONDED) { + //bonding process was successful + //also means that the user pressed OK on the Dialog + + // Get the BluetoothDevice object from the Intent + BluetoothDevice device = intent.getParcelableExtra( + BluetoothDevice.EXTRA_DEVICE); + + mBluetoothDevicePairingPS.onNext(device); + + return; + } + + // Paired device not found means error/cancel during pairing process + mBluetoothDevicePairingPS.onError(new BleException.PairingToBTDeviceException()); + } + } + }; + + // ======== Start Bluetooth Status Related ======== + private Context mContext; + private boolean mDiscoveringReceiverRegistered = false, mPairingReceiverRegistered = false; + + public BluetoothManagerImpl(Context context) { + mContext = context; + registerToBluetoothChanges(); + } + + @Override + public Single getBluetoothStatus() { + return Single.fromCallable(() -> { + BluetoothAdapter mBluetoothAdapter = getBluetoothAdapter(); + if (mBluetoothAdapter == null) { + // Device does not support Bluetooth + throw new BleException.BluetoothNotSupportedException(); + } + + return mBluetoothAdapter.isEnabled() ? BluetoothState.BLUETOOTH_ON + : BluetoothState.BLUETOOTH_OFF; + }); + } + + @Override + public Observable observeBluetoothStatus() { + return mBluetoothStatusPS; + } + + @Override + public Completable turnOn() { + return Single.fromCallable(() -> { + BluetoothAdapter mBluetoothAdapter = getBluetoothAdapter(); + if (mBluetoothAdapter == null) { + // Device does not support Bluetooth + throw new BleException.BluetoothNotSupportedException(); + } + + if (!mBluetoothAdapter.isEnabled()) { + mBluetoothAdapter.enable(); // Works only with ADMIN BLUETOOTH permission. + return true; // Wait for connection, turn on can take a while. + } + + return false; + } + ).flatMapCompletable(waitForConnection -> { + if (waitForConnection) { + return mBluetoothStatusPS + .filter(status -> status == BluetoothState.BLUETOOTH_ON) + .firstOrError() + .ignoreElement(); + } else { + return Completable.complete(); + } + }); + } + + // ======== End Bluetooth Status Related ======== + + @Override + public Completable turnOff() { + return Completable.fromAction(() -> { + BluetoothAdapter mBluetoothAdapter = getBluetoothAdapter(); + if (mBluetoothAdapter == null) { + // Device does not support Bluetooth + throw new BleException.BluetoothNotSupportedException(); + } + + if (mBluetoothAdapter.isEnabled()) { + mBluetoothAdapter.disable(); + } + } + ); + } + + // ======== Start Pairing Related ======== + + @Override + public Single> getPairedDevices() { + return Single.fromCallable(() -> new ArrayList<>(getBluetoothPairedDevices())); + } + + @Override + public Completable pairDevice(BluetoothDevice bluetoothDevice) { + // Check if device is already paired + if (getPairedDevice(bluetoothDevice.getAddress()) != null) { + return Completable.complete(); + } + + mBluetoothDevicePairingPS = BehaviorSubject.create(); + + return mBluetoothDevicePairingPS + .firstOrError() + // Re-Check address just for case. + .filter(pairedBluetoothDevice -> pairedBluetoothDevice.getAddress() + .equals(bluetoothDevice.getAddress())) + .flatMapCompletable(__ -> Completable.complete()) + .doOnSubscribe(__ -> { + registerToBTPairingReceiver(); + bluetoothDevice.createBond(); + }); + } + + @Override + public Completable startDiscovery() { + return Completable.fromAction(() -> { + if (!getBluetoothAdapter().isDiscovering()) { + getBluetoothAdapter().startDiscovery(); + } + + registerToBTDiscoveryReceiver(); + }); + } + + @Override + public Completable stopDiscovery() { + return Completable.fromAction(() -> { + unregisterToBTDiscoveryReceiver(); + getBluetoothAdapter().cancelDiscovery(); + }); + } + + // ======== End Pairing Related ======== + + // ======== Start Discovery Related ======== + + @Override + public Observable observeBluetoothDiscovery() { + return mBluetoothDeviceDiscoveryPS; + } + + @Override + public void unpair(String deviceMacAddress) { + for (BluetoothDevice bluetoothDevice : getBluetoothPairedDevices()) { + if (bluetoothDevice.getAddress().equals(deviceMacAddress)) { + try { + Method m = bluetoothDevice.getClass() + .getMethod("removeBond", (Class[]) null); + m.invoke(bluetoothDevice, (Object[]) null); + } catch (Exception e) { + Log.d(TAG, "Removing has been failed.", e); + } + } + } + } + + @Override + public Completable discoverAndPairDevice(String deviceMacAddress) { + return stopDiscovery() + .andThen(startDiscovery()) + .andThen( + observeBluetoothDiscovery() + .filter(bluetoothDevice -> bluetoothDevice.getAddress().equals( + deviceMacAddress)) + .firstOrError() + .flatMapCompletable(this::pairDevice) + .doAfterTerminate(this::stopDiscovery)); + } + + @Override + public void stop() { + getBluetoothAdapter().cancelDiscovery(); + unregisterToBTDiscoveryReceiver(); + unregisterToBTPairingReceiver(); + } + + private void registerToBluetoothChanges() { + IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); + mContext.registerReceiver(mBluetoothStatusReceiver, filter); + } + + private void registerToBTPairingReceiver() { + if (!mPairingReceiverRegistered) { + IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED); + mContext.registerReceiver(mBTPairingReceiver, filter); + mPairingReceiverRegistered = true; + } + } + + // ======== End Discovery Related ======== + + private void unregisterToBTPairingReceiver() { + if (mPairingReceiverRegistered) { + mContext.unregisterReceiver(mBTPairingReceiver); + mPairingReceiverRegistered = false; + } + } + + private void registerToBTDiscoveryReceiver() { + IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); + mContext.registerReceiver(mBTDiscoveryReceiver, filter); + mDiscoveringReceiverRegistered = true; + } + + private void unregisterToBTDiscoveryReceiver() { + if (mDiscoveringReceiverRegistered) { + mContext.unregisterReceiver(mBTDiscoveryReceiver); + mDiscoveringReceiverRegistered = false; + } + } + + private Set getBluetoothPairedDevices() { + return getBluetoothAdapter().getBondedDevices(); + } + + protected BluetoothAdapter getBluetoothAdapter() { + return BluetoothAdapter.getDefaultAdapter(); + } + + private boolean isDevicePaired(String mac) { + return getPairedDevice(mac) != null; + } + + private BluetoothDevice getPairedDevice(String mac) { + for (BluetoothDevice bluetoothDevice : getBluetoothPairedDevices()) { + if (bluetoothDevice.getAddress().equals(mac)) { + return bluetoothDevice; + } + } + + return null; + } +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothState.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothState.java new file mode 100644 index 0000000..bed32ca --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothState.java @@ -0,0 +1,19 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import static co.lateralview.myapp.infraestructure.manager.bluetooth.base.BluetoothState + .BLUETOOTH_OFF; +import static co.lateralview.myapp.infraestructure.manager.bluetooth.base.BluetoothState + .BLUETOOTH_ON; + +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; + +@Retention(SOURCE) +@IntDef({BLUETOOTH_ON, BLUETOOTH_OFF}) +public @interface BluetoothState { + int BLUETOOTH_ON = 0; + int BLUETOOTH_OFF = 1; +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java new file mode 100644 index 0000000..ff49cd4 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java @@ -0,0 +1,48 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base; + +import android.bluetooth.BluetoothDevice; +import android.os.ParcelUuid; +import android.util.Log; + +public class BluetoothUtils { + public static final String TAG = "BluetoothUtils"; + private static final String LOG_SEPARATOR = "==========================================="; + private static final String LOG_NEW_LINE = "\n"; + private static final String LOG_ITEM_SEPARATOR = "----------"; + private BluetoothUtils() { + + } + + public static void dumpBluetoothDevice(BluetoothDevice bluetoothDevice) { + StringBuilder stringBuilder = new StringBuilder(); + + stringBuilder.append(LOG_SEPARATOR); + stringBuilder.append("Dumping Bluetooth Device Data"); + stringBuilder.append(LOG_NEW_LINE); + stringBuilder.append("Mac Address: " + bluetoothDevice.getAddress()); + stringBuilder.append(LOG_NEW_LINE); + stringBuilder.append("Name: " + bluetoothDevice.getName()); + stringBuilder.append(LOG_NEW_LINE); + stringBuilder.append(LOG_ITEM_SEPARATOR); + stringBuilder.append(LOG_NEW_LINE); + + stringBuilder.append("List Of Services: "); + stringBuilder.append(LOG_NEW_LINE); + stringBuilder.append(LOG_NEW_LINE); + + ParcelUuid[] uuids = bluetoothDevice.getUuids(); + + if (uuids != null) { + for (ParcelUuid parcelUuid : bluetoothDevice.getUuids()) { + stringBuilder.append("Service: " + parcelUuid.getUuid().toString()); + stringBuilder.append(LOG_NEW_LINE); + } + } + + stringBuilder.append(LOG_NEW_LINE); + stringBuilder.append(LOG_SEPARATOR); + stringBuilder.append(LOG_NEW_LINE); + + Log.d(TAG, stringBuilder.toString()); + } +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/exceptions/BleException.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/exceptions/BleException.java new file mode 100644 index 0000000..90ea0d5 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/exceptions/BleException.java @@ -0,0 +1,39 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base.exceptions; + +public class BleException extends Exception { + + public BleException(String message) { + super(message); + } + + public static class BluetoothDeviceUnpairedException extends BleException { + public BluetoothDeviceUnpairedException() { + super("The requested device got unpaired."); + } + } + + public static class BluetoothNotEnabledException extends BleException { + public BluetoothNotEnabledException() { + super("Bluetooth is Off."); + } + } + + public static class BluetoothAccessNotGrantedException extends BleException { + public BluetoothAccessNotGrantedException() { + super("Bluetooth access not granted."); + } + } + + public static class BluetoothNotSupportedException extends BleException { + public BluetoothNotSupportedException() { + super("The current device doesn't support Bluetooth."); + } + } + + public static class PairingToBTDeviceException extends BleException { + public PairingToBTDeviceException() { + super("Couldn't pair to the selected Bluetooth device. Check if it is in pairing " + + "mode and in the appropriate range."); + } + } +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java new file mode 100644 index 0000000..46c7092 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java @@ -0,0 +1,82 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base.model; + +import java.util.UUID; + +public class BleOperation { + private static int sTemporaryId = 0; + + /** + * Identify temporarily the BLE Operation until we get the final Characteristic Instance ID. + */ + private int id; + + private UUID service; + private UUID charUuid; + + // Only used for characteristic write + private byte[] data; + + // Only used for characteristic notification subscription + private boolean enable; + + @BleOperationType + private int type; + + private boolean highPriority = false; + + private BleOperation(UUID service, UUID charUuid, byte[] data, boolean enable, int type, + boolean highPriority) { + this.id = sTemporaryId++; + this.service = service; + this.charUuid = charUuid; + this.data = data; + this.enable = enable; + this.type = type; + this.highPriority = highPriority; + } + + public static BleOperation newWriteOperation(UUID service, UUID charUuid, byte[] data, + boolean highPriority) { + return new BleOperation(service, charUuid, data, false, BleOperationType.TYPE_WRITE, + highPriority); + } + + public static BleOperation newReadOperation(UUID service, UUID charUuid, boolean highPriority) { + return new BleOperation(service, charUuid, null, false, BleOperationType.TYPE_READ, + highPriority); + } + + public static BleOperation newSubscribeOperation(UUID service, UUID charUuid, boolean enable, + boolean highPriority) { + return new BleOperation(service, charUuid, null, enable, BleOperationType.TYPE_SUBSCRIBE, + highPriority); + } + + public int getId() { + return id; + } + + public UUID getService() { + return service; + } + + public UUID getCharUuid() { + return charUuid; + } + + public byte[] getData() { + return data; + } + + public boolean isEnable() { + return enable; + } + + public int getType() { + return type; + } + + public boolean isHighPriority() { + return highPriority; + } +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperationType.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperationType.java new file mode 100644 index 0000000..f190c8b --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperationType.java @@ -0,0 +1,22 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.base.model; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import static co.lateralview.myapp.infraestructure.manager.bluetooth.base.model.BleOperationType + .TYPE_READ; +import static co.lateralview.myapp.infraestructure.manager.bluetooth.base.model.BleOperationType + .TYPE_SUBSCRIBE; +import static co.lateralview.myapp.infraestructure.manager.bluetooth.base.model.BleOperationType + .TYPE_WRITE; + +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; + +@Retention(SOURCE) +@IntDef({TYPE_SUBSCRIBE, TYPE_READ, TYPE_WRITE}) +public @interface BleOperationType { + int TYPE_SUBSCRIBE = 0; + int TYPE_READ = 1; + int TYPE_WRITE = 2; +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java new file mode 100644 index 0000000..79bff00 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java @@ -0,0 +1,16 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.myBtDevices; + +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class MyBluetoothDevicesConstants { + public final static List DEVICES_SUPPORTED = Arrays.asList("My Own BT Device V1", + "My Own BT Device V2"); + + public final static String MY_OWN_DEVICE_SERVICE = "52401523-f97c-7f90-0e7f-6c6f4e36db1c"; + public final static String WRITE_READ_ID = "52401524-f97c-7f90-0e7f-6c6f4e36db1c"; + + public final static UUID UUID_MY_OWN_DEVICE_SERVICE = UUID.fromString(MY_OWN_DEVICE_SERVICE); + public final static UUID UUID_WRITE_READ_ID = UUID.fromString(WRITE_READ_ID); +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManager.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManager.java new file mode 100644 index 0000000..bfd78c5 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManager.java @@ -0,0 +1,11 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.myBtDevices.devices.myDevice; + +import io.reactivex.Completable; +import io.reactivex.Single; + +public interface MyOwnBluetoothDeviceManager { + // Operations + Completable writeInt(int value); + + Single readValue(int id); +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManagerImpl.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManagerImpl.java new file mode 100644 index 0000000..2d7a1d8 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/devices/myDevice/MyOwnBluetoothDeviceManagerImpl.java @@ -0,0 +1,42 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.myBtDevices.devices.myDevice; + + +import static co.lateralview.myapp.infraestructure.manager.bluetooth.myBtDevices + .MyBluetoothDevicesConstants.UUID_MY_OWN_DEVICE_SERVICE; +import static co.lateralview.myapp.infraestructure.manager.bluetooth.myBtDevices + .MyBluetoothDevicesConstants.UUID_WRITE_READ_ID; + +import android.content.Context; + +import co.lateralview.myapp.infraestructure.manager.bluetooth.base.BluetoothDeviceManager; +import co.lateralview.myapp.infraestructure.manager.bluetooth.base.BluetoothManager; +import io.reactivex.Completable; +import io.reactivex.Single; + +public class MyOwnBluetoothDeviceManagerImpl extends BluetoothDeviceManager implements + MyOwnBluetoothDeviceManager { + private static final String TAG = "MyOwnBluetoothDeviceManagerImpl"; + + public MyOwnBluetoothDeviceManagerImpl(BluetoothManager bluetoothManager, Context context, + String deviceMacAddress) { + super(bluetoothManager, context, deviceMacAddress); + } + + @Override + public Completable writeInt(int value) { + // Create the packet according your needs + byte[] packet = new byte[90]; + packet[0] = (byte) value; + + return write(UUID_MY_OWN_DEVICE_SERVICE, UUID_WRITE_READ_ID, packet, false); + } + + @Override + public Single readValue(int id) { + // Create the packet according your needs + + return read(UUID_MY_OWN_DEVICE_SERVICE, UUID_WRITE_READ_ID, true) + // TODO Get Value from BluetoothGattCharacteristic + .map(bluetoothGattCharacteristic -> bluetoothGattCharacteristic.getStringValue(0)); + } +} diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/exceptions/MyOwnBluetoothException.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/exceptions/MyOwnBluetoothException.java new file mode 100644 index 0000000..ea09281 --- /dev/null +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/exceptions/MyOwnBluetoothException.java @@ -0,0 +1,14 @@ +package co.lateralview.myapp.infraestructure.manager.bluetooth.myBtDevices.exceptions; + +public class MyOwnBluetoothException extends Exception { + + public MyOwnBluetoothException(String message) { + super(message); + } + + public static class DeviceNotSupportedException extends MyOwnBluetoothException { + public DeviceNotSupportedException() { + super("The selected device is not in the whitelist of supported devices."); + } + } +} diff --git a/app/src/main/java/co/lateralview/myapp/ui/util/RxSchedulersUtils.java b/app/src/main/java/co/lateralview/myapp/ui/util/RxSchedulersUtils.java index 9842c4a..5eb1ff8 100644 --- a/app/src/main/java/co/lateralview/myapp/ui/util/RxSchedulersUtils.java +++ b/app/src/main/java/co/lateralview/myapp/ui/util/RxSchedulersUtils.java @@ -1,11 +1,15 @@ package co.lateralview.myapp.ui.util; +import java.util.List; + import io.reactivex.CompletableTransformer; import io.reactivex.MaybeTransformer; import io.reactivex.ObservableTransformer; import io.reactivex.SingleTransformer; import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.CompositeDisposable; +import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; public final class RxSchedulersUtils { @@ -33,4 +37,91 @@ public static CompletableTransformer applyCompletableSchedulers() { return upstream -> upstream.subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()); } + + // Useful methods to quickly dispose subscriptions + + public static void safeDispose(CompositeDisposable compositeDisposable) { + if (compositeDisposable != null && !compositeDisposable.isDisposed()) { + compositeDisposable.dispose(); + } + } + + public static void safeDispose(Disposable disposable) { + if (disposable != null && !disposable.isDisposed()) { + disposable.dispose(); + } + } + + public static void safeDispose(List disposableList) { + if (disposableList != null && !disposableList.isEmpty()) { + for (Disposable disposable : disposableList) { + disposable.dispose(); + } + } + } + + // Observe observable stream in the UI Thread + + public static ObservableTransformer observeObservableOnUi() { + return upstream -> upstream.observeOn(AndroidSchedulers.mainThread()); + } + + public static MaybeTransformer observeMaybeOnUi() { + return upstream -> upstream.observeOn(AndroidSchedulers.mainThread()); + } + + public static SingleTransformer observeSingleOnUi() { + return upstream -> upstream.observeOn(AndroidSchedulers.mainThread()); + } + + public static CompletableTransformer observeCompletableOnUi() { + return upstream -> upstream.observeOn(AndroidSchedulers.mainThread()); + } + + // Observe observable stream in the IO Thread in case we don't need to update the UI + + public static ObservableTransformer observeObservableOnIO() { + return upstream -> upstream.observeOn(Schedulers.io()); + } + + public static MaybeTransformer observeMaybeOnIO() { + return upstream -> upstream.observeOn(Schedulers.io()); + } + + public static SingleTransformer observeSingleOnIO() { + return upstream -> upstream.observeOn(Schedulers.io()); + } + + public static CompletableTransformer observeCompletableOnIO() { + return upstream -> upstream.observeOn(Schedulers.io()); + } + + // Subscribe observable on IO Thread to not block UI Thread + + public static ObservableTransformer subscribeObservableOnIO() { + return upstream -> upstream.subscribeOn(Schedulers.io()); + } + + public static MaybeTransformer subscribeMaybeOnIO() { + return upstream -> upstream.subscribeOn(Schedulers.io()); + } + + public static SingleTransformer subscribeSingleOnIO() { + return upstream -> upstream.subscribeOn(Schedulers.io()); + } + + public static CompletableTransformer subscribeCompletableOnIO() { + return upstream -> upstream.subscribeOn(Schedulers.io()); + } + + // Subscribe observable on Single Thread to not block UI Thread and run them sequentially + + + public static SingleTransformer subscribeSingleOnSingle() { + return upstream -> upstream.subscribeOn(Schedulers.single()); + } + + public static CompletableTransformer subscribeCompletableOnSingle() { + return upstream -> upstream.subscribeOn(Schedulers.single()); + } } From 8690b386b9dc269134d61a8b71f346b411701ad4 Mon Sep 17 00:00:00 2001 From: Julian Falcionelli Date: Mon, 31 Dec 2018 11:22:20 +0100 Subject: [PATCH 2/2] Style fixes --- .../bluetooth/base/BluetoothConstants.java | 8 ++++++-- .../bluetooth/base/BluetoothDeviceManager.java | 13 ++++++------- .../bluetooth/base/BluetoothManagerImpl.java | 4 +++- .../manager/bluetooth/base/BluetoothUtils.java | 3 ++- .../bluetooth/base/model/BleOperation.java | 2 +- .../MyBluetoothDevicesConstants.java | 17 +++++++++++------ 6 files changed, 29 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothConstants.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothConstants.java index a055836..7393bb6 100644 --- a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothConstants.java +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothConstants.java @@ -2,11 +2,15 @@ import android.Manifest; -public class BluetoothConstants { +public final class BluetoothConstants { + + private BluetoothConstants() { + + } public static final int GET_FIRST_8_BITS = 0xFF; - public final static String[] REQUIRED_PERMISSIONS = new String[]{ + public static final String[] REQUIRED_PERMISSIONS = new String[]{ Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION }; diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceManager.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceManager.java index 7d672d1..86c1c0e 100644 --- a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceManager.java +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothDeviceManager.java @@ -155,13 +155,12 @@ public BluetoothDeviceManager(BluetoothManager bluetoothManager, Context context mBluetoothManager.observeBluetoothStatus() .compose(RxSchedulersUtils.observeObservableOnIO()) .subscribe(status -> { - if (status == BluetoothState.BLUETOOTH_OFF) { - clearStates(); - Log.d(TAG, "Bluetooth Status: " + String.valueOf(status)); - } - } - , error -> { - }); + if (status == BluetoothState.BLUETOOTH_OFF) { + clearStates(); + Log.d(TAG, "Bluetooth Status: " + String.valueOf(status)); + } + }, error -> { + }); } public Observable observeDeviceState() { diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java index b1719e5..a0195c1 100644 --- a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothManagerImpl.java @@ -97,8 +97,10 @@ public void onReceive(Context context, Intent intent) { }; // ======== Start Bluetooth Status Related ======== + private Context mContext; - private boolean mDiscoveringReceiverRegistered = false, mPairingReceiverRegistered = false; + private boolean mDiscoveringReceiverRegistered = false; + private boolean mPairingReceiverRegistered = false; public BluetoothManagerImpl(Context context) { mContext = context; diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java index ff49cd4..b8e3061 100644 --- a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/BluetoothUtils.java @@ -4,11 +4,12 @@ import android.os.ParcelUuid; import android.util.Log; -public class BluetoothUtils { +public final class BluetoothUtils { public static final String TAG = "BluetoothUtils"; private static final String LOG_SEPARATOR = "==========================================="; private static final String LOG_NEW_LINE = "\n"; private static final String LOG_ITEM_SEPARATOR = "----------"; + private BluetoothUtils() { } diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java index 46c7092..bfb78e2 100644 --- a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/base/model/BleOperation.java @@ -2,7 +2,7 @@ import java.util.UUID; -public class BleOperation { +public final class BleOperation { private static int sTemporaryId = 0; /** diff --git a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java index 79bff00..2954ad0 100644 --- a/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java +++ b/app/src/main/java/co/lateralview/myapp/infraestructure/manager/bluetooth/myBtDevices/MyBluetoothDevicesConstants.java @@ -4,13 +4,18 @@ import java.util.List; import java.util.UUID; -public class MyBluetoothDevicesConstants { - public final static List DEVICES_SUPPORTED = Arrays.asList("My Own BT Device V1", +public final class MyBluetoothDevicesConstants { + + private MyBluetoothDevicesConstants() { + + } + + public static final List DEVICES_SUPPORTED = Arrays.asList("My Own BT Device V1", "My Own BT Device V2"); - public final static String MY_OWN_DEVICE_SERVICE = "52401523-f97c-7f90-0e7f-6c6f4e36db1c"; - public final static String WRITE_READ_ID = "52401524-f97c-7f90-0e7f-6c6f4e36db1c"; + private static final String MY_OWN_DEVICE_SERVICE = "52401523-f97c-7f90-0e7f-6c6f4e36db1c"; + private static final String WRITE_READ_ID = "52401524-f97c-7f90-0e7f-6c6f4e36db1c"; - public final static UUID UUID_MY_OWN_DEVICE_SERVICE = UUID.fromString(MY_OWN_DEVICE_SERVICE); - public final static UUID UUID_WRITE_READ_ID = UUID.fromString(WRITE_READ_ID); + public static final UUID UUID_MY_OWN_DEVICE_SERVICE = UUID.fromString(MY_OWN_DEVICE_SERVICE); + public static final UUID UUID_WRITE_READ_ID = UUID.fromString(WRITE_READ_ID); }