diff --git a/app/build.gradle b/app/build.gradle
index 06f63ffb..1de1f496 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -54,6 +54,9 @@ dependencies {
// add it as a module into the project structure and uncomment the following line (and also the according lines in the settings.gradle):
// implementation project(':dfu')
+ // Import the BLE Library
+ implementation project(':ble')
+
implementation('org.simpleframework:simple-xml:2.7.1') {
exclude group: 'stax', module: 'stax-api'
exclude group: 'xpp3', module: 'xpp3'
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/PermissionRationaleFragment.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/PermissionRationaleFragment.java
index b1418c5e..cd8c5409 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/PermissionRationaleFragment.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/PermissionRationaleFragment.java
@@ -23,7 +23,6 @@ package no.nordicsemi.android.nrftoolbox;
import android.app.Dialog;
import android.content.Context;
-import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMActivity.java
index 74976617..7d4f9f3e 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMActivity.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMActivity.java
@@ -28,8 +28,8 @@ import android.widget.TextView;
import java.util.Calendar;
import java.util.UUID;
+import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.nrftoolbox.R;
-import no.nordicsemi.android.nrftoolbox.profile.BleManager;
import no.nordicsemi.android.nrftoolbox.profile.BleProfileActivity;
// TODO The BPMActivity should be rewritten to use the service approach, like other do.
diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMManager.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMManager.java
index 88586ffe..a93aad9b 100644
--- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMManager.java
+++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/bpm/BPMManager.java
@@ -31,10 +31,10 @@ import java.util.Deque;
import java.util.LinkedList;
import java.util.UUID;
+import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.parser.BloodPressureMeasurementParser;
import no.nordicsemi.android.nrftoolbox.parser.IntermediateCuffPressureParser;
-import no.nordicsemi.android.nrftoolbox.profile.BleManager;
public class BPMManager extends BleManager The BleManager is responsible for managing the low level communication with a Bluetooth Smart device. Please see profiles implementation for an example of use.
- * This base manager has been tested against number of devices and samples from Nordic SDK. The manager handles connection events and initializes the device after establishing the connection.
- *
- *
The manager also is responsible for parsing the Battery Level values and calling {@link BleManagerCallbacks#onBatteryValueReceived(BluetoothDevice, int)} method.
Events from all profiles are being logged into the nRF Logger application, - * which may be downloaded from Google Play: https://play.google.com/store/apps/details?id=no.nordicsemi.android.log
- *The nRF Logger application allows you to see application logs without need to connect it to the computer.
- * - * @paramtrue. The first connection attempt is done with autoConnect
- * flag set to false (to make the first connection quick) but on connection lost the manager will call {@link #connect(BluetoothDevice)} again.
- * This time this method will call {@link BluetoothGatt#connect()} which always uses autoConnect equal true.
- */
- private boolean mInitialConnection;
- /** Flag set to true when the device is connected. */
- private boolean mConnected;
- private int mConnectionState = BluetoothGatt.STATE_DISCONNECTED;
- /** Last received battery value or -1 if value wasn't received. */
- private int mBatteryValue = -1;
-
- private final BroadcastReceiver mBluetoothStateBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(final Context context, final Intent intent) {
- final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF);
- final int previousState = intent.getIntExtra(BluetoothAdapter.EXTRA_PREVIOUS_STATE, BluetoothAdapter.STATE_OFF);
-
- final String stateString = "[Broadcast] Action received: " + BluetoothAdapter.ACTION_STATE_CHANGED + ", state changed to " + state2String(state);
- Logger.d(mLogSession, stateString);
-
- switch (state) {
- case BluetoothAdapter.STATE_TURNING_OFF:
- case BluetoothAdapter.STATE_OFF:
- if (mConnected && previousState != BluetoothAdapter.STATE_TURNING_OFF && previousState != BluetoothAdapter.STATE_OFF) {
- // The connection is killed by the system, no need to gently disconnect
- mGattCallback.notifyDeviceDisconnected(mBluetoothDevice);
- }
- // Calling close() will prevent the STATE_OFF event from being logged (this receiver will be unregistered). But it doesn't matter.
- close();
- break;
- }
- }
-
- private String state2String(final int state) {
- switch (state) {
- case BluetoothAdapter.STATE_TURNING_ON:
- return "TURNING ON";
- case BluetoothAdapter.STATE_ON:
- return "ON";
- case BluetoothAdapter.STATE_TURNING_OFF:
- return "TURNING OFF";
- case BluetoothAdapter.STATE_OFF:
- return "OFF";
- default:
- return "UNKNOWN (" + state + ")";
- }
- }
- };
-
- private BroadcastReceiver mBondingBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(final Context context, final Intent intent) {
- final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- final int bondState = intent.getIntExtra(BluetoothDevice.EXTRA_BOND_STATE, -1);
- final int previousBondState = intent.getIntExtra(BluetoothDevice.EXTRA_PREVIOUS_BOND_STATE, -1);
-
- // Skip other devices
- if (mBluetoothGatt == null || !device.getAddress().equals(mBluetoothGatt.getDevice().getAddress()))
- return;
-
- Logger.d(mLogSession, "[Broadcast] Action received: " + BluetoothDevice.ACTION_BOND_STATE_CHANGED + ", bond state changed to: " + bondStateToString(bondState) + " (" + bondState + ")");
- DebugLogger.i(TAG, "Bond state changed for: " + device.getName() + " new state: " + bondState + " previous: " + previousBondState);
-
- switch (bondState) {
- case BluetoothDevice.BOND_BONDING:
- mCallbacks.onBondingRequired(device);
- break;
- case BluetoothDevice.BOND_BONDED:
- Logger.i(mLogSession, "Device bonded");
- mCallbacks.onBonded(device);
-
- // Start initializing again.
- // In fact, bonding forces additional, internal service discovery (at least on Nexus devices), so this method may safely be used to start this process again.
- Logger.v(mLogSession, "Discovering Services...");
- Logger.d(mLogSession, "gatt.discoverServices()");
- mBluetoothGatt.discoverServices();
- break;
- }
- }
- };
-
- private final BroadcastReceiver mPairingRequestBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(final Context context, final Intent intent) {
- final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-
- // Skip other devices
- if (mBluetoothGatt == null || !device.getAddress().equals(mBluetoothGatt.getDevice().getAddress()))
- return;
-
- // String values are used as the constants are not available for Android 4.3.
- final int variant = intent.getIntExtra("android.bluetooth.device.extra.PAIRING_VARIANT"/*BluetoothDevice.EXTRA_PAIRING_VARIANT*/, 0);
- Logger.d(mLogSession, "[Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST"/*BluetoothDevice.ACTION_PAIRING_REQUEST*/ +
- ", pairing variant: " + pairingVariantToString(variant) + " (" + variant + ")");
-
- // The API below is available for Android 4.4 or newer.
-
- // An app may set the PIN here or set pairing confirmation (depending on the variant) using:
- // device.setPin(new byte[] { '1', '2', '3', '4', '5', '6' });
- // device.setPairingConfirmation(true);
- }
- };
-
- public BleManager(final Context context) {
- mContext = context;
- mHandler = new Handler();
- }
-
- /**
- * Returns the context that the manager was created with.
- *
- * @return the context
- */
- protected Context getContext() {
- return mContext;
- }
-
- /**
- * This method must return the gatt callback used by the manager.
- * This method must not create a new gatt callback each time it is being invoked, but rather return a single object.
- *
- * @return the gatt callback object
- */
- protected abstract BleManagerGattCallback getGattCallback();
-
- /**
- * Returns whether to connect to the remote device just once (false) or to add the address to white list of devices
- * that will be automatically connect as soon as they become available (true). In the latter case, if
- * Bluetooth adapter is enabled, Android scans periodically for devices from the white list and if a advertising packet
- * is received from such, it tries to connect to it. When the connection is lost, the system will keep trying to reconnect
- * to it in. If true is returned, and the connection to the device is lost the {@link BleManagerCallbacks#onLinklossOccur(BluetoothDevice)}
- * callback is called instead of {@link BleManagerCallbacks#onDeviceDisconnected(BluetoothDevice)}.
- * This feature works much better on newer Android phone models and many not work on older phones.
- *This method should only be used with bonded devices, as otherwise the device may change it's address. - * It will however work also with non-bonded devices with private static address. A connection attempt to - * a device with private resolvable address will fail.
- *The first connection to a device will always be created with autoConnect flag to false - * (see {@link BluetoothDevice#connectGatt(Context, boolean, BluetoothGattCallback)}). This is to make it quick as the - * user most probably waits for a quick response. However, if this method returned true during first connection and the link was lost, - * the manager will try to reconnect to it using {@link BluetoothGatt#connect()} which forces autoConnect to true .
- * - * @return autoConnect flag value - */ - protected boolean shouldAutoConnect() { - return false; - } - - /** - * Connects to the Bluetooth Smart device. - * - * @param device a device to connect to - */ - public void connect(final BluetoothDevice device) { - if (mConnected) - return; - - synchronized (mLock) { - if (mBluetoothGatt != null) { - // There are 2 ways of reconnecting to the same device: - // 1. Reusing the same BluetoothGatt object and calling connect() - this will force the autoConnect flag to true - // 2. Closing it and reopening a new instance of BluetoothGatt object. - // The gatt.close() is an asynchronous method. It requires some time before it's finished and - // device.connectGatt(...) can't be called immediately or service discovery - // may never finish on some older devices (Nexus 4, Android 5.0.1). - // If shouldAutoConnect() method returned false we can't call gatt.connect() and have to close gatt and open it again. - if (!mInitialConnection) { - Logger.d(mLogSession, "gatt.close()"); - mBluetoothGatt.close(); - mBluetoothGatt = null; - try { - Logger.d(mLogSession, "wait(200)"); - Thread.sleep(200); // Is 200 ms enough? - } catch (final InterruptedException e) { - // Ignore - } - } else { - // Instead, the gatt.connect() method will be used to reconnect to the same device. - // This method forces autoConnect = true even if the gatt was created with this flag set to false. - mInitialConnection = false; - Logger.v(mLogSession, "Connecting..."); - mConnectionState = BluetoothGatt.STATE_CONNECTING; - mCallbacks.onDeviceConnecting(device); - Logger.d(mLogSession, "gatt.connect()"); - mBluetoothGatt.connect(); - return; - } - } else { - // Register bonding broadcast receiver - mContext.registerReceiver(mBluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); - mContext.registerReceiver(mBondingBroadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED)); - mContext.registerReceiver(mPairingRequestBroadcastReceiver, new IntentFilter("android.bluetooth.device.action.PAIRING_REQUEST"/*BluetoothDevice.ACTION_PAIRING_REQUEST*/)); - } - } - - final boolean shouldAutoConnect = shouldAutoConnect(); - mUserDisconnected = !shouldAutoConnect; // We will receive Linkloss events only when the device is connected with autoConnect=true - // The first connection will always be done with autoConnect = false to make the connection quick. - // If the shouldAutoConnect() method returned true, the manager will automatically try to reconnect to this device on link loss. - if (shouldAutoConnect) - mInitialConnection = true; - mBluetoothDevice = device; - Logger.v(mLogSession, "Connecting..."); - mConnectionState = BluetoothGatt.STATE_CONNECTING; - mCallbacks.onDeviceConnecting(device); - Logger.d(mLogSession, "gatt = device.connectGatt(autoConnect = false)"); - mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback = getGattCallback()); - } - - /** - * Disconnects from the device or cancels the pending connection attempt. Does nothing if device was not connected. - * @return true if device is to be disconnected. False if it was already disconnected. - */ - public boolean disconnect() { - mUserDisconnected = true; - mInitialConnection = false; - - if (mBluetoothGatt != null) { - mConnectionState = BluetoothGatt.STATE_DISCONNECTING; - Logger.v(mLogSession, mConnected ? "Disconnecting..." : "Cancelling connection..."); - mCallbacks.onDeviceDisconnecting(mBluetoothGatt.getDevice()); - final boolean wasConnected = mConnected; - Logger.d(mLogSession, "gatt.disconnect()"); - mBluetoothGatt.disconnect(); - - if (!wasConnected) { - // There will be no callback, the connection attempt will be stopped - mConnectionState = BluetoothGatt.STATE_DISCONNECTED; - Logger.i(mLogSession, "Disconnected"); - mCallbacks.onDeviceDisconnected(mBluetoothGatt.getDevice()); - } - return true; - } - return false; - } - - /** - * This method returns true if the device is connected. Services could have not been discovered yet. - */ - public boolean isConnected() { - return mConnected; - } - - /** - * Method returns the connection state: - * {@link BluetoothGatt#STATE_CONNECTING STATE_CONNECTING}, - * {@link BluetoothGatt#STATE_CONNECTED STATE_CONNECTED}, - * {@link BluetoothGatt#STATE_DISCONNECTING STATE_DISCONNECTING}, - * {@link BluetoothGatt#STATE_DISCONNECTED STATE_DISCONNECTED} - * @return the connection state - */ - public int getConnectionState() { - return mConnectionState; - } - - /** - * Returns the last received value of Battery Level characteristic, or -1 if such does not exist, hasn't been read or notification wasn't received yet. - * @return the last battery level value in percent - */ - public int getBatteryValue() { - return mBatteryValue; - } - - /** - * Closes and releases resources. May be also used to unregister broadcast listeners. - */ - public void close() { - try { - mContext.unregisterReceiver(mBluetoothStateBroadcastReceiver); - mContext.unregisterReceiver(mBondingBroadcastReceiver); - mContext.unregisterReceiver(mPairingRequestBroadcastReceiver); - } catch (Exception e) { - // the receiver must have been not registered or unregistered before - } - synchronized (mLock) { - if (mBluetoothGatt != null) { - Logger.d(mLogSession, "gatt.close()"); - mBluetoothGatt.close(); - mBluetoothGatt = null; - } - mConnected = false; - mInitialConnection = false; - mConnectionState = BluetoothGatt.STATE_DISCONNECTED; - mGattCallback = null; - mBluetoothDevice = null; - } - } - - /** - * Sets the optional log session. This session will be used to log Bluetooth events. - * The logs may be viewed using the nRF Logger application: https://play.google.com/store/apps/details?id=no.nordicsemi.android.log - * Since nRF Logger Library v2.0 an app may define it's own log provider. Use {@link BleProfileServiceReadyActivity#getLocalAuthorityLogger()} to define local log URI. - * NOTE: nRF Logger must be installed prior to nRF Toolbox as it defines the required permission which is used by nRF Toolbox. - * - * @param session the session, or null if nRF Logger is not installed. - */ - public void setLogger(final ILogSession session) { - mLogSession = session; - } - - @Override - public void log(final int level, final String message) { - Logger.log(mLogSession, level, message); - } - - @Override - public void log(final int level, @StringRes final int messageRes, final Object... params) { - Logger.log(mLogSession, level, messageRes, params); - } - - /** - * Sets the manager callback listener - * - * @param callbacks the callback listener - */ - public void setGattCallbacks(E callbacks) { - mCallbacks = callbacks; - } - - /** - * Enqueues creating bond request to the queue. - * @return true if request has been enqueued, false if the device has not been connected - */ - protected final boolean createBond() { - return enqueue(Request.createBond()); - } - - /** - * Creates a bond with the device. The device must be first set using {@link #connect(BluetoothDevice)} which will - * try to connect to the device. If you need to pair with a device before connecting to it you may do it without - * the use of BleManager object and connect after bond is established. - * @return true if pairing has started, false if it was already paired or an immediate error occur. - */ - private boolean internalCreateBond() { - final BluetoothDevice device = mBluetoothDevice; - if (device == null) - return false; - - if (device.getBondState() == BluetoothDevice.BOND_BONDED) { - Logger.v(mLogSession, "Create bond request on already bonded device..."); - Logger.i(mLogSession, "Device bonded"); - return false; - } - - Logger.v(mLogSession, "Starting pairing..."); - - boolean result = false; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - Logger.d(mLogSession, "device.createBond()"); - result = device.createBond(); - } else { - /* - * There is a createBond() method in BluetoothDevice class but for now it's hidden. We will call it using reflections. It has been revealed in KitKat (Api19) - */ - try { - final Method createBond = device.getClass().getMethod("createBond"); - if (createBond != null) { - Logger.d(mLogSession, "device.createBond() (hidden)"); - result = (Boolean) createBond.invoke(device); - } - } catch (final Exception e) { - Log.w(TAG, "An exception occurred while creating bond", e); - } - } - - if (!result) - Log.w(TAG, "Creating bond failed"); - return result; - } - - /** - * When the device is bonded and has the Generic Attribute service and the Service Changed characteristic this method enables indications on this characteristic. - * In case one of the requirements is not fulfilled this method returnsfalse.
- *
- * @return true when the request has been sent, false when the device is not bonded, does not have the Generic Attribute service, the GA service does not have
- * the Service Changed characteristic or this characteristic does not have the CCCD.
- */
- private boolean ensureServiceChangedEnabled() {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null)
- return false;
-
- // The Service Changed indications have sense only on bonded devices
- final BluetoothDevice device = gatt.getDevice();
- if (device.getBondState() != BluetoothDevice.BOND_BONDED)
- return false;
-
- final BluetoothGattService gaService = gatt.getService(GENERIC_ATTRIBUTE_SERVICE);
- if (gaService == null)
- return false;
-
- final BluetoothGattCharacteristic scCharacteristic = gaService.getCharacteristic(SERVICE_CHANGED_CHARACTERISTIC);
- if (scCharacteristic == null)
- return false;
-
- Logger.i(mLogSession, "Service Changed characteristic found on a bonded device");
- return internalEnableIndications(scCharacteristic);
- }
-
- /**
- * Enables notifications on given characteristic.
- *
- * @return true is the request has been enqueued
- */
- protected final boolean enableNotifications(final BluetoothGattCharacteristic characteristic) {
- return enqueue(Request.newEnableNotificationsRequest(characteristic));
- }
-
- private boolean internalEnableNotifications(final BluetoothGattCharacteristic characteristic) {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null || characteristic == null)
- return false;
-
- // Check characteristic property
- final int properties = characteristic.getProperties();
- if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0)
- return false;
-
- Logger.d(mLogSession, "gatt.setCharacteristicNotification(" + characteristic.getUuid() + ", true)");
- gatt.setCharacteristicNotification(characteristic, true);
- final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
- if (descriptor != null) {
- descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
- Logger.v(mLogSession, "Enabling notifications for " + characteristic.getUuid());
- Logger.d(mLogSession, "gatt.writeDescriptor(" + CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID + ", value=0x01-00)");
- return internalWriteDescriptorWorkaround(descriptor);
- }
- return false;
- }
-
- /**
- * Enables indications on given characteristic.
- *
- * @return true is the request has been enqueued
- */
- protected final boolean enableIndications(final BluetoothGattCharacteristic characteristic) {
- return enqueue(Request.newEnableIndicationsRequest(characteristic));
- }
-
- private boolean internalEnableIndications(final BluetoothGattCharacteristic characteristic) {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null || characteristic == null)
- return false;
-
- // Check characteristic property
- final int properties = characteristic.getProperties();
- if ((properties & BluetoothGattCharacteristic.PROPERTY_INDICATE) == 0)
- return false;
-
- Logger.d(mLogSession, "gatt.setCharacteristicNotification(" + characteristic.getUuid() + ", true)");
- gatt.setCharacteristicNotification(characteristic, true);
- final BluetoothGattDescriptor descriptor = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
- if (descriptor != null) {
- descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
- Logger.v(mLogSession, "Enabling indications for " + characteristic.getUuid());
- Logger.d(mLogSession, "gatt.writeDescriptor(" + CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID + ", value=0x02-00)");
- return internalWriteDescriptorWorkaround(descriptor);
- }
- return false;
- }
-
- /**
- * Sends the read request to the given characteristic.
- *
- * @param characteristic the characteristic to read
- * @return true if request has been enqueued
- */
- protected final boolean readCharacteristic(final BluetoothGattCharacteristic characteristic) {
- return enqueue(Request.newReadRequest(characteristic));
- }
-
- private boolean internalReadCharacteristic(final BluetoothGattCharacteristic characteristic) {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null || characteristic == null)
- return false;
-
- // Check characteristic property
- final int properties = characteristic.getProperties();
- if ((properties & BluetoothGattCharacteristic.PROPERTY_READ) == 0)
- return false;
-
- Logger.v(mLogSession, "Reading characteristic " + characteristic.getUuid());
- Logger.d(mLogSession, "gatt.readCharacteristic(" + characteristic.getUuid() + ")");
- return gatt.readCharacteristic(characteristic);
- }
-
- /**
- * Writes the characteristic value to the given characteristic.
- *
- * @param characteristic the characteristic to write to
- * @return true if request has been enqueued
- */
- protected final boolean writeCharacteristic(final BluetoothGattCharacteristic characteristic) {
- return enqueue(Request.newWriteRequest(characteristic, characteristic.getValue()));
- }
-
- private boolean internalWriteCharacteristic(final BluetoothGattCharacteristic characteristic) {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null || characteristic == null)
- return false;
-
- // Check characteristic property
- final int properties = characteristic.getProperties();
- if ((properties & (BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) == 0)
- return false;
-
- Logger.v(mLogSession, "Writing characteristic " + characteristic.getUuid() + " (" + getWriteType(characteristic.getWriteType()) + ")");
- Logger.d(mLogSession, "gatt.writeCharacteristic(" + characteristic.getUuid() + ")");
- return gatt.writeCharacteristic(characteristic);
- }
-
- /**
- * Sends the read request to the given descriptor.
- *
- * @param descriptor the descriptor to read
- * @return true if request has been enqueued
- */
- protected final boolean readDescriptor(final BluetoothGattDescriptor descriptor) {
- return enqueue(Request.newReadRequest(descriptor));
- }
-
- private boolean internalReadDescriptor(final BluetoothGattDescriptor descriptor) {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null || descriptor == null)
- return false;
-
- Logger.v(mLogSession, "Reading descriptor " + descriptor.getUuid());
- Logger.d(mLogSession, "gatt.readDescriptor(" + descriptor.getUuid() + ")");
- return gatt.readDescriptor(descriptor);
- }
-
- /**
- * Writes the descriptor value to the given descriptor.
- *
- * @param descriptor the descriptor to write to
- * @return true if request has been enqueued
- */
- protected final boolean writeDescriptor(final BluetoothGattDescriptor descriptor) {
- return enqueue(Request.newWriteRequest(descriptor, descriptor.getValue()));
- }
-
- private boolean internalWriteDescriptor(final BluetoothGattDescriptor descriptor) {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null || descriptor == null)
- return false;
-
- Logger.v(mLogSession, "Writing descriptor " + descriptor.getUuid());
- Logger.d(mLogSession, "gatt.writeDescriptor(" + descriptor.getUuid() + ")");
- return internalWriteDescriptorWorkaround(descriptor);
- }
-
- /**
- * Reads the battery level from the device.
- *
- * @return true if request has been enqueued
- */
- public final boolean readBatteryLevel() {
- return enqueue(Request.newReadBatteryLevelRequest());
- }
-
- private boolean internalReadBatteryLevel() {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null)
- return false;
-
- final BluetoothGattService batteryService = gatt.getService(BATTERY_SERVICE);
- if (batteryService == null)
- return false;
-
- final BluetoothGattCharacteristic batteryLevelCharacteristic = batteryService.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC);
- if (batteryLevelCharacteristic == null)
- return false;
-
- // Check characteristic property
- final int properties = batteryLevelCharacteristic.getProperties();
- if ((properties & BluetoothGattCharacteristic.PROPERTY_READ) == 0)
- return false;
-
- Logger.a(mLogSession, "Reading battery level...");
- return internalReadCharacteristic(batteryLevelCharacteristic);
- }
-
- /**
- * This method tries to enable notifications on the Battery Level characteristic.
- *
- * @param enable true to enable battery notifications, false to disable
- * @return true if request has been enqueued
- */
- public final boolean setBatteryNotifications(final boolean enable) {
- if (enable)
- return enqueue(Request.newEnableBatteryLevelNotificationsRequest());
- else
- return enqueue(Request.newDisableBatteryLevelNotificationsRequest());
- }
-
- private boolean internalSetBatteryNotifications(final boolean enable) {
- final BluetoothGatt gatt = mBluetoothGatt;
- if (gatt == null) {
- return false;
- }
-
- final BluetoothGattService batteryService = gatt.getService(BATTERY_SERVICE);
- if (batteryService == null)
- return false;
-
- final BluetoothGattCharacteristic batteryLevelCharacteristic = batteryService.getCharacteristic(BATTERY_LEVEL_CHARACTERISTIC);
- if (batteryLevelCharacteristic == null)
- return false;
-
- // Check characteristic property
- final int properties = batteryLevelCharacteristic.getProperties();
- if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) == 0)
- return false;
-
- gatt.setCharacteristicNotification(batteryLevelCharacteristic, enable);
- final BluetoothGattDescriptor descriptor = batteryLevelCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID);
- if (descriptor != null) {
- if (enable) {
- descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
- Logger.a(mLogSession, "Enabling battery level notifications...");
- Logger.v(mLogSession, "Enabling notifications for " + BATTERY_LEVEL_CHARACTERISTIC);
- Logger.d(mLogSession, "gatt.writeDescriptor(" + CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID + ", value=0x0100)");
- } else {
- descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
- Logger.a(mLogSession, "Disabling battery level notifications...");
- Logger.v(mLogSession, "Disabling notifications for " + BATTERY_LEVEL_CHARACTERISTIC);
- Logger.d(mLogSession, "gatt.writeDescriptor(" + CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID + ", value=0x0000)");
- }
- return internalWriteDescriptorWorkaround(descriptor);
- }
- return false;
- }
-
- /**
- * There was a bug in Android up to 6.0 where the descriptor was written using parent
- * characteristic's write type, instead of always Write With Response, as the spec says.
- * - * See: - * https://android.googlesource.com/platform/frameworks/base/+/942aebc95924ab1e7ea1e92aaf4e7fc45f695a6c%5E%21/#F0 - *
- * @param descriptor the descriptor to be written - * @return the result of {@link BluetoothGatt#writeDescriptor(BluetoothGattDescriptor)} - */ - private boolean internalWriteDescriptorWorkaround(final BluetoothGattDescriptor descriptor) { - final BluetoothGatt gatt = mBluetoothGatt; - if (gatt == null || descriptor == null) - return false; - - final BluetoothGattCharacteristic parentCharacteristic = descriptor.getCharacteristic(); - final int originalWriteType = parentCharacteristic.getWriteType(); - parentCharacteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT); - final boolean result = gatt.writeDescriptor(descriptor); - parentCharacteristic.setWriteType(originalWriteType); - return result; - } - - /** - * Enqueues a new request. The request will be handled immediately if there is no operation in progress, - * or automatically after the last enqueued one will finish. - *This method should be used to read and write data from the target device as it ensures that the last operation has finished - * before a new one will be called.
- * @param request new request to be added to the queue. - * @return true if request has been enqueued, false if the {@link #connect(BluetoothDevice)} method was not called before, - * or the manager was closed using {@link #close()}. - */ - public boolean enqueue(final Request request) { - if (mGattCallback != null) { - // Add the new task to the end of the queue - mGattCallback.mTaskQueue.add(request); - mGattCallback.nextRequest(); - return true; - } - return false; - } - - /** - * On Android, when multiple BLE operations needs to be done, it is required to wait for a proper - * {@link android.bluetooth.BluetoothGattCallback BluetoothGattCallback} callback before calling - * another operation. In order to make BLE operations easier the BleManager allows to enqueue a request - * containing all data necessary for a given operation. Requests are performed one after another until the - * queue is empty. Use static methods from below to instantiate a request and then enqueue them using {@link #enqueue(Request)}. - */ - protected static final class Request { - private enum Type { - CREATE_BOND, - WRITE, - READ, - WRITE_DESCRIPTOR, - READ_DESCRIPTOR, - ENABLE_NOTIFICATIONS, - ENABLE_INDICATIONS, - READ_BATTERY_LEVEL, - ENABLE_BATTERY_LEVEL_NOTIFICATIONS, - DISABLE_BATTERY_LEVEL_NOTIFICATIONS, - ENABLE_SERVICE_CHANGED_INDICATIONS, - } - - private final Type type; - private final BluetoothGattCharacteristic characteristic; - private final BluetoothGattDescriptor descriptor; - private final byte[] value; - private final int writeType; - - private Request(final Type type) { - this.type = type; - this.characteristic = null; - this.descriptor = null; - this.value = null; - this.writeType = 0; - } - - private Request(final Type type, final BluetoothGattCharacteristic characteristic) { - this.type = type; - this.characteristic = characteristic; - this.descriptor = null; - this.value = null; - this.writeType = 0; - } - - private Request(final Type type, final BluetoothGattCharacteristic characteristic, final int writeType, final byte[] value, final int offset, final int length) { - this.type = type; - this.characteristic = characteristic; - this.descriptor = null; - this.value = copy(value, offset, length); - this.writeType = writeType; - } - - private Request(final Type type, final BluetoothGattDescriptor descriptor) { - this.type = type; - this.characteristic = null; - this.descriptor = descriptor; - this.value = null; - this.writeType = 0; - } - - private Request(final Type type, final BluetoothGattDescriptor descriptor, final byte[] value, final int offset, final int length) { - this.type = type; - this.characteristic = null; - this.descriptor = descriptor; - this.value = copy(value, offset, length); - this.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT; - } - - private static byte[] copy(final byte[] value, final int offset, final int length) { - if (value == null || offset > value.length) - return null; - final int maxLength = Math.min(value.length - offset, length); - final byte[] copy = new byte[maxLength]; - System.arraycopy(value, offset, copy, 0, maxLength); - return copy; - } - - /** - * Creates a new request that will start pairing with the device. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request createBond() { - return new Request(Type.CREATE_BOND); - } - - /** - * Creates new Read Characteristic request. The request will not be executed if given characteristic - * is null or does not have READ property. After the operation is complete a proper callback will be invoked. - * @param characteristic characteristic to be read - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newReadRequest(final BluetoothGattCharacteristic characteristic) { - return new Request(Type.READ, characteristic); - } - - /** - * Creates new Write Characteristic request. The request will not be executed if given characteristic - * is null or does not have WRITE property. After the operation is complete a proper callback will be invoked. - * @param characteristic characteristic to be written - * @param value value to be written. The array is copied into another buffer so it's safe to reuse the array again. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newWriteRequest(final BluetoothGattCharacteristic characteristic, final byte[] value) { - return new Request(Type.WRITE, characteristic, characteristic.getWriteType(), value, 0, value != null ? value.length : 0); - } - - /** - * Creates new Write Characteristic request. The request will not be executed if given characteristic - * is null or does not have WRITE property. After the operation is complete a proper callback will be invoked. - * @param characteristic characteristic to be written - * @param value value to be written. The array is copied into another buffer so it's safe to reuse the array again. - * @param writeType write type to be used, one of {@link BluetoothGattCharacteristic#WRITE_TYPE_DEFAULT}, {@link BluetoothGattCharacteristic#WRITE_TYPE_NO_RESPONSE}. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newWriteRequest(final BluetoothGattCharacteristic characteristic, final byte[] value, final int writeType) { - return new Request(Type.WRITE, characteristic, writeType, value, 0, value != null ? value.length : 0); - } - - /** - * Creates new Write Characteristic request. The request will not be executed if given characteristic - * is null or does not have WRITE property. After the operation is complete a proper callback will be invoked. - * @param characteristic characteristic to be written - * @param value value to be written. The array is copied into another buffer so it's safe to reuse the array again. - * @param offset the offset from which value has to be copied - * @param length number of bytes to be copied from the value buffer - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newWriteRequest(final BluetoothGattCharacteristic characteristic, final byte[] value, final int offset, final int length) { - return new Request(Type.WRITE, characteristic, characteristic.getWriteType(), value, offset, length); - } - - /** - * Creates new Write Characteristic request. The request will not be executed if given characteristic - * is null or does not have WRITE property. After the operation is complete a proper callback will be invoked. - * @param characteristic characteristic to be written - * @param value value to be written. The array is copied into another buffer so it's safe to reuse the array again. - * @param offset the offset from which value has to be copied - * @param length number of bytes to be copied from the value buffer - * @param writeType write type to be used, one of {@link BluetoothGattCharacteristic#WRITE_TYPE_DEFAULT}, {@link BluetoothGattCharacteristic#WRITE_TYPE_NO_RESPONSE}. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newWriteRequest(final BluetoothGattCharacteristic characteristic, final byte[] value, final int offset, final int length, final int writeType) { - return new Request(Type.WRITE, characteristic, writeType, value, offset, length); - } - - /** - * Creates new Read Descriptor request. The request will not be executed if given descriptor - * is null. After the operation is complete a proper callback will be invoked. - * @param descriptor descriptor to be read - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newReadRequest(final BluetoothGattDescriptor descriptor) { - return new Request(Type.READ_DESCRIPTOR, descriptor); - } - - /** - * Creates new Write Descriptor request. The request will not be executed if given descriptor - * is null. After the operation is complete a proper callback will be invoked. - * @param descriptor descriptor to be written - * @param value value to be written. The array is copied into another buffer so it's safe to reuse the array again. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newWriteRequest(final BluetoothGattDescriptor descriptor, final byte[] value) { - return new Request(Type.WRITE_DESCRIPTOR, descriptor, value, 0, value != null ? value.length : 0); - } - - /** - * Creates new Write Descriptor request. The request will not be executed if given descriptor - * is null. After the operation is complete a proper callback will be invoked. - * @param descriptor descriptor to be written - * @param value value to be written. The array is copied into another buffer so it's safe to reuse the array again. - * @param offset the offset from which value has to be copied - * @param length number of bytes to be copied from the value buffer - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newWriteRequest(final BluetoothGattDescriptor descriptor, final byte[] value, final int offset, final int length) { - return new Request(Type.WRITE_DESCRIPTOR, descriptor, value, offset, length); - } - - /** - * Creates new Enable Notification request. The request will not be executed if given characteristic - * is null, does not have NOTIFY property or the CCCD. After the operation is complete a proper callback will be invoked. - * @param characteristic characteristic to have notifications enabled - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newEnableNotificationsRequest(final BluetoothGattCharacteristic characteristic) { - return new Request(Type.ENABLE_NOTIFICATIONS, characteristic); - } - - /** - * Creates new Enable Indications request. The request will not be executed if given characteristic - * is null, does not have INDICATE property or the CCCD. After the operation is complete a proper callback will be invoked. - * @param characteristic characteristic to have indications enabled - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newEnableIndicationsRequest(final BluetoothGattCharacteristic characteristic) { - return new Request(Type.ENABLE_INDICATIONS, characteristic); - } - - /** - * Reads the first found Battery Level characteristic value from the first found Battery Service. - * If any of them is not found, or the characteristic does not have the READ property this operation will not execute. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newReadBatteryLevelRequest() { - return new Request(Type.READ_BATTERY_LEVEL); // the first Battery Level char from the first Battery Service is used - } - - /** - * Enables notifications on the first found Battery Level characteristic from the first found Battery Service. - * If any of them is not found, or the characteristic does not have the NOTIFY property this operation will not execute. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newEnableBatteryLevelNotificationsRequest() { - return new Request(Type.ENABLE_BATTERY_LEVEL_NOTIFICATIONS); // the first Battery Level char from the first Battery Service is used - } - - /** - * Disables notifications on the first found Battery Level characteristic from the first found Battery Service. - * If any of them is not found, or the characteristic does not have the NOTIFY property this operation will not execute. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - public static Request newDisableBatteryLevelNotificationsRequest() { - return new Request(Type.DISABLE_BATTERY_LEVEL_NOTIFICATIONS); // the first Battery Level char from the first Battery Service is used - } - - /** - * Enables indications on Service Changed characteristic if such exists in the Generic Attribute service. - * It is required to enable those notifications on bonded devices on older Android versions to be - * informed about attributes changes. Android 7+ (or 6+) handles this automatically and no action is required. - * @return the new request that can be enqueued using {@link #enqueue(Request)} method. - */ - private static Request newEnableServiceChangedIndicationsRequest() { - return new Request(Type.ENABLE_SERVICE_CHANGED_INDICATIONS); // the only Service Changed char is used (if such exists) - } - } - - protected abstract class BleManagerGattCallback extends BluetoothGattCallback { - private final static String ERROR_CONNECTION_STATE_CHANGE = "Error on connection state change"; - private final static String ERROR_DISCOVERY_SERVICE = "Error on discovering services"; - private final static String ERROR_AUTH_ERROR_WHILE_BONDED = "Phone has lost bonding information"; - private final static String ERROR_READ_CHARACTERISTIC = "Error on reading characteristic"; - private final static String ERROR_WRITE_CHARACTERISTIC = "Error on writing characteristic"; - private final static String ERROR_READ_DESCRIPTOR = "Error on reading descriptor"; - private final static String ERROR_WRITE_DESCRIPTOR = "Error on writing descriptor"; - - private final Queuetrue when the gatt device supports the required services.
- *
- * @param gatt the gatt device with services discovered
- * @return true when the device has teh required service
- */
- protected abstract boolean isRequiredServiceSupported(final BluetoothGatt gatt);
-
- /**
- * This method should return true when the gatt device supports the optional services.
- * The default implementation returns false.
- *
- * @param gatt the gatt device with services discovered
- * @return true when the device has teh optional service
- */
- protected boolean isOptionalServiceSupported(final BluetoothGatt gatt) {
- return false;
- }
-
- /**
- * This method should return a list of requests needed to initialize the profile.
- * Enabling Service Change indications for bonded devices and reading the Battery Level value and enabling Battery Level notifications
- * is handled before executing this queue. The queue should not have requests that are not available, e.g. should not
- * read an optional service when it is not supported by the connected device.
- * This method is called when the services has been discovered and the device is supported (has required service).
- * - * @param gatt the gatt device with services discovered - * @return the queue of requests - */ - protected abstract DequeIf this callback is invoked while a reliable write transaction is - * in progress, the value of the characteristic represents the value - * reported by the remote device. An application should compare this - * value to the desired value to be written. If the values don't match, - * the application must abort the reliable write transaction. - * - * @param gatt GATT client - * @param characteristic Characteristic that was written to the associated remote device. - */ - protected void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { - // do nothing - } - - /** - * Callback reporting the result of a descriptor read operation. - * - * @param gatt GATT client - * @param descriptor Descriptor that was read from the associated remote device. - */ - protected void onDescriptorRead(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor) { - // do nothing - } - - /** - * Callback indicating the result of a descriptor write operation. - *
If this callback is invoked while a reliable write transaction is in progress, - * the value of the characteristic represents the value reported by the remote device. - * An application should compare this value to the desired value to be written. - * If the values don't match, the application must abort the reliable write transaction. - * - * @param gatt GATT client - * @param descriptor Descriptor that was written to the associated remote device. - */ - protected void onDescriptorWrite(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor) { - // do nothing - } - - /** - * Callback reporting the value of Battery Level characteristic which could have - * been received by Read or Notify operations. - * - * @param gatt GATT client - * @param value the battery value in percent - */ - protected void onBatteryValueReceived(final BluetoothGatt gatt, final int value) { - // do nothing - } - - /** - * Callback indicating a notification has been received. - * @param gatt GATT client - * @param characteristic Characteristic from which the notification came. - */ - protected void onCharacteristicNotified(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { - // do nothing - } - - /** - * Callback indicating an indication has been received. - * @param gatt GATT client - * @param characteristic Characteristic from which the indication came. - */ - protected void onCharacteristicIndicated(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { - // do nothing - } - - private void onError(final BluetoothDevice device, final String message, final int errorCode) { - Logger.e(mLogSession, "Error (0x" + Integer.toHexString(errorCode) + "): " + GattError.parse(errorCode)); - mCallbacks.onError(device, message, errorCode); - } - - @Override - public final void onConnectionStateChange(final BluetoothGatt gatt, final int status, final int newState) { - Logger.d(mLogSession, "[Callback] Connection state changed with status: " + status + " and new state: " + newState + " (" + stateToString(newState) + ")"); - - if (status == BluetoothGatt.GATT_SUCCESS && newState == BluetoothProfile.STATE_CONNECTED) { - // Notify the parent activity/service - Logger.i(mLogSession, "Connected to " + gatt.getDevice().getAddress()); - mConnected = true; - mConnectionState = BluetoothGatt.STATE_CONNECTED; - mCallbacks.onDeviceConnected(gatt.getDevice()); - - /* - * The onConnectionStateChange event is triggered just after the Android connects to a device. - * In case of bonded devices, the encryption is reestablished AFTER this callback is called. - * Moreover, when the device has Service Changed indication enabled, and the list of services has changed (e.g. using the DFU), - * the indication is received few hundred milliseconds later, depending on the connection interval. - * When received, Android will start performing a service discovery operation on its own, internally, - * and will NOT notify the app that services has changed. - * - * If the gatt.discoverServices() method would be invoked here with no delay, if would return cached services, - * as the SC indication wouldn't be received yet. - * Therefore we have to postpone the service discovery operation until we are (almost, as there is no such callback) sure, - * that it has been handled. - * TODO: Please calculate the proper delay that will work in your solution. - * It should be greater than the time from LLCP Feature Exchange to ATT Write for Service Change indication. - * If your device does not use Service Change indication (for example does not have DFU) the delay may be 0. - */ - final boolean bonded = gatt.getDevice().getBondState() == BluetoothDevice.BOND_BONDED; - final int delay = bonded ? 1600 : 0; // around 1600 ms is required when connection interval is ~45ms. - if (delay > 0) - Logger.d(mLogSession, "wait(" + delay + ")"); - mHandler.postDelayed(() -> { - // Some proximity tags (e.g. nRF PROXIMITY) initialize bonding automatically when connected. - if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_BONDING) { - Logger.v(mLogSession, "Discovering Services..."); - Logger.d(mLogSession, "gatt.discoverServices()"); - gatt.discoverServices(); - } - }, delay); - } else { - if (newState == BluetoothProfile.STATE_DISCONNECTED) { - if (status != BluetoothGatt.GATT_SUCCESS) - Logger.w(mLogSession, "Error: (0x" + Integer.toHexString(status) + "): " + GattError.parseConnectionError(status)); - - mOperationInProgress = true; // no more calls are possible - mInitQueue = null; - mTaskQueue.clear(); - final boolean wasConnected = mConnected; - // if (mConnected) { // Checking mConnected prevents from calling onDeviceDisconnected if connection attempt failed. This check is not necessary - notifyDeviceDisconnected(gatt.getDevice()); // This sets the mConnected flag to false - // } - // Try to reconnect if the initial connection was lost because of a link loss or timeout, and shouldAutoConnect() returned true during connection attempt. - // This time it will set the autoConnect flag to true (gatt.connect() forces autoConnect true) - if (mInitialConnection) { - connect(gatt.getDevice()); - } - - if (wasConnected || status == BluetoothGatt.GATT_SUCCESS) - return; - } else { - if (status != BluetoothGatt.GATT_SUCCESS) - Logger.e(mLogSession, "Error (0x" + Integer.toHexString(status) + "): " + GattError.parseConnectionError(status)); - } - mCallbacks.onError(gatt.getDevice(), ERROR_CONNECTION_STATE_CHANGE, status); - } - } - - @Override - public final void onServicesDiscovered(final BluetoothGatt gatt, final int status) { - if (status == BluetoothGatt.GATT_SUCCESS) { - Logger.i(mLogSession, "Services Discovered"); - if (isRequiredServiceSupported(gatt)) { - Logger.v(mLogSession, "Primary service found"); - final boolean optionalServicesFound = isOptionalServiceSupported(gatt); - if (optionalServicesFound) - Logger.v(mLogSession, "Secondary service found"); - - // Notify the parent activity - mCallbacks.onServicesDiscovered(gatt.getDevice(), optionalServicesFound); - - // Obtain the queue of initialization requests - mInitInProgress = true; - mInitQueue = initGatt(gatt); - - // Before we start executing the initialization queue some other tasks need to be done. - if (mInitQueue == null) - mInitQueue = new LinkedList<>(); - - // Note, that operations are added in reverse order to the front of the queue. - - // 3. Enable Battery Level notifications if required (if this char. does not exist, this operation will be skipped) - if (mCallbacks.shouldEnableBatteryLevelNotifications(gatt.getDevice())) - mInitQueue.addFirst(Request.newEnableBatteryLevelNotificationsRequest()); - // 2. Read Battery Level characteristic (if such does not exist, this will be skipped) - mInitQueue.addFirst(Request.newReadBatteryLevelRequest()); - // 1. On devices running Android 4.3-6.0 the Service Changed characteristic needs to be enabled by the app (for bonded devices) - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) - mInitQueue.addFirst(Request.newEnableServiceChangedIndicationsRequest()); - - mOperationInProgress = false; - nextRequest(); - } else { - Logger.w(mLogSession, "Device is not supported"); - mCallbacks.onDeviceNotSupported(gatt.getDevice()); - disconnect(); - } - } else { - DebugLogger.e(TAG, "onServicesDiscovered error " + status); - onError(gatt.getDevice(), ERROR_DISCOVERY_SERVICE, status); - } - } - - @Override - public final void onCharacteristicRead(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) { - if (status == BluetoothGatt.GATT_SUCCESS) { - Logger.i(mLogSession, "Read Response received from " + characteristic.getUuid() + ", value: " + ParserUtils.parse(characteristic)); - - if (isBatteryLevelCharacteristic(characteristic)) { - final int batteryValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0); - Logger.a(mLogSession, "Battery level received: " + batteryValue + "%"); - mBatteryValue = batteryValue; - onBatteryValueReceived(gatt, batteryValue); - mCallbacks.onBatteryValueReceived(gatt.getDevice(), batteryValue); - } else { - // The value has been read. Notify the manager and proceed with the initialization queue. - onCharacteristicRead(gatt, characteristic); - } - } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { - if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) { - // This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352 - DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED); - mCallbacks.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status); - } - } else { - DebugLogger.e(TAG, "onCharacteristicRead error " + status); - onError(gatt.getDevice(), ERROR_READ_CHARACTERISTIC, status); - } - mOperationInProgress = false; - nextRequest(); - } - - @Override - public final void onCharacteristicWrite(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic, final int status) { - if (status == BluetoothGatt.GATT_SUCCESS) { - Logger.i(mLogSession, "Data written to " + characteristic.getUuid() + ", value: " + ParserUtils.parse(characteristic)); - // The value has been written. Notify the manager and proceed with the initialization queue. - onCharacteristicWrite(gatt, characteristic); - } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { - if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) { - // This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352 - DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED); - mCallbacks.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status); - } - } else { - DebugLogger.e(TAG, "onCharacteristicWrite error " + status); - onError(gatt.getDevice(), ERROR_WRITE_CHARACTERISTIC, status); - } - mOperationInProgress = false; - nextRequest(); - } - - @Override - public void onDescriptorRead(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final int status) { - if (status == BluetoothGatt.GATT_SUCCESS) { - Logger.i(mLogSession, "Read Response received from descr. " + descriptor.getUuid() + ", value: " + ParserUtils.parse(descriptor)); - - // The value has been read. Notify the manager and proceed with the initialization queue. - onDescriptorRead(gatt, descriptor); - } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { - if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) { - // This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352 - DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED); - mCallbacks.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status); - } - } else { - DebugLogger.e(TAG, "onDescriptorRead error " + status); - onError(gatt.getDevice(), ERROR_READ_DESCRIPTOR, status); - } - mOperationInProgress = false; - nextRequest(); - } - - @Override - public final void onDescriptorWrite(final BluetoothGatt gatt, final BluetoothGattDescriptor descriptor, final int status) { - if (status == BluetoothGatt.GATT_SUCCESS) { - Logger.i(mLogSession, "Data written to descr. " + descriptor.getUuid() + ", value: " + ParserUtils.parse(descriptor)); - - if (isServiceChangedCCCD(descriptor)) { - Logger.a(mLogSession, "Service Changed notifications enabled"); - } else if (isBatteryLevelCCCD(descriptor)) { - final byte[] value = descriptor.getValue(); - if (value != null && value.length == 2 && value[1] == 0x00) { - if (value[0] == 0x01) { - Logger.a(mLogSession, "Battery Level notifications enabled"); - } else { - Logger.a(mLogSession, "Battery Level notifications disabled"); - } - } else { - onDescriptorWrite(gatt, descriptor); - } - } else if (isCCCD(descriptor)) { - final byte[] value = descriptor.getValue(); - if (value != null && value.length == 2 && value[1] == 0x00) { - switch (value[0]) { - case 0x00: - Logger.a(mLogSession, "Notifications and indications disabled"); - break; - case 0x01: - Logger.a(mLogSession, "Notifications enabled"); - break; - case 0x02: - Logger.a(mLogSession, "Indications enabled"); - break; - } - } else { - onDescriptorWrite(gatt, descriptor); - } - } else { - onDescriptorWrite(gatt, descriptor); - } - } else if (status == BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION) { - if (gatt.getDevice().getBondState() != BluetoothDevice.BOND_NONE) { - // This should never happen but it used to: http://stackoverflow.com/a/20093695/2115352 - DebugLogger.w(TAG, ERROR_AUTH_ERROR_WHILE_BONDED); - mCallbacks.onError(gatt.getDevice(), ERROR_AUTH_ERROR_WHILE_BONDED, status); - } - } else { - DebugLogger.e(TAG, "onDescriptorWrite error " + status); - onError(gatt.getDevice(), ERROR_WRITE_DESCRIPTOR, status); - } - mOperationInProgress = false; - nextRequest(); - } - - @Override - public final void onCharacteristicChanged(final BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { - final String data = ParserUtils.parse(characteristic); - - if (isBatteryLevelCharacteristic(characteristic)) { - Logger.i(mLogSession, "Notification received from " + characteristic.getUuid() + ", value: " + data); - final int batteryValue = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 0); - Logger.a(mLogSession, "Battery level received: " + batteryValue + "%"); - mBatteryValue = batteryValue; - onBatteryValueReceived(gatt, batteryValue); - mCallbacks.onBatteryValueReceived(gatt.getDevice(), batteryValue); - } else { - final BluetoothGattDescriptor cccd = characteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID); - final boolean notifications = cccd == null || cccd.getValue() == null || cccd.getValue().length != 2 || cccd.getValue()[0] == 0x01; - - if (notifications) { - Logger.i(mLogSession, "Notification received from " + characteristic.getUuid() + ", value: " + data); - onCharacteristicNotified(gatt, characteristic); - } else { // indications - Logger.i(mLogSession, "Indication received from " + characteristic.getUuid() + ", value: " + data); - onCharacteristicIndicated(gatt, characteristic); - } - } - } - - /** - * Executes the next request. If the last element from the initialization queue has been executed - * the {@link #onDeviceReady()} callback is called. - */ - private void nextRequest() { - if (mOperationInProgress) - return; - - // Get the first request from the init queue - Request request = mInitQueue != null ? mInitQueue.poll() : null; - - // Are we done with initializing? - if (request == null) { - if (mInitInProgress) { - mInitQueue = null; // release the queue - mInitInProgress = false; - onDeviceReady(); - } - // If so, we can continue with the task queue - request = mTaskQueue.poll(); - if (request == null) { - // Nothing to be done for now - return; - } - } - - mOperationInProgress = true; - boolean result = false; - switch (request.type) { - case CREATE_BOND: { - result = internalCreateBond(); - break; - } - case READ: { - result = internalReadCharacteristic(request.characteristic); - break; - } - case WRITE: { - final BluetoothGattCharacteristic characteristic = request.characteristic; - characteristic.setValue(request.value); - characteristic.setWriteType(request.writeType); - result = internalWriteCharacteristic(characteristic); - break; - } - case READ_DESCRIPTOR: { - result = internalReadDescriptor(request.descriptor); - break; - } - case WRITE_DESCRIPTOR: { - final BluetoothGattDescriptor descriptor = request.descriptor; - descriptor.setValue(request.value); - result = internalWriteDescriptor(descriptor); - break; - } - case ENABLE_NOTIFICATIONS: { - result = internalEnableNotifications(request.characteristic); - break; - } - case ENABLE_INDICATIONS: { - result = internalEnableIndications(request.characteristic); - break; - } - case READ_BATTERY_LEVEL: { - result = internalReadBatteryLevel(); - break; - } - case ENABLE_BATTERY_LEVEL_NOTIFICATIONS: { - result = internalSetBatteryNotifications(true); - break; - } - case DISABLE_BATTERY_LEVEL_NOTIFICATIONS: { - result = internalSetBatteryNotifications(false); - break; - } - case ENABLE_SERVICE_CHANGED_INDICATIONS: { - result = ensureServiceChangedEnabled(); - break; - } - } - // The result may be false if given characteristic or descriptor were not found on the device. - // In that case, proceed with next operation and ignore the one that failed. - if (!result) { - mOperationInProgress = false; - nextRequest(); - } - } - - /** - * Returns true if this descriptor is from the Service Changed characteristic. - * - * @param descriptor the descriptor to be checked - * @return true if the descriptor belongs to the Service Changed characteristic - */ - private boolean isServiceChangedCCCD(final BluetoothGattDescriptor descriptor) { - if (descriptor == null) - return false; - - return SERVICE_CHANGED_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid()); - } - - /** - * Returns true if the characteristic is the Battery Level characteristic. - * - * @param characteristic the characteristic to be checked - * @return true if the characteristic is the Battery Level characteristic. - */ - private boolean isBatteryLevelCharacteristic(final BluetoothGattCharacteristic characteristic) { - if (characteristic == null) - return false; - - return BATTERY_LEVEL_CHARACTERISTIC.equals(characteristic.getUuid()); - } - - /** - * Returns true if this descriptor is from the Battery Level characteristic. - * - * @param descriptor the descriptor to be checked - * @return true if the descriptor belongs to the Battery Level characteristic - */ - private boolean isBatteryLevelCCCD(final BluetoothGattDescriptor descriptor) { - if (descriptor == null) - return false; - - return BATTERY_LEVEL_CHARACTERISTIC.equals(descriptor.getCharacteristic().getUuid()); - } - - /** - * Returns true if this descriptor is a Client Characteristic Configuration descriptor (CCCD). - * - * @param descriptor the descriptor to be checked - * @return true if the descriptor is a CCCD - */ - private boolean isCCCD(final BluetoothGattDescriptor descriptor) { - if (descriptor == null) - return false; - - return CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR_UUID.equals(descriptor.getUuid()); - } - } - - private static final int PAIRING_VARIANT_PIN = 0; - private static final int PAIRING_VARIANT_PASSKEY = 1; - private static final int PAIRING_VARIANT_PASSKEY_CONFIRMATION = 2; - private static final int PAIRING_VARIANT_CONSENT = 3; - private static final int PAIRING_VARIANT_DISPLAY_PASSKEY = 4; - private static final int PAIRING_VARIANT_DISPLAY_PIN = 5; - private static final int PAIRING_VARIANT_OOB_CONSENT = 6; - - protected String pairingVariantToString(final int variant) { - switch (variant) { - case PAIRING_VARIANT_PIN: - return "PAIRING_VARIANT_PIN"; - case PAIRING_VARIANT_PASSKEY: - return "PAIRING_VARIANT_PASSKEY"; - case PAIRING_VARIANT_PASSKEY_CONFIRMATION: - return "PAIRING_VARIANT_PASSKEY_CONFIRMATION"; - case PAIRING_VARIANT_CONSENT: - return "PAIRING_VARIANT_CONSENT"; - case PAIRING_VARIANT_DISPLAY_PASSKEY: - return "PAIRING_VARIANT_DISPLAY_PASSKEY"; - case PAIRING_VARIANT_DISPLAY_PIN: - return "PAIRING_VARIANT_DISPLAY_PIN"; - case PAIRING_VARIANT_OOB_CONSENT: - return "PAIRING_VARIANT_OOB_CONSENT"; - default: - return "UNKNOWN"; - } - } - - protected String bondStateToString(final int state) { - switch (state) { - case BluetoothDevice.BOND_NONE: - return "BOND_NONE"; - case BluetoothDevice.BOND_BONDING: - return "BOND_BONDING"; - case BluetoothDevice.BOND_BONDED: - return "BOND_BONDED"; - default: - return "UNKNOWN"; - } - } - - protected String getWriteType(final int type) { - switch (type) { - case BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT: - return "WRITE REQUEST"; - case BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE: - return "WRITE COMMAND"; - case BluetoothGattCharacteristic.WRITE_TYPE_SIGNED: - return "WRITE SIGNED"; - default: - return "UNKNOWN: " + type; - } - } - - /** - * Converts the connection state to String value - * @param state the connection state - * @return state as String - */ - protected String stateToString(final int state) { - switch (state) { - case BluetoothProfile.STATE_CONNECTED: - return "CONNECTED"; - case BluetoothProfile.STATE_CONNECTING: - return "CONNECTING"; - case BluetoothProfile.STATE_DISCONNECTING: - return "DISCONNECTING"; - default: - return "DISCONNECTED"; - } - } -} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleManagerCallbacks.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleManagerCallbacks.java deleted file mode 100644 index ea67f998..00000000 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleManagerCallbacks.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2015, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package no.nordicsemi.android.nrftoolbox.profile; - -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothGatt; -import android.bluetooth.BluetoothGattCallback; - -/** - * DO NOT EDIT THIS FILE UNLESS NECESSARY! - * The BleManagerCallbacks should be overridden in your app and all the 'high level' callbacks should be added there. - * Keeping this file as is (and {@link BleManager} as well) will allow to quickly update it when an update is posted here. - * @see no.nordicsemi.android.nrftoolbox.rsc.RSCManagerCallbacks - */ -public interface BleManagerCallbacks { - - /** - * Called when the Android device started connecting to given device. - * The {@link #onDeviceConnected(BluetoothDevice)} will be called when the device is connected, - * or {@link #onError(BluetoothDevice, String, int)} in case of error. - * @param device the device that got connected - */ - void onDeviceConnecting(final BluetoothDevice device); - - /** - * Called when the device has been connected. This does not mean that the application may start communication. - * A service discovery will be handled automatically after this call. Service discovery - * may ends up with calling {@link #onServicesDiscovered(BluetoothDevice, boolean)} or - * {@link #onDeviceNotSupported(BluetoothDevice)} if required services have not been found. - * @param device the device that got connected - */ - void onDeviceConnected(final BluetoothDevice device); - - /** - * Called when user initialized disconnection. - * @param device the device that gets disconnecting - */ - void onDeviceDisconnecting(final BluetoothDevice device); - - /** - * Called when the device has disconnected (when the callback returned - * {@link BluetoothGattCallback#onConnectionStateChange(BluetoothGatt, int, int)} with state DISCONNECTED), - * but ONLY if the {@link BleManager#shouldAutoConnect()} method returned false for this device when it was connecting. - * Otherwise the {@link #onLinklossOccur(BluetoothDevice)} method will be called instead. - * @param device the device that got disconnected - */ - void onDeviceDisconnected(final BluetoothDevice device); - - /** - * This callback is invoked when the Ble Manager lost connection to a device that has been connected - * with autoConnect option (see {@link BleManager#shouldAutoConnect()}. - * Otherwise a {@link #onDeviceDisconnected(BluetoothDevice)} method will be called on such event. - * @param device the device that got disconnected due to a link loss - */ - void onLinklossOccur(final BluetoothDevice device); - - /** - * Called when service discovery has finished and primary services has been found. - * This method is not called if the primary, mandatory services were not found during service discovery. - * For example in the Blood Pressure Monitor, a Blood Pressure service is a primary service and - * Intermediate Cuff Pressure service is a optional secondary service. - * Existence of battery service is not notified by this call. - *
After successful service discovery the service will initialize all services. - * The {@link #onDeviceReady(BluetoothDevice)} method will be called when the initialization is complete.
- * - * @param device the device which services got disconnected - * @param optionalServicesFound - * iftrue the secondary services were also found on the device.
- */
- void onServicesDiscovered(final BluetoothDevice device, final boolean optionalServicesFound);
-
- /**
- * Method called when all initialization requests has been completed.
- * @param device the device that get ready
- */
- void onDeviceReady(final BluetoothDevice device);
-
- /**
- * This method should return true if Battery Level notifications should be enabled on the target device.
- * If there is no Battery Service, or the Battery Level characteristic does not have NOTIFY property,
- * this method will not be called for this device.
- * This method may return true only if an activity is bound to the service (to display the information - * to the user), always (e.g. if critical battery level is reported using notifications) or never, if - * such information is not important or the manager wants to control Battery Level notifications on its own.
- * @param device target device - * @return true to enabled battery level notifications after connecting to the device, false otherwise - */ - boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device); - - /** - * Called when battery value has been received from the device. - * - * @param value - * the battery value in percent - * @param device the device frm which the battery value has changed - */ - void onBatteryValueReceived(final BluetoothDevice device, final int value); - - /** - * Called when an {@link BluetoothGatt#GATT_INSUFFICIENT_AUTHENTICATION} error occurred and the device bond state is NOT_BONDED - * @param device the device that requires bonding - */ - void onBondingRequired(final BluetoothDevice device); - - /** - * Called when the device has been successfully bonded. - * @param device the device that got bonded - */ - void onBonded(final BluetoothDevice device); - - /** - * Called when a BLE error has occurred - * - * @param message - * the error message - * @param errorCode - * the error code - * @param device the device that caused an error - */ - void onError(final BluetoothDevice device, final String message, final int errorCode); - - /** - * Called when service discovery has finished but the main services were not found on the device. - * @param device the device that failed to connect due to lack of required services - */ - void onDeviceNotSupported(final BluetoothDevice device); -} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileActivity.java index b1256c1f..01775706 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileActivity.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileActivity.java @@ -41,6 +41,8 @@ import android.widget.Toast; import java.util.UUID; +import no.nordicsemi.android.ble.BleManager; +import no.nordicsemi.android.ble.BleManagerCallbacks; import no.nordicsemi.android.log.ILogSession; import no.nordicsemi.android.log.LocalLogSession; import no.nordicsemi.android.log.Logger; diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java index 01880610..f1bb65c2 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileExpandableListActivity.java @@ -40,6 +40,8 @@ import android.widget.Toast; import java.util.UUID; +import no.nordicsemi.android.ble.BleManager; +import no.nordicsemi.android.ble.BleManagerCallbacks; import no.nordicsemi.android.log.ILogSession; import no.nordicsemi.android.log.LocalLogSession; import no.nordicsemi.android.log.Logger; diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java index a1aa5cd1..9cf3b1df 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileService.java @@ -38,6 +38,9 @@ import android.support.annotation.StringRes; import android.support.v4.content.LocalBroadcastManager; import android.widget.Toast; +import no.nordicsemi.android.ble.BleManager; +import no.nordicsemi.android.ble.BleManagerCallbacks; +import no.nordicsemi.android.ble.utils.ILogger; import no.nordicsemi.android.log.ILogSession; import no.nordicsemi.android.log.LogContract; import no.nordicsemi.android.log.Logger; diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java index a8a4b136..83f9430b 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/BleProfileServiceReadyActivity.java @@ -48,6 +48,7 @@ import android.widget.Toast; import java.util.UUID; +import no.nordicsemi.android.ble.BleManagerCallbacks; import no.nordicsemi.android.log.ILogSession; import no.nordicsemi.android.log.LocalLogSession; import no.nordicsemi.android.log.Logger; diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/ILogger.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/ILogger.java deleted file mode 100644 index 1afce151..00000000 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/ILogger.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 2016, Nordic Semiconductor - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -package no.nordicsemi.android.nrftoolbox.profile; - -import android.support.annotation.StringRes; - -public interface ILogger { - - /** - * Logs the given message with given log level into the all managed devices' log session. - * @param level the log level - * @param message the message to be logged - */ - void log(final int level, final String message); - - /** - * Logs the given message with given log level into the all managed devices' log session. - * @param level the log level - * @param messageRes string resource id - * @param params additional (optional) parameters used to fill the message - */ - void log(final int level, @StringRes final int messageRes, final Object... params); -} diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java index bea13065..2578f825 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileService.java @@ -41,11 +41,11 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; +import no.nordicsemi.android.ble.BleManager; +import no.nordicsemi.android.ble.BleManagerCallbacks; +import no.nordicsemi.android.ble.utils.ILogger; import no.nordicsemi.android.log.ILogSession; import no.nordicsemi.android.log.LogContract; -import no.nordicsemi.android.nrftoolbox.profile.BleManager; -import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks; -import no.nordicsemi.android.nrftoolbox.profile.ILogger; public abstract class BleMulticonnectProfileService extends Service implements BleManagerCallbacks { @SuppressWarnings("unused") diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileServiceReadyActivity.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileServiceReadyActivity.java index 5a867a9f..7536104b 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileServiceReadyActivity.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/profile/multiconnect/BleMulticonnectProfileServiceReadyActivity.java @@ -48,13 +48,13 @@ import java.util.Collections; import java.util.List; import java.util.UUID; +import no.nordicsemi.android.ble.BleManagerCallbacks; import no.nordicsemi.android.log.ILogSession; import no.nordicsemi.android.log.LocalLogSession; import no.nordicsemi.android.log.LogContract; import no.nordicsemi.android.log.Logger; import no.nordicsemi.android.nrftoolbox.AppHelpFragment; import no.nordicsemi.android.nrftoolbox.R; -import no.nordicsemi.android.nrftoolbox.profile.BleManagerCallbacks; import no.nordicsemi.android.nrftoolbox.scanner.ScannerFragment; import no.nordicsemi.android.nrftoolbox.utility.DebugLogger; diff --git a/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityManager.java b/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityManager.java index f5b983d2..67a16500 100644 --- a/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityManager.java +++ b/app/src/main/java/no/nordicsemi/android/nrftoolbox/proximity/ProximityManager.java @@ -30,9 +30,9 @@ import java.util.Deque; import java.util.LinkedList; import java.util.UUID; +import no.nordicsemi.android.ble.BleManager; import no.nordicsemi.android.log.Logger; import no.nordicsemi.android.nrftoolbox.parser.AlertLevelParser; -import no.nordicsemi.android.nrftoolbox.profile.BleManager; import no.nordicsemi.android.nrftoolbox.utility.DebugLogger; public class ProximityManager extends BleManager