This commit is contained in:
Aleksander Nowakowski
2018-04-19 22:19:41 +02:00
12 changed files with 169 additions and 91 deletions

View File

@@ -27,6 +27,8 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
private final static UUID BATTERY_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb"); private final static UUID BATTERY_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A19-0000-1000-8000-00805f9b34fb");
private BluetoothGattCharacteristic mBatteryLevelCharacteristic; private BluetoothGattCharacteristic mBatteryLevelCharacteristic;
/** Last received Battery Level value. */
private Integer mBatteryLevel;
/** /**
* The manager constructor. * The manager constructor.
@@ -41,42 +43,62 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
protected abstract BatteryManagerGattCallback getGattCallback(); protected abstract BatteryManagerGattCallback getGattCallback();
public void readBatteryLevelCharacteristic() { public void readBatteryLevelCharacteristic() {
readCharacteristic(mBatteryLevelCharacteristic) if (isConnected()) {
.with(new BatteryLevelDataCallback() { readCharacteristic(mBatteryLevelCharacteristic)
@Override .with(new BatteryLevelDataCallback() {
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) { @Override
mCallbacks.onBatteryLevelChanged(device, batteryLevel); public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
} mBatteryLevel = batteryLevel;
mCallbacks.onBatteryLevelChanged(device, batteryLevel);
}
@Override @Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, final @NonNull Data data) { public void onInvalidDataReceived(@NonNull final BluetoothDevice device, final @NonNull Data data) {
log(LogContract.Log.Level.WARNING, "Invalid Battery Level data received: " + data); log(LogContract.Log.Level.WARNING, "Invalid Battery Level data received: " + data);
} }
}) })
.fail(status -> log(LogContract.Log.Level.WARNING, "Battery Level characteristic not found")); .fail(status -> log(LogContract.Log.Level.WARNING, "Battery Level characteristic not found"));
}
} }
public void enableBatteryLevelCharacteristicNotifications() { public void enableBatteryLevelCharacteristicNotifications() {
// If the Battery Level characteristic is null, the request will be ignored if (isConnected()) {
enableNotifications(mBatteryLevelCharacteristic) // If the Battery Level characteristic is null, the request will be ignored
.with(new BatteryLevelDataCallback() { enableNotifications(mBatteryLevelCharacteristic)
@Override .with(new BatteryLevelDataCallback() {
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) { @Override
mCallbacks.onBatteryLevelChanged(device, batteryLevel); public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
} mBatteryLevel = batteryLevel;
mCallbacks.onBatteryLevelChanged(device, batteryLevel);
}
@Override @Override
public void onInvalidDataReceived(@NonNull final BluetoothDevice device, final @NonNull Data data) { public void onInvalidDataReceived(@NonNull final BluetoothDevice device, final @NonNull Data data) {
log(LogContract.Log.Level.WARNING, "Invalid Battery Level data received: " + data); log(LogContract.Log.Level.WARNING, "Invalid Battery Level data received: " + data);
} }
}) })
.done(() -> log(LogContract.Log.Level.INFO, "Battery Level notifications enabled")) .done(() -> log(LogContract.Log.Level.INFO, "Battery Level notifications enabled"))
.fail(status -> log(LogContract.Log.Level.WARNING, "Battery Level characteristic not found")); .fail(status -> log(LogContract.Log.Level.WARNING, "Battery Level characteristic not found"));
}
} }
/**
*
*/
public void disableBatteryLevelCharacteristicNotifications() { public void disableBatteryLevelCharacteristicNotifications() {
disableNotifications(mBatteryLevelCharacteristic) if (isConnected()) {
.done(() -> log(LogContract.Log.Level.INFO, "Battery Level notifications disabled")); disableNotifications(mBatteryLevelCharacteristic)
.done(() -> log(LogContract.Log.Level.INFO, "Battery Level notifications disabled"));
}
}
/**
* Returns the last received Battery Level value.
* The value is set to null when the device disconnects.
* @return Battery Level value, in percent.
*/
public Integer getBatteryLevel() {
return mBatteryLevel;
} }
protected abstract class BatteryManagerGattCallback extends BleManagerGattCallback { protected abstract class BatteryManagerGattCallback extends BleManagerGattCallback {
@@ -99,6 +121,7 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
@Override @Override
protected void onDeviceDisconnected() { protected void onDeviceDisconnected() {
mBatteryLevelCharacteristic = null; mBatteryLevelCharacteristic = null;
mBatteryLevel = null;
} }
} }
} }

