Implementing request queue in BleManager

Both BleManagers (app and wear) modified,
All profiles adjusted to match new API,
Supporting Bluetooth OFF/ON event in BleProfileService
This commit is contained in:
Aleksander Nowakowski
2016-10-17 18:00:44 +02:00
parent 0d898e0557
commit 0b2e3aba17
31 changed files with 1885 additions and 556 deletions

View File

@@ -27,14 +27,14 @@ import android.bluetooth.BluetoothGattService;
import android.content.Context;
import java.util.Calendar;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
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<BPMManagerCallbacks> {
/** Blood Pressure service UUID */
@@ -73,7 +73,7 @@ public class BPMManager extends BleManager<BPMManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
if (mICPCharacteristic != null)
requests.add(Request.newEnableNotificationsRequest(mICPCharacteristic));

View File

@@ -28,8 +28,8 @@ import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.util.SparseArray;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
@@ -128,7 +128,7 @@ public class CGMSManager extends BleManager<CGMSManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableNotificationsRequest(mCGMMeasurementCharacteristic));
if (mCGMOpsControlPointCharacteristic != null) {

View File

@@ -161,12 +161,6 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
createNotification(R.string.csc_notification_connected_message, 0);
}
@Override
protected void onServiceStarted() {
// logger is now available. Assign it to the manager
mManager.setLogger(getLogSession());
}
/**
* Creates the notification
*

View File

@@ -27,13 +27,13 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
import no.nordicsemi.android.nrftoolbox.parser.CSCMeasurementParser;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
public class CSCManager extends BleManager<CSCManagerCallbacks> {
/** Cycling Speed and Cadence service UUID */
@@ -61,7 +61,7 @@ public class CSCManager extends BleManager<CSCManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableNotificationsRequest(mCSCMeasurementCharacteristic));
return requests;

View File

@@ -120,12 +120,6 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
createNotification(R.string.csc_notification_connected_message, 0);
}
@Override
protected void onServiceStarted() {
// logger is now available. Assign it to the manager
mManager.setLogger(getLogSession());
}
@Override
public void onWheelMeasurementReceived(final BluetoothDevice device, final int wheelRevolutions, final int lastWheelEventTime) {
Logger.a(getLogSession(), "Wheel rev: " + wheelRevolutions + "\nLast wheel event time: " + lastWheelEventTime + " ms");

View File

@@ -29,15 +29,15 @@ import android.os.Handler;
import android.util.SparseArray;
import java.util.Calendar;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
import no.nordicsemi.android.nrftoolbox.parser.GlucoseMeasurementContextParser;
import no.nordicsemi.android.nrftoolbox.parser.GlucoseMeasurementParser;
import no.nordicsemi.android.nrftoolbox.parser.RecordAccessControlPointParser;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
@SuppressWarnings("unused")
@@ -127,7 +127,7 @@ public class GlucoseManager extends BleManager<GlucoseManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableNotificationsRequest(mGlucoseMeasurementCharacteristic));
if (mGlucoseMeasurementContextCharacteristic != null)

View File

@@ -26,15 +26,15 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.R;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
import no.nordicsemi.android.nrftoolbox.parser.BodySensorLocationParser;
import no.nordicsemi.android.nrftoolbox.parser.HeartRateMeasurementParser;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
/**
* HRSManager class performs BluetoothGatt operations for connection, service discovery, enabling notification and reading characteristics. All operations required to connect to device with BLE HR
@@ -74,7 +74,7 @@ public class HRSManager extends BleManager<HRSManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
if (mHRLocationCharacteristic != null)
requests.add(Request.newReadRequest(mHRLocationCharacteristic));

View File

@@ -26,8 +26,8 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
@@ -71,7 +71,7 @@ public class HTSManager extends BleManager<HTSManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableIndicationsRequest(mHTCharacteristic));
return requests;

View File

@@ -100,12 +100,6 @@ public class HTSService extends BleProfileService implements HTSManagerCallbacks
createNotification(R.string.hts_notification_connected_message, 0);
}
@Override
protected void onServiceStarted() {
// logger is now available. Assign it to the manager
mManager.setLogger(getLogSession());
}
@Override
public void onHTValueReceived(final BluetoothDevice device, final double value) {
final Intent broadcast = new Intent(BROADCAST_HTS_MEASUREMENT);

View File

@@ -86,6 +86,18 @@ public interface BleManagerCallbacks {
*/
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.
* <p>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.</p>
* @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.
*

View File

