mirror of
https://github.com/aljazceru/Android-nRF-Toolbox.git
synced 2026-01-21 23:54:33 +01:00
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:
@@ -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));
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user