View File

@@ -35,17 +35,20 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.widget.ListView; import android.widget.ListView;
import android.widget.PopupMenu; import android.widget.PopupMenu;
import android.widget.TextView;
import java.util.UUID; import java.util.UUID;
import no.nordicsemi.android.nrftoolbox.R; import no.nordicsemi.android.nrftoolbox.R;
import no.nordicsemi.android.nrftoolbox.profile.BleProfileService; import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
import no.nordicsemi.android.nrftoolbox.profile.BleProfileServiceReadyActivity; import no.nordicsemi.android.nrftoolbox.profile.BleProfileServiceReadyActivity;
import no.nordicsemi.android.nrftoolbox.proximity.ProximityService;
public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMSBinder> implements PopupMenu.OnMenuItemClickListener { public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMSBinder> implements PopupMenu.OnMenuItemClickListener {
private View mControlPanelStd; private View mControlPanelStd;
private View mControlPanelAbort; private View mControlPanelAbort;
private ListView mRecordsListView; private ListView mRecordsListView;
private TextView mBatteryLevelView;
private CGMSRecordsAdapter mCgmsRecordsAdapter; private CGMSRecordsAdapter mCgmsRecordsAdapter;
private CGMService.CGMSBinder mBinder; private CGMService.CGMSBinder mBinder;
@@ -65,6 +68,7 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
mRecordsListView = findViewById(R.id.list); mRecordsListView = findViewById(R.id.list);
mControlPanelStd = findViewById(R.id.cgms_control_std); mControlPanelStd = findViewById(R.id.cgms_control_std);
mControlPanelAbort = findViewById(R.id.cgms_control_abort); mControlPanelAbort = findViewById(R.id.cgms_control_abort);
mBatteryLevelView = findViewById(R.id.battery);
findViewById(R.id.action_last).setOnClickListener(v -> { findViewById(R.id.action_last).setOnClickListener(v -> {
clearRecords(); clearRecords();
@@ -166,10 +170,15 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
}); });
} }
public void onBatteryLevelChanged(final BluetoothDevice device, final int value) {
mBatteryLevelView.setText(getString(R.string.battery, value));
}
@Override @Override
public void onDeviceDisconnected(final BluetoothDevice device) { public void onDeviceDisconnected(final BluetoothDevice device) {
super.onDeviceDisconnected(device); super.onDeviceDisconnected(device);
setOperationInProgress(false); setOperationInProgress(false);
mBatteryLevelView.setText(R.string.not_available);
} }
@Override @Override
@@ -181,6 +190,7 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
@Override @Override
protected void setDefaultUI() { protected void setDefaultUI() {
clearRecords(); clearRecords();
mBatteryLevelView.setText(R.string.not_available);
} }
@Override @Override
@@ -217,6 +227,7 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
@Override @Override
public void onReceive(final Context context, final Intent intent) { public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction(); final String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(ProximityService.EXTRA_DEVICE);
switch (action) { switch (action) {
case CGMService.BROADCAST_NEW_CGMS_VALUE: { case CGMService.BROADCAST_NEW_CGMS_VALUE: {
@@ -237,6 +248,11 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
// Update GUI // Update GUI
setOperationInProgress(true); setOperationInProgress(true);
break; break;
case CGMService.BROADCAST_BATTERY_LEVEL:
final int batteryLevel = intent.getIntExtra(CGMService.EXTRA_BATTERY_LEVEL, 0);
// Update GUI
onBatteryLevelChanged(device, batteryLevel);
break;
case CGMService.OPERATION_FAILED: case CGMService.OPERATION_FAILED:
// Update GUI // Update GUI
showToast(R.string.gls_operation_failed); showToast(R.string.gls_operation_failed);
@@ -258,6 +274,7 @@ public class CGMSActivity extends BleProfileServiceReadyActivity<CGMService.CGMS
intentFilter.addAction(CGMService.OPERATION_NOT_SUPPORTED); intentFilter.addAction(CGMService.OPERATION_NOT_SUPPORTED);
intentFilter.addAction(CGMService.OPERATION_ABORTED); intentFilter.addAction(CGMService.OPERATION_ABORTED);
intentFilter.addAction(CGMService.OPERATION_FAILED); intentFilter.addAction(CGMService.OPERATION_FAILED);
intentFilter.addAction(CGMService.BROADCAST_BATTERY_LEVEL);
return intentFilter; return intentFilter;
} }
} }

View File

@@ -22,6 +22,10 @@ import no.nordicsemi.android.nrftoolbox.profile.BleProfileService;
public class CGMService extends BleProfileService implements CGMSManagerCallbacks { public class CGMService extends BleProfileService implements CGMSManagerCallbacks {
private static final String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.cgms.ACTION_DISCONNECT"; private static final String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.cgms.ACTION_DISCONNECT";
public static final String BROADCAST_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.BROADCAST_BATTERY_LEVEL";
public static final String EXTRA_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.EXTRA_BATTERY_LEVEL";
public static final String BROADCAST_NEW_CGMS_VALUE = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_NEW_CGMS_VALUE"; public static final String BROADCAST_NEW_CGMS_VALUE = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_NEW_CGMS_VALUE";
public static final String BROADCAST_DATA_SET_CLEAR = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_DATA_SET_CLEAR"; public static final String BROADCAST_DATA_SET_CLEAR = "no.nordicsemi.android.nrftoolbox.cgms.BROADCAST_DATA_SET_CLEAR";
public static final String OPERATION_STARTED = "no.nordicsemi.android.nrftoolbox.cgms.OPERATION_STARTED"; public static final String OPERATION_STARTED = "no.nordicsemi.android.nrftoolbox.cgms.OPERATION_STARTED";
@@ -33,9 +37,6 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
public static final String EXTRA_CGMS_RECORD = "no.nordicsemi.android.nrftoolbox.cgms.EXTRA_CGMS_RECORD"; public static final String EXTRA_CGMS_RECORD = "no.nordicsemi.android.nrftoolbox.cgms.EXTRA_CGMS_RECORD";
public static final String EXTRA_DATA = "no.nordicsemi.android.nrftoolbox.cgms.EXTRA_DATA"; public static final String EXTRA_DATA = "no.nordicsemi.android.nrftoolbox.cgms.EXTRA_DATA";
public static final String BROADCAST_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.BROADCAST_BATTERY_LEVEL";
public static final String EXTRA_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.EXTRA_BATTERY_LEVEL";
private final static int NOTIFICATION_ID = 229; private final static int NOTIFICATION_ID = 229;
private final static int OPEN_ACTIVITY_REQ = 0; private final static int OPEN_ACTIVITY_REQ = 0;
private final static int DISCONNECT_REQ = 1; private final static int DISCONNECT_REQ = 1;
@@ -277,10 +278,10 @@ public class CGMService extends BleProfileService implements CGMSManagerCallback
} }
@Override @Override
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int value) { public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL); final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
broadcast.putExtra(EXTRA_DEVICE, getBluetoothDevice()); broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_BATTERY_LEVEL, value); broadcast.putExtra(EXTRA_BATTERY_LEVEL, batteryLevel);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast); LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
} }
} }