@@ -52,9 +52,9 @@ import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
public abstract class BleProfileActivity extends AppCompatActivity implements BleManagerCallbacks, ScannerFragment.OnDeviceSelectedListener {
private static final String TAG = "BaseProfileActivity";
private static final String CONNECTION_STATUS = "connection_status";
private static final String DEVICE_NAME = "device_name";
private static final int REQUEST_ENABLE_BT = 2;
private static final String SIS_CONNECTION_STATUS = "connection_status";
private static final String SIS_DEVICE_NAME = "device_name";
protected static final int REQUEST_ENABLE_BT = 2;
private BleManager<? extends BleManagerCallbacks> mBleManager;
@@ -82,12 +82,18 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
* broadcast listeners, local broadcast listeners (see support.v4 library), or messages. See the Proximity profile for Service approach.
*/
mBleManager = initializeManager();
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
onInitialize(savedInstanceState);
// The onCreateView class should... create the view
onCreateView(savedInstanceState);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
// Common nRF Toolbox view references are obtained here
setUpView();
// View is ready to be used
onViewCreated(savedInstanceState);
}
@@ -101,18 +107,24 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
/**
* Called from {@link #onCreate(Bundle)}. This method should build the activity UI, f.e. using {@link #setContentView(int)}. Use to obtain references to
* views. Connect/Disconnect button, the device name view and battery level view are manager automatically.
*
* @param savedInstanceState
* contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}. Note: <b>Otherwise it is null</b>.
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}. Note: <b>Otherwise it is null</b>.
*/
protected abstract void onCreateView(final Bundle savedInstanceState);
/**
* Called after the view has been created.
*
* @param savedInstanceState
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}. Note: <b>Otherwise it is null</b>.
*/
protected final void onViewCreated(final Bundle savedInstanceState) {
protected void onViewCreated(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called after the view and the toolbar has been created.
*/
protected final void setUpView() {
// set GUI
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mConnectButton = (Button) findViewById(R.id.action_connect);
@@ -129,15 +141,15 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
@Override
protected void onSaveInstanceState(final Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(CONNECTION_STATUS, mDeviceConnected);
outState.putString(DEVICE_NAME, mDeviceName);
outState.putBoolean(SIS_CONNECTION_STATUS, mDeviceConnected);
outState.putString(SIS_DEVICE_NAME, mDeviceName);
}
@Override
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mDeviceConnected = savedInstanceState.getBoolean(CONNECTION_STATUS);
mDeviceName = savedInstanceState.getString(DEVICE_NAME);
mDeviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
if (mDeviceConnected) {
mConnectButton.setText(R.string.action_disconnect);
@@ -154,9 +166,8 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
/**
* Use this method to handle menu actions other than home and about.
*
* @param itemId
* the menu item id
*
* @param itemId the menu item id
* @return <code>true</code> if action has been handled
*/
protected boolean onOptionsItemSelected(final int itemId) {
@@ -168,15 +179,15 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
public boolean onOptionsItemSelected(final MenuItem item) {
final int id = item.getItemId();
switch (id) {
case android.R.id.home:
onBackPressed();
break;
case R.id.action_about:
final AppHelpFragment fragment = AppHelpFragment.getInstance(getAboutTextId());
fragment.show(getSupportFragmentManager(), "help_fragment");
break;
default:
return onOptionsItemSelected(id);
case android.R.id.home:
onBackPressed();
break;
case R.id.action_about:
final AppHelpFragment fragment = AppHelpFragment.getInstance(getAboutTextId());
fragment.show(getSupportFragmentManager(), "help_fragment");
break;
default:
return onOptionsItemSelected(id);
}
return true;
}
@@ -229,7 +240,6 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
mBleManager.setLogger(mLogSession);
mDeviceNameView.setText(name != null ? name : getString(R.string.not_available));
mConnectButton.setText(R.string.action_connecting);
mConnectButton.setEnabled(false);
mBleManager.connect(device);
}
@@ -250,7 +260,6 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
@Override
public void run() {
mConnectButton.setText(R.string.action_disconnect);
mConnectButton.setEnabled(true);
}
});
}
@@ -270,7 +279,6 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
mConnectButton.setText(R.string.action_connect);
mDeviceNameView.setText(getDefaultDeviceName());
mBatteryLevelView.setText(R.string.not_available);
mConnectButton.setEnabled(true);
}
});
}
@@ -281,21 +289,20 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
runOnUiThread(new Runnable() {
@Override
public void run() {
mConnectButton.setText(R.string.action_connect);
mDeviceNameView.setText(getDefaultDeviceName());
mBatteryLevelView.setText(R.string.not_available);
if (mBatteryLevelView != null)
mBatteryLevelView.setText(R.string.not_available);
}
});
}
@Override
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mBatteryLevelView.setText(getString(R.string.battery, value));
}
});
public void onServicesDiscovered(final BluetoothDevice device, boolean optionalServicesFound) {
// this may notify user or show some views
}
@Override
public void onDeviceReady(final BluetoothDevice device) {
// empty default implementation
}
@Override
@@ -308,6 +315,23 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
showToast(R.string.bonded);
}
@Override
public boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
// Yes, we want battery level updates
return true;
}
@Override
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mBatteryLevelView != null)
mBatteryLevelView.setText(getString(R.string.battery, value));
}
});
}
@Override
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
@@ -321,9 +345,8 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param message
* a message to be shown
*
* @param message a message to be shown
*/
protected void showToast(final String message) {
runOnUiThread(new Runnable() {
@@ -336,9 +359,8 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
* @param messageResId
* an resource id of the message to be shown
*
* @param messageResId an resource id of the message to be shown
*/
protected void showToast(final int messageResId) {
runOnUiThread(new Runnable() {
@@ -365,7 +387,7 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
/**
* Initializes the Bluetooth Low Energy manager. A manager is used to communicate with profile's services.
*
*
* @return the manager that was created
*/
protected abstract BleManager<? extends BleManagerCallbacks> initializeManager();
@@ -378,14 +400,14 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
/**
* Returns the default device name resource id. The real device name is obtained when connecting to the device. This one is used when device has
* disconnected.
*
*
* @return the default device name resource id
*/
protected abstract int getDefaultDeviceName();
/**
* Returns the string resource id that will be shown in About box
*
*
* @return the about resource id
*/
protected abstract int getAboutTextId();
@@ -393,17 +415,16 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
/**
* The UUID filter is used to filter out available devices that does not have such UUID in their advertisement packet. See also:
* {@link #isChangingConfigurations()}.
*
*
* @return the required UUID or <code>null</code>
*/
protected abstract UUID getFilterUUID();
/**
* Shows the scanner fragment.
*
* @param filter
* the UUID filter used to filter out available devices. The fragment will always show all bonded devices as there is no information about their
* services
*
* @param filter the UUID filter used to filter out available devices. The fragment will always show all bonded devices as there is no information about their
* services
* @see #getFilterUUID()
*/
private void showDeviceScanningDialog(final UUID filter) {
@@ -416,6 +437,15 @@ public abstract class BleProfileActivity extends AppCompatActivity implements Bl
});
}
/**
* Returns the log session. Log session is created when the device was selected using the {@link ScannerFragment} and released when user press DISCONNECT.
*
* @return the logger session or <code>null</code>
*/
protected ILogSession getLogSession() {
return mLogSession;
}
private void ensureBLESupported() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show();

View File

@@ -29,6 +29,7 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
@@ -81,12 +82,18 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
* broadcast listeners, local broadcast listeners (see support.v4 library), or messages. See the Proximity profile for Service approach.
*/
mBleManager = initializeManager();
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
onInitialize(savedInstanceState);
// The onCreateView class should... create the view
onCreateView(savedInstanceState);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
// Common nRF Toolbox view references are obtained here
setUpView();
// View is ready to be used
onViewCreated(savedInstanceState);
}
@@ -110,7 +117,14 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
*
* @param savedInstanceState contains the data it most recently supplied in {@link #onSaveInstanceState(Bundle)}. Note: <b>Otherwise it is null</b>.
*/
protected final void onViewCreated(final Bundle savedInstanceState) {
protected void onViewCreated(final Bundle savedInstanceState) {
// empty default implementation
}
/**
* Called after the view and the toolbar has been created.
*/
protected final void setUpView() {
// set GUI
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mConnectButton = (Button) findViewById(R.id.action_connect);
@@ -132,7 +146,7 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
}
@Override
protected void onRestoreInstanceState(final Bundle savedInstanceState) {
protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mDeviceConnected = savedInstanceState.getBoolean(SIS_CONNECTION_STATUS);
mDeviceName = savedInstanceState.getString(SIS_DEVICE_NAME);
@@ -226,7 +240,6 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
mBleManager.setLogger(mLogSession);
mDeviceNameView.setText(name != null ? name : getString(R.string.not_available));
mConnectButton.setText(R.string.action_connecting);
mConnectButton.setEnabled(false);
mBleManager.connect(device);
}
@@ -247,7 +260,6 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
@Override
public void run() {
mConnectButton.setText(R.string.action_disconnect);
mConnectButton.setEnabled(true);
}
});
}
@@ -277,9 +289,8 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
runOnUiThread(new Runnable() {
@Override
public void run() {
mConnectButton.setText(R.string.action_connect);
mDeviceNameView.setText(getDefaultDeviceName());
mBatteryLevelView.setText(R.string.not_available);
if (mBatteryLevelView != null)
mBatteryLevelView.setText(R.string.not_available);
}
});
}
@@ -289,23 +300,11 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
// this may notify user or show some views
}
/**
* Called when the initialization process in completed.
*/
@Override
public void onDeviceReady(final BluetoothDevice device) {
// empty default implementation
}
@Override
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mBatteryLevelView.setText(getString(R.string.battery, value));
}
});
}
@Override
public void onBondingRequired(final BluetoothDevice device) {
showToast(R.string.bonding);
@@ -316,6 +315,23 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
showToast(R.string.bonded);
}
@Override
public boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
// Yes, we want battery level updates
return true;
}
@Override
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
runOnUiThread(new Runnable() {
@Override
public void run() {
if (mBatteryLevelView != null)
mBatteryLevelView.setText(getString(R.string.battery, value));
}
});
}
@Override
public void onError(final BluetoothDevice device, final String message, final int errorCode) {
DebugLogger.e(TAG, "Error occurred: " + message + ", error code: " + errorCode);
@@ -421,6 +437,15 @@ public abstract class BleProfileExpandableListActivity extends ExpandableListAct
});
}
/**
* Returns the log session. Log session is created when the device was selected using the {@link ScannerFragment} and released when user press DISCONNECT.
*
* @return the logger session or <code>null</code>
*/
protected ILogSession getLogSession() {
return mLogSession;
}
private void ensureBLESupported() {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
Toast.makeText(this, R.string.no_ble, Toast.LENGTH_LONG).show();

View File

@@ -24,16 +24,22 @@ package no.nordicsemi.android.nrftoolbox.profile;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.support.annotation.StringRes;
import android.support.v4.content.LocalBroadcastManager;
import android.widget.Toast;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.LogContract;
import no.nordicsemi.android.log.Logger;
public abstract class BleProfileService extends Service implements BleManagerCallbacks {
@@ -71,18 +77,54 @@ public abstract class BleProfileService extends Service implements BleManagerCal
private Handler mHandler;
protected boolean mBinded;
private boolean mActivityFinished;
private boolean mConnected;
private boolean mActivityIsChangingConfiguration;
private BluetoothDevice mBluetoothDevice;
private String mDeviceName;
private ILogSession mLogSession;
public class LocalBinder extends Binder {
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 ILogger logger = getBinder();
final String stateString = "[Broadcast] Action received: " + BluetoothAdapter.ACTION_STATE_CHANGED + ", state changed to " + state2String(state);
logger.log(LogContract.Log.Level.DEBUG, stateString);
switch (state) {
case BluetoothAdapter.STATE_ON:
onBluetoothEnabled();
break;
case BluetoothAdapter.STATE_TURNING_OFF:
case BluetoothAdapter.STATE_OFF:
onBluetoothDisabled();
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 + ")";
}
}
};
public class LocalBinder extends Binder implements ILogger {
/**
* Disconnects from the sensor.
*/
public final void disconnect() {
if (!mConnected) {
final int state = mBleManager.getConnectionState();
if (state == BluetoothGatt.STATE_DISCONNECTED || state == BluetoothGatt.STATE_DISCONNECTING) {
mBleManager.close();
onDeviceDisconnected(mBluetoothDevice);
return;
@@ -92,16 +134,17 @@ public abstract class BleProfileService extends Service implements BleManagerCal
}
/**
* Sets whether the binded activity if finishing or not. If <code>true</code>, we will turn off battery level notifications in onUnbind(..) method below.
* @param finishing true if the binded activity is finishing
* Sets whether the bound activity if changing configuration or not.
* If <code>false</code>, we will turn off battery level notifications in onUnbind(..) method below.
* @param changing true if the bound activity is finishing
*/
public void setActivityIsFinishing(final boolean finishing) {
mActivityFinished = finishing;
public void setActivityIsChangingConfiguration(final boolean changing) {
mActivityIsChangingConfiguration = changing;
}
/**
* Returns the device address
*
*
* @return device address
*/
public String getDeviceAddress() {
@@ -110,7 +153,7 @@ public abstract class BleProfileService extends Service implements BleManagerCal
/**
* Returns the device name
*
*
* @return the device name
*/
public String getDeviceName() {
@@ -128,26 +171,46 @@ public abstract class BleProfileService extends Service implements BleManagerCal
/**
* Returns <code>true</code> if the device is connected to the sensor.
*
*
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
public boolean isConnected() {
return mConnected;
return mBleManager.isConnected();
}
/**
* Returns the connection state of given device.
* @return the connection state, as in {@link BleManager#getConnectionState()}.
*/
public int getConnectionState() {
return mBleManager.getConnectionState();
}
/**
* Returns the log session that can be used to append log entries. The log session is created when the service is being created. The method returns <code>null</code> if the nRF Logger app was
* not installed.
* Returns the log session that can be used to append log entries.
* The log session is created when the service is being created.
* The method returns <code>null</code> if the nRF Logger app was not installed.
*
* @return the log session
*/
public ILogSession getLogSession() {
return mLogSession;
}
@Override
public void log(final int level, final String message) {
Logger.log(mLogSession, level, message);
}
@Override
public void log(final int level, final @StringRes int messageRes, final Object... params) {
Logger.log(mLogSession, level, messageRes, params);
}
}
/**
* Returns the binder implementation. This must return class implementing the additional manager interface that may be used in the binded activity.
* Returns the binder implementation. This must return class implementing the additional manager interface that may be used in the bound activity.
*
* @return the service binder
*/
@@ -166,11 +229,10 @@ public abstract class BleProfileService extends Service implements BleManagerCal
public final void onRebind(final Intent intent) {
mBinded = true;
if (mActivityFinished)
if (!mActivityIsChangingConfiguration)
onRebind();
if (mActivityFinished && mConnected) {
mActivityFinished = false;
if (!mActivityIsChangingConfiguration && mBleManager.isConnected()) {
// This method will read the Battery Level value, if possible and then try to enable battery notifications (if it has NOTIFY property).
// If the Battery Level characteristic has only the NOTIFY property, it will only try to enable notifications.
mBleManager.readBatteryLevel();
@@ -178,33 +240,35 @@ public abstract class BleProfileService extends Service implements BleManagerCal
}
/**
* Called when the activity has rebinded to the service after being recreated. This method is not called when the activity was killed and recreated just to change the phone orientation.
* Called when the activity has rebound to the service after being recreated.
* This method is not called when the activity was killed to be recreated when the phone orientation changed
* if prior to being killed called {@link BleProfileService.LocalBinder#setActivityIsChangingConfiguration(boolean)} with parameter true.
*/
protected void onRebind() {
// empty
// empty default implementation
}
@Override
public final boolean onUnbind(final Intent intent) {
mBinded = false;
if (mActivityFinished)
if (!mActivityIsChangingConfiguration)
onUnbind();
// When we are connected, but the application is not open, we are not really interested in battery level notifications. But we will still be receiving other values, if enabled.
if (mActivityFinished && mConnected)
if (!mActivityIsChangingConfiguration && mBleManager.isConnected())
mBleManager.setBatteryNotifications(false);
// we must allow to rebind to the same service
// We want the onRebind method be called if anything else binds to it again
return true;
}
/**
* Called when the activity has unbound from the service before being finished.
* This method is not called when the activity is killed to be recreated just to change the phone orientation.
* This method is not called when the activity is killed to be recreated when the phone orientation changed.
*/
protected void onUnbind() {
// empty
// empty default implementation
}
@SuppressWarnings("unchecked")
@@ -214,11 +278,34 @@ public abstract class BleProfileService extends Service implements BleManagerCal
mHandler = new Handler();
// initialize the manager
// Initialize the manager
mBleManager = initializeManager();
mBleManager.setGattCallbacks(this);
// Register broadcast receivers
registerReceiver(mBluetoothStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
// Service has now been created
onServiceCreated();
// Call onBluetoothEnabled if Bluetooth enabled
final BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter.isEnabled()) {
onBluetoothEnabled();
}
}
/**
* Called when the service has been created, before the {@link #onBluetoothEnabled()} is called.
*/
protected void onServiceCreated() {
// empty default implementation
}
/**
* Initializes the Ble Manager responsible for connecting to a single device.
* @return a new BleManager object
*/
@SuppressWarnings("rawtypes")
protected abstract BleManager initializeManager();
@@ -237,22 +324,35 @@ public abstract class BleProfileService extends Service implements BleManagerCal
final BluetoothAdapter adapter = bluetoothManager.getAdapter();
final String deviceAddress = intent.getStringExtra(EXTRA_DEVICE_ADDRESS);
mBluetoothDevice = adapter.getRemoteDevice(deviceAddress);
onServiceStarted();
mBleManager.setLogger(mLogSession);
onServiceStarted();
mBleManager.connect(mBluetoothDevice);
return START_REDELIVER_INTENT;
}
/**
* Called when the service has been started. The device name and address are set. It nRF Logger is installed than logger was also initialized.
* Called when the service has been started. The device name and address are set.
* The BLE Manager will try to connect to the device after this method finishes.
*/
protected void onServiceStarted() {
// empty default implementation
}
@Override
public void onTaskRemoved(final Intent rootIntent) {
super.onTaskRemoved(rootIntent);
// This method is called when user removed the app from Recents.
// By default, the service will be killed and recreated immediately after that.
// However, all managed devices will be lost and devices will be disconnected.
stopSelf();
}
@Override
public void onDestroy() {
super.onDestroy();
// Unregister broadcast receivers
unregisterReceiver(mBluetoothStateBroadcastReceiver);
// shutdown the manager
mBleManager.close();
@@ -260,10 +360,31 @@ public abstract class BleProfileService extends Service implements BleManagerCal
mBleManager = null;
mBluetoothDevice = null;
mDeviceName = null;
mConnected = false;
mLogSession = null;
}
/**
* Method called when Bluetooth Adapter has been disabled.
*/
protected void onBluetoothDisabled() {
// empty default implementation
}
/**
* This method is called when Bluetooth Adapter has been enabled and
* after the service was created if Bluetooth Adapter was enabled at that moment.
* This method could initialize all Bluetooth related features, for example open the GATT server.
*/
protected void onBluetoothEnabled() {
// empty default implementation
}
@Override
public boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
// By default the Battery Level notifications will be enabled only the activity is bound.
return mBinded;
}
@Override
public void onDeviceConnecting(final BluetoothDevice device) {
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
@@ -274,8 +395,6 @@ public abstract class BleProfileService extends Service implements BleManagerCal
@Override
public void onDeviceConnected(final BluetoothDevice device) {
mConnected = true;
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_CONNECTED);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
@@ -303,8 +422,6 @@ public abstract class BleProfileService extends Service implements BleManagerCal
@Override
public void onDeviceDisconnected(final BluetoothDevice device) {
mConnected = false;
// Do not use the device argument here unless you change calling onDeviceDisconnected from the binder above
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
@@ -323,8 +440,6 @@ public abstract class BleProfileService extends Service implements BleManagerCal
@Override
public void onLinklossOccur(final BluetoothDevice device) {
mConnected = false;
final Intent broadcast = new Intent(BROADCAST_CONNECTION_STATE);
broadcast.putExtra(EXTRA_DEVICE, mBluetoothDevice);
broadcast.putExtra(EXTRA_CONNECTION_STATE, STATE_LINK_LOSS);
@@ -394,6 +509,8 @@ public abstract class BleProfileService extends Service implements BleManagerCal
broadcast.putExtra(EXTRA_ERROR_CODE, errorCode);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
// After receiving an error the device will be automatically disconnected.
// Replace it with other implementation if necessary.
mBleManager.disconnect();
stopSelf();
}
@@ -471,6 +588,6 @@ public abstract class BleProfileService extends Service implements BleManagerCal
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
protected boolean isConnected() {
return mConnected;
return mBleManager.isConnected();
}
}

View File

@@ -179,21 +179,30 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
final E bleService = mService = (E) service;
mBluetoothDevice = bleService.getBluetoothDevice();
mLogSession = mService.getLogSession();
Logger.d(mLogSession, "Activity binded to the service");
Logger.d(mLogSession, "Activity bound to the service");
onServiceBinded(bleService);
// update UI
// Update UI
mDeviceName = bleService.getDeviceName();
mDeviceNameView.setText(mDeviceName);
mConnectButton.setText(R.string.action_disconnect);
// and notify user if device is connected
if (bleService.isConnected())
// And notify user if device is connected
if (bleService.isConnected()) {
onDeviceConnected(mBluetoothDevice);
} else {
// If the device is not connected it means that either it is still connecting,
// or the link was lost and service is trying to connect to it (autoConnect=true).
onDeviceConnecting(mBluetoothDevice);
}
}
@Override
public void onServiceDisconnected(final ComponentName name) {
// Note: this method is called only when the service is killed by the system,
// not when it stops itself or is stopped by the activity.
// It will be called only when there is critically low memory, in practice never
// when the activity is in foreground.
Logger.d(mLogSession, "Activity disconnected from the service");
mDeviceNameView.setText(getDefaultDeviceName());
mConnectButton.setText(R.string.action_connect);
@@ -221,33 +230,32 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
mLogSession = Logger.openSession(getApplicationContext(), logUri);
}
/*
* In this example we use the ProximityManager in the service. This class communicates with the service using local broadcasts. Final activity may bind
* to the Server to use its interface.
*/
// In onInitialize method a final class may register local broadcast receivers that will listen for events from the service
onInitialize(savedInstanceState);
// The onCreateView class should... create the view
onCreateView(savedInstanceState);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_actionbar);
setSupportActionBar(toolbar);
// Common nRF Toolbox view references are obtained here
setUpView();
// View is ready to be used
onViewCreated(savedInstanceState);
LocalBroadcastManager.getInstance(this).registerReceiver(mCommonBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onStart() {
super.onStart();
protected void onResume() {
super.onResume();
/*
* If the service has not been started before, the following lines will not start it. However, if it's running, the Activity will be binded to it and
* If the service has not been started before, the following lines will not start it. However, if it's running, the Activity will bind to it and
* notified via mServiceConnection.
*/
final Intent service = new Intent(this, getServiceClass());
if (bindService(service, mServiceConnection, 0)) // we pass 0 as a flag so the service will not be created if not exists
Logger.d(mLogSession, "Binding to the service..."); // (* - see the comment below)
bindService(service, mServiceConnection, 0); // we pass 0 as a flag so the service will not be created if not exists
/*
* * - When user exited the UARTActivity while being connected, the log session is kept in the service. We may not get it before binding to it so in this
@@ -256,20 +264,19 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
}
@Override
protected void onStop() {
super.onStop();
protected void onPause() {
super.onPause();
try {
// We don't want to perform some operations (e.g. disable Battery Level notifications) in the service if we are just rotating the screen.
// However, when the activity is finishing, we may want to disable some device features to reduce the battery consumption.
// However, when the activity will disappear, we may want to disable some device features to reduce the battery consumption.
if (mService != null)
mService.setActivityIsFinishing(isFinishing());
mService.setActivityIsChangingConfiguration(isChangingConfigurations());
Logger.d(mLogSession, "Unbinding from the service...");
unbindService(mServiceConnection);
mService = null;
Logger.d(mLogSession, "Activity unbinded from the service");
Logger.d(mLogSession, "Activity unbound from the service");
onServiceUnbinded();
mDeviceName = null;
mBluetoothDevice = null;
@@ -460,7 +467,6 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
mDeviceName = name;
mDeviceNameView.setText(name != null ? name : getString(R.string.not_available));
mConnectButton.setText(R.string.action_connecting);
mConnectButton.setEnabled(false);
// The device may not be in the range but the service will try to connect to it if it reach it
Logger.d(mLogSession, "Creating service...");
@@ -488,7 +494,6 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
public void onDeviceConnected(final BluetoothDevice device) {
mDeviceNameView.setText(mDeviceName);
mConnectButton.setText(R.string.action_disconnect);
mConnectButton.setEnabled(true);
}
@Override
@@ -545,8 +550,10 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
}
@Override
public void onDeviceNotSupported(final BluetoothDevice device) {
showToast(R.string.not_supported);
public final boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
// This method will never be called.
// Please see BleProfileService#shouldEnableBatteryLevelNotifications(BluetoothDevice) instead.
throw new UnsupportedOperationException("This method should not be called");
}
@Override
@@ -561,6 +568,11 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
showToast(message + " (" + errorCode + ")");
}
@Override
public void onDeviceNotSupported(final BluetoothDevice device) {
showToast(R.string.not_supported);
}
/**
* Shows a message as a Toast notification. This method is thread safe, you can call it from any thread
*
@@ -593,7 +605,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
* Returns <code>true</code> if the device is connected. Services may not have been discovered yet.
*/
protected boolean isDeviceConnected() {
return mService != null;
return mService != null && mService.isConnected();
}
/**
@@ -658,7 +670,7 @@ public abstract class BleProfileServiceReadyActivity<E extends BleProfileService
*
* @return the logger session or <code>null</code>
*/
public ILogSession getLogSession() {
protected ILogSession getLogSession() {
return mLogSession;
}

View File

@@ -0,0 +1,43 @@
/*
* 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);
}

View File

@@ -35,8 +35,8 @@ import android.os.Handler;
import android.preference.PreferenceManager;
import android.util.Log;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.error.GattError;
@@ -277,7 +277,7 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newWriteRequest(mLinklossCharacteristic, HIGH_ALERT));
return requests;

View File

@@ -163,12 +163,6 @@ public class ProximityService extends BleProfileService implements ProximityMana
createNotification(R.string.proximity_notification_linkloss_alert, 0);
}
@Override
protected void onServiceStarted() {
// logger is now available. Assign it to the manager
mProximityManager.setLogger(getLogSession());
}
@Override
public void onDeviceDisconnecting(final BluetoothDevice device) {
stopAlarm();

View File

@@ -27,13 +27,13 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
import no.nordicsemi.android.nrftoolbox.parser.RSCMeasurementParser;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
public class RSCManager extends BleManager<RSCManagerCallbacks> {
private static final byte INSTANTANEOUS_STRIDE_LENGTH_PRESENT = 0x01; // 1 bit
@@ -62,7 +62,7 @@ public class RSCManager extends BleManager<RSCManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableNotificationsRequest(mRSCMeasurementCharacteristic));
return requests;

View File

@@ -121,12 +121,6 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
createNotification(R.string.rsc_notification_connected_message, 0);
}
@Override
protected void onServiceStarted() {
// logger is now available. Assign it to the manager
mManager.setLogger(getLogSession());
}
private final Runnable mUpdateStridesTask = new Runnable() {
@Override
public void run() {

View File

@@ -26,13 +26,13 @@ import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
import no.nordicsemi.android.nrftoolbox.parser.TemplateParser;
import no.nordicsemi.android.nrftoolbox.profile.BleManager;
/**
* Modify to template manager to match your requirements.
@@ -63,7 +63,7 @@ public class TemplateManager extends BleManager<TemplateManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
// TODO initialize your device, enable required notifications and indications, write what needs to be written to start working
requests.add(Request.newEnableNotificationsRequest(mCharacteristic));

View File

@@ -106,12 +106,6 @@ public class TemplateService extends BleProfileService implements TemplateManage
createNotification(R.string.template_notification_connected_message, 0);
}
@Override
protected void onServiceStarted() {
// logger is now available. Assign it to the manager
mManager.setLogger(getLogSession());
}
@Override
public void onSampleValueReceived(final BluetoothDevice device, final int value) {
final Intent broadcast = new Intent(BROADCAST_TEMPLATE_MEASUREMENT);

View File

@@ -29,8 +29,8 @@ import android.content.Context;
import android.text.TextUtils;
import java.io.UnsupportedEncodingException;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Queue;
import java.util.UUID;
import no.nordicsemi.android.log.Logger;
@@ -65,7 +65,7 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() {
@Override
protected Queue<Request> initGatt(final BluetoothGatt gatt) {
protected Deque<Request> initGatt(final BluetoothGatt gatt) {
final LinkedList<Request> requests = new LinkedList<>();
requests.add(Request.newEnableNotificationsRequest(mTXCharacteristic));
return requests;
@@ -116,11 +116,8 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
mOutgoingBuffer = null;
} else { // Otherwise...
final int length = Math.min(buffer.length - mBufferOffset, MAX_PACKET_SIZE);
final byte[] data = new byte[length]; // We send at most 20 bytes
System.arraycopy(buffer, mBufferOffset, data, 0, length);
enqueue(Request.newWriteRequest(mRXCharacteristic, buffer, mBufferOffset, length));
mBufferOffset += length;
mRXCharacteristic.setValue(data);
writeCharacteristic(mRXCharacteristic);
}
}
@@ -158,15 +155,12 @@ public class UARTManager extends BleManager<UARTManagerCallbacks> {
if (!writeRequest) { // no WRITE REQUEST property
final int length = Math.min(buffer.length, MAX_PACKET_SIZE);
final byte[] data = new byte[length]; // We send at most 20 bytes
System.arraycopy(buffer, 0, data, 0, length);
mBufferOffset += length;
mRXCharacteristic.setValue(data);
} else { // there is WRITE REQUEST property
mRXCharacteristic.setValue(buffer);
enqueue(Request.newWriteRequest(mRXCharacteristic, buffer, 0, length));
} else { // there is WRITE REQUEST property, let's try Long Write
mBufferOffset = buffer.length;
enqueue(Request.newWriteRequest(mRXCharacteristic, buffer, 0, buffer.length));
}
writeCharacteristic(mRXCharacteristic);
}
}
}

View File

@@ -83,11 +83,6 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
public void send(final String text) {
mManager.send(text);
}
@Override
public ILogSession getLogSession() {
return super.getLogSession();
}
}
@Override
@@ -138,9 +133,9 @@ public class UARTService extends BleProfileService implements UARTManagerCallbac
}
@Override
protected void onServiceStarted() {
// logger is now available. Assign it to the manager
mManager.setLogger(getLogSession());
public boolean shouldEnableBatteryLevelNotifications(final BluetoothDevice device) {
// No UI in UART profile for Battery Level information
return false;
}
@Override

View File

@@ -51,4 +51,17 @@ public class ParserUtils {
}
return "(0x) " + new String(out);
}
public static String parseDebug(final byte[] data) {
if (data == null || data.length == 0)
return "";
final char[] out = new char[data.length * 2];
for (int j = 0; j < data.length; j++) {
int v = data[j] & 0xFF;
out[j * 2] = HEX_ARRAY[v >>> 4];
out[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return "0x" + new String(out);
}
}