View File

@@ -187,7 +187,7 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
mBatteryLevelView.setText(R.string.not_available); mBatteryLevelView.setText(R.string.not_available);
} }
private void onMeasurementReceived(float speed, float distance, float totalDistance) { private void onMeasurementReceived(final BluetoothDevice device, float speed, float distance, float totalDistance) {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
final int unit = Integer.parseInt(preferences.getString(SettingsFragment.SETTINGS_UNIT, String.valueOf(SettingsFragment.SETTINGS_UNIT_DEFAULT))); final int unit = Integer.parseInt(preferences.getString(SettingsFragment.SETTINGS_UNIT, String.valueOf(SettingsFragment.SETTINGS_UNIT_DEFAULT)));
@@ -223,12 +223,12 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
mSpeedView.setText(String.format(Locale.US, "%.1f", speed)); mSpeedView.setText(String.format(Locale.US, "%.1f", speed));
} }
private void onGearRatioUpdate(final float ratio, final int cadence) { private void onGearRatioUpdate(final BluetoothDevice device, final int cadence, final float ratio) {
mGearRatioView.setText(String.format(Locale.US, "%.1f", ratio));
mCadenceView.setText(String.format(Locale.US, "%d", cadence)); mCadenceView.setText(String.format(Locale.US, "%d", cadence));
mGearRatioView.setText(String.format(Locale.US, "%.1f", ratio));
} }
public void onBatteryLevelChanged(final int value) { public void onBatteryLevelChanged(final BluetoothDevice device, final int value) {
mBatteryLevelView.setText(getString(R.string.battery, value)); mBatteryLevelView.setText(getString(R.string.battery, value));
} }
@@ -236,22 +236,23 @@ public class CSCActivity extends BleProfileServiceReadyActivity<CSCService.CSCBi
@Override @Override
public void onReceive(final Context context, final Intent intent) { public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction(); final String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(CSCService.EXTRA_DEVICE);
if (CSCService.BROADCAST_WHEEL_DATA.equals(action)) { if (CSCService.BROADCAST_WHEEL_DATA.equals(action)) {
final float speed = intent.getFloatExtra(CSCService.EXTRA_SPEED, 0.0f); // [m/s] final float speed = intent.getFloatExtra(CSCService.EXTRA_SPEED, 0.0f); // [m/s]
final float distance = intent.getFloatExtra(CSCService.EXTRA_DISTANCE, 0); final float distance = intent.getFloatExtra(CSCService.EXTRA_DISTANCE, 0);
final float totalDistance = intent.getFloatExtra(CSCService.EXTRA_TOTAL_DISTANCE, 0); final float totalDistance = intent.getFloatExtra(CSCService.EXTRA_TOTAL_DISTANCE, 0);
// Update GUI // Update GUI
onMeasurementReceived(speed, distance, totalDistance); onMeasurementReceived(device, speed, distance, totalDistance);
} else if (CSCService.BROADCAST_CRANK_DATA.equals(action)) { } else if (CSCService.BROADCAST_CRANK_DATA.equals(action)) {
final float ratio = intent.getFloatExtra(CSCService.EXTRA_GEAR_RATIO, 0); final float ratio = intent.getFloatExtra(CSCService.EXTRA_GEAR_RATIO, 0);
final int cadence = intent.getIntExtra(CSCService.EXTRA_CADENCE, 0); final int cadence = intent.getIntExtra(CSCService.EXTRA_CADENCE, 0);
// Update GUI // Update GUI
onGearRatioUpdate(ratio, cadence); onGearRatioUpdate(device, cadence, ratio);
} else if (CSCService.BROADCAST_BATTERY_LEVEL.equals(action)) { } else if (CSCService.BROADCAST_BATTERY_LEVEL.equals(action)) {
final int batteryLevel = intent.getIntExtra(CSCService.EXTRA_BATTERY_LEVEL, 0); final int batteryLevel = intent.getIntExtra(CSCService.EXTRA_BATTERY_LEVEL, 0);
// Update GUI // Update GUI
onBatteryLevelChanged(batteryLevel); onBatteryLevelChanged(device, batteryLevel);
} }
} }
}; };

View File

@@ -261,12 +261,6 @@ public abstract class BleMulticonnectProfileService extends Service implements B
if (!mActivityIsChangingConfiguration) { if (!mActivityIsChangingConfiguration) {
onRebind(); onRebind();
// This method will read the Battery Level value from each connected device, 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.
for (final BleManager<BleManagerCallbacks> manager : mBleManagers.values()) {
if (manager.isConnected())
manager.readBatteryLevel();
}
} }
} }
@@ -286,12 +280,6 @@ public abstract class BleMulticonnectProfileService extends Service implements B
if (!mActivityIsChangingConfiguration) { if (!mActivityIsChangingConfiguration) {
if (!mManagedDevices.isEmpty()) { if (!mManagedDevices.isEmpty()) {
onUnbind(); 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.
for (final BleManager<BleManagerCallbacks> manager : mBleManagers.values()) {
if (manager.isConnected())
manager.disableBatteryLevelNotifications();
}
} else { } else {
// The last activity has disconnected from the service and there are no devices to manage. The service may be stopped. // The last activity has disconnected from the service and there are no devices to manage. The service may be stopped.
stopSelf(); stopSelf();

View File

@@ -136,8 +136,8 @@ public class DeviceAdapter extends RecyclerView.Adapter<DeviceAdapter.ViewHolder
actionButton.setImageResource(on ? R.drawable.ic_stat_notify_proximity_silent : R.drawable.ic_stat_notify_proximity_find); actionButton.setImageResource(on ? R.drawable.ic_stat_notify_proximity_silent : R.drawable.ic_stat_notify_proximity_find);
actionButton.setVisibility(state == BluetoothGatt.STATE_CONNECTED ? View.VISIBLE : View.GONE); actionButton.setVisibility(state == BluetoothGatt.STATE_CONNECTED ? View.VISIBLE : View.GONE);
final int batteryValue = mService.getBatteryLevel(device); final Integer batteryValue = mService.getBatteryLevel(device);
if (batteryValue >= 0) { if (batteryValue != null) {
batteryView.getCompoundDrawables()[0 /*left*/].setLevel(batteryValue); batteryView.getCompoundDrawables()[0 /*left*/].setLevel(batteryValue);
batteryView.setVisibility(View.VISIBLE); batteryView.setVisibility(View.VISIBLE);
batteryView.setText(batteryView.getResources().getString(R.string.battery, batteryValue)); batteryView.setText(batteryView.getResources().getString(R.string.battery, batteryValue));

View File

@@ -23,7 +23,12 @@ package no.nordicsemi.android.nrftoolbox.proximity;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
@@ -50,6 +55,17 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
setGUI(); setGUI();
} }
@Override
protected void onInitialize(final Bundle savedInstanceState) {
LocalBroadcastManager.getInstance(this).registerReceiver(mBroadcastReceiver, makeIntentFilter());
}
@Override
protected void onDestroy() {
super.onDestroy();
LocalBroadcastManager.getInstance(this).unregisterReceiver(mBroadcastReceiver);
}
private void setGUI() { private void setGUI() {
final RecyclerView recyclerView = mDevicesView = findViewById(android.R.id.list); final RecyclerView recyclerView = mDevicesView = findViewById(android.R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setLayoutManager(new LinearLayoutManager(this));
@@ -133,12 +149,12 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
showLinklossDialog(device.getName()); showLinklossDialog(device.getName());
} }
@Override private void onBatteryLevelChanged(final BluetoothDevice device, final int batteryLevel) {
public void onBatteryValueReceived(final BluetoothDevice device, final int value) {
if (mAdapter != null) if (mAdapter != null)
mAdapter.onBatteryValueReceived(device); // Value will be obtained from the service mAdapter.onBatteryValueReceived(device); // Value will be obtained from the service
} }
private void showLinklossDialog(final String name) { private void showLinklossDialog(final String name) {
try { try {
final LinklossFragment dialog = LinklossFragment.getInstance(name); final LinklossFragment dialog = LinklossFragment.getInstance(name);
@@ -147,4 +163,23 @@ public class ProximityActivity extends BleMulticonnectProfileServiceReadyActivit
// the activity must have been destroyed // the activity must have been destroyed
} }
} }
private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(final Context context, final Intent intent) {
final String action = intent.getAction();
final BluetoothDevice device = intent.getParcelableExtra(ProximityService.EXTRA_DEVICE);
if (ProximityService.BROADCAST_BATTERY_LEVEL.equals(action)) {
final int batteryLevel = intent.getIntExtra(ProximityService.EXTRA_BATTERY_LEVEL, 0);
// Update GUI
onBatteryLevelChanged(device, batteryLevel);
}
}
};
private static IntentFilter makeIntentFilter() {
final IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ProximityService.BROADCAST_BATTERY_LEVEL);
return intentFilter;
}
} }

View File

@@ -28,24 +28,19 @@ import android.bluetooth.BluetoothGattService;
import android.content.Context; import android.content.Context;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import java.util.Deque;
import java.util.LinkedList;
import java.util.UUID; import java.util.UUID;
import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.Request;
import no.nordicsemi.android.log.LogContract; import no.nordicsemi.android.log.LogContract;
import no.nordicsemi.android.log.Logger; import no.nordicsemi.android.nrftoolbox.battery.BatteryManager;
import no.nordicsemi.android.nrftoolbox.parser.AlertLevelParser; import no.nordicsemi.android.nrftoolbox.parser.AlertLevelParser;
import no.nordicsemi.android.nrftoolbox.utility.DebugLogger;
public class ProximityManager extends BleManager<ProximityManagerCallbacks> { class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
private final String TAG = "ProximityManager"; private final String TAG = "ProximityManager";
/** Immediate Alert service UUID */ /** Immediate Alert service UUID */
public final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb"); private final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
/** Linkloss service UUID */ /** Linkloss service UUID */
public final static UUID LINKLOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb"); final static UUID LINKLOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb");
/** Alert Level characteristic UUID */ /** Alert Level characteristic UUID */
private static final UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb"); private static final UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb");
@@ -55,9 +50,8 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
private BluetoothGattCharacteristic mAlertLevelCharacteristic, mLinklossCharacteristic; private BluetoothGattCharacteristic mAlertLevelCharacteristic, mLinklossCharacteristic;
private boolean mAlertOn; private boolean mAlertOn;
private int mBatteryLevel;
public ProximityManager(final Context context) { ProximityManager(final Context context) {
super(context); super(context);
} }
@@ -67,17 +61,18 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
} }
@Override @Override
protected BleManagerGattCallback getGattCallback() { protected BatteryManagerGattCallback getGattCallback() {
return mGattCallback; return mGattCallback;
} }
/** /**
* BluetoothGatt callbacks for connection/disconnection, service discovery, receiving indication, etc * BluetoothGatt callbacks for connection/disconnection, service discovery, receiving indication, etc
*/ */
private final BleManagerGattCallback mGattCallback = new BleManagerGattCallback() { private final BatteryManagerGattCallback mGattCallback = new BatteryManagerGattCallback() {
@Override @Override
protected void initialize(@NonNull final BluetoothDevice device) { protected void initialize(@NonNull final BluetoothDevice device) {
super.initialize(device);
writeCharacteristic(mLinklossCharacteristic, HIGH_ALERT); writeCharacteristic(mLinklossCharacteristic, HIGH_ALERT);
} }
@@ -92,6 +87,7 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
@Override @Override
protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) { protected boolean isOptionalServiceSupported(@NonNull final BluetoothGatt gatt) {
super.isOptionalServiceSupported(gatt);
final BluetoothGattService iaService = gatt.getService(IMMEDIATE_ALERT_SERVICE_UUID); final BluetoothGattService iaService = gatt.getService(IMMEDIATE_ALERT_SERVICE_UUID);
if (iaService != null) { if (iaService != null) {
mAlertLevelCharacteristic = iaService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID); mAlertLevelCharacteristic = iaService.getCharacteristic(ALERT_LEVEL_CHARACTERISTIC_UUID);
@@ -101,6 +97,7 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
@Override @Override
protected void onDeviceDisconnected() { protected void onDeviceDisconnected() {
super.onDeviceDisconnected();
mAlertLevelCharacteristic = null; mAlertLevelCharacteristic = null;
mLinklossCharacteristic = null; mLinklossCharacteristic = null;
// Reset the alert flag // Reset the alert flag
@@ -140,12 +137,4 @@ public class ProximityManager extends BleManager<ProximityManagerCallbacks> {
boolean isAlertEnabled() { boolean isAlertEnabled() {
return mAlertOn; return mAlertOn;
} }
/**
* Returns the last obtained Battery Level value in percent.
* @return battery level value
*/
int getBatteryLevel() {
return mBatteryLevel;
}
} }

View File

@@ -21,8 +21,8 @@
*/ */
package no.nordicsemi.android.nrftoolbox.proximity; package no.nordicsemi.android.nrftoolbox.proximity;
import no.nordicsemi.android.ble.BleManagerCallbacks; import no.nordicsemi.android.nrftoolbox.battery.BatteryManagerCallbacks;
public interface ProximityManagerCallbacks extends BleManagerCallbacks { interface ProximityManagerCallbacks extends BatteryManagerCallbacks {
// No additional methods // No additional methods
} }

View File

@@ -42,13 +42,13 @@ import no.nordicsemi.android.nrftoolbox.parser.AlertLevelParser;
import no.nordicsemi.android.nrftoolbox.profile.multiconnect.IDeviceLogger; import no.nordicsemi.android.nrftoolbox.profile.multiconnect.IDeviceLogger;
import no.nordicsemi.android.nrftoolbox.utility.ParserUtils; import no.nordicsemi.android.nrftoolbox.utility.ParserUtils;
public class ProximityServerManager { class ProximityServerManager {
private final String TAG = "ProximityServerManager"; private final String TAG = "ProximityServerManager";
/** Immediate Alert service UUID */ /** Immediate Alert service UUID */
public final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb"); final static UUID IMMEDIATE_ALERT_SERVICE_UUID = UUID.fromString("00001802-0000-1000-8000-00805f9b34fb");
/** Linkloss service UUID */ /** Linkloss service UUID */
public final static UUID LINKLOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb"); final static UUID LINKLOSS_SERVICE_UUID = UUID.fromString("00001803-0000-1000-8000-00805f9b34fb");
/** Alert Level characteristic UUID */ /** Alert Level characteristic UUID */
private static final UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb"); private static final UUID ALERT_LEVEL_CHARACTERISTIC_UUID = UUID.fromString("00002A06-0000-1000-8000-00805f9b34fb");
@@ -70,7 +70,7 @@ public class ProximityServerManager {
void onGattServerFailed(final int error); void onGattServerFailed(final int error);
} }
public ProximityServerManager(final ProximityServerManagerCallbacks callbacks) { ProximityServerManager(final ProximityServerManagerCallbacks callbacks) {
mHandler = new Handler(); mHandler = new Handler();
mCallbacks = callbacks; mCallbacks = callbacks;
} }

View File

@@ -23,9 +23,7 @@ package no.nordicsemi.android.nrftoolbox.proximity;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import no.nordicsemi.android.ble.BleManagerCallbacks; public interface ProximityServerManagerCallbacks {
public interface ProximityServerManagerCallbacks extends BleManagerCallbacks {
void onAlarmTriggered(final BluetoothDevice device); void onAlarmTriggered(final BluetoothDevice device);
void onAlarmStopped(final BluetoothDevice device); void onAlarmStopped(final BluetoothDevice device);

View File

@@ -34,9 +34,11 @@ import android.media.AudioManager;
import android.media.MediaPlayer; import android.media.MediaPlayer;
import android.media.RingtoneManager; import android.media.RingtoneManager;
import android.net.Uri; import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat; import android.support.v4.app.NotificationManagerCompat;
import android.support.v4.content.ContextCompat; import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
@@ -45,7 +47,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import no.nordicsemi.android.ble.BleManager; import no.nordicsemi.android.ble.BleManager;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.log.LogContract; import no.nordicsemi.android.log.LogContract;
import no.nordicsemi.android.nrftoolbox.FeaturesActivity; import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
import no.nordicsemi.android.nrftoolbox.R; import no.nordicsemi.android.nrftoolbox.R;
@@ -56,10 +57,12 @@ public class ProximityService extends BleMulticonnectProfileService implements P
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final String TAG = "ProximityService"; private static final String TAG = "ProximityService";
public static final String BROADCAST_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.BROADCAST_BATTERY_LEVEL";
public static final String EXTRA_BATTERY_LEVEL = "no.nordicsemi.android.nrftoolbox.EXTRA_BATTERY_LEVEL";
private final static String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.proximity.ACTION_DISCONNECT"; private final static String ACTION_DISCONNECT = "no.nordicsemi.android.nrftoolbox.proximity.ACTION_DISCONNECT";
private final static String ACTION_FIND = "no.nordicsemi.android.nrftoolbox.proximity.ACTION_FIND"; private final static String ACTION_FIND = "no.nordicsemi.android.nrftoolbox.proximity.ACTION_FIND";
private final static String ACTION_SILENT = "no.nordicsemi.android.nrftoolbox.proximity.ACTION_SILENT"; private final static String ACTION_SILENT = "no.nordicsemi.android.nrftoolbox.proximity.ACTION_SILENT";
private final static String EXTRA_DEVICE = "no.nordicsemi.android.nrftoolbox.proximity.EXTRA_DEVICE";
private final static String PROXIMITY_GROUP_ID = "proximity_connected_tags"; private final static String PROXIMITY_GROUP_ID = "proximity_connected_tags";
private final static int NOTIFICATION_ID = 1000; private final static int NOTIFICATION_ID = 1000;
@@ -109,9 +112,10 @@ public class ProximityService extends BleMulticonnectProfileService implements P
/** /**
* Returns the last received battery level value. * Returns the last received battery level value.
* @param device the device of which battery level should be returned * @param device the device of which battery level should be returned
* @return battery value or -1 if no value was received or Battery Level characteristic was not found * @return battery value or null if no value was received or Battery Level characteristic was not found,
* or the device is disconnected
*/ */
public int getBatteryLevel(final BluetoothDevice device) { public Integer getBatteryLevel(final BluetoothDevice device) {
final ProximityManager manager = (ProximityManager) getBleManager(device); final ProximityManager manager = (ProximityManager) getBleManager(device);
return manager.getBatteryLevel(); return manager.getBatteryLevel();
} }
@@ -232,10 +236,24 @@ public class ProximityService extends BleMulticonnectProfileService implements P
protected void onRebind() { protected void onRebind() {
// When the activity rebinds to the service, remove the notification // When the activity rebinds to the service, remove the notification
cancelNotifications(); cancelNotifications();
// This method will read the Battery Level value from each connected device, 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.
for (final BluetoothDevice device : getManagedDevices()) {
final ProximityManager manager = (ProximityManager) getBleManager(device);
manager.readBatteryLevelCharacteristic();
manager.enableBatteryLevelCharacteristicNotifications();
}
} }
@Override @Override
public void onUnbind() { public void 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.
for (final BluetoothDevice device : getManagedDevices()) {
final ProximityManager manager = (ProximityManager) getBleManager(device);
manager.disableBatteryLevelCharacteristicNotifications();
}
createBackgroundNotification(); createBackgroundNotification();
} }
@@ -292,6 +310,14 @@ public class ProximityService extends BleMulticonnectProfileService implements P
stopAlarm(device); stopAlarm(device);
} }
@Override
public void onBatteryLevelChanged(@NonNull final BluetoothDevice device, final int batteryLevel) {
final Intent broadcast = new Intent(BROADCAST_BATTERY_LEVEL);
broadcast.putExtra(EXTRA_DEVICE, device);
broadcast.putExtra(EXTRA_BATTERY_LEVEL, batteryLevel);
LocalBroadcastManager.getInstance(this).sendBroadcast(broadcast);
}
private void createBackgroundNotification() { private void createBackgroundNotification() {
final List<BluetoothDevice> connectedDevices = getConnectedDevices(); final List<BluetoothDevice> connectedDevices = getConnectedDevices();
for (final BluetoothDevice device : connectedDevices) { for (final BluetoothDevice device : connectedDevices) {