Merge pull request #95 from NordicSemiconductor/develop

Version 2.9.0
This commit is contained in:
Aleksander Nowakowski
2020-05-26 21:51:46 +02:00
committed by GitHub
71 changed files with 101 additions and 264 deletions

View File

@@ -22,11 +22,11 @@ for bidirectional text communication between devices.
### How to import to Android Studio
The production version of nRF Toolbox depends on
[Android BLE Common Library](https://github.com/NordicSemiconductor/Android-BLE-Common-Library/)
(which depends on [Android BLE Library](https://github.com/NordicSemiconductor/Android-BLE-Library/)).
Both libraries are available on jcenter.
[Android BLE Library](https://github.com/NordicSemiconductor/Android-BLE-Library/) and demonstrates
use of the Android BLE Common Library (ble-common module), which provides parsers for common profiles
adopted by Bluetooth SIG. Both libraries are available on jcenter.
You may also include the BLE Library or BLE Common Library as modules. Clone the library project
You may also include the BLE Library and BLE Common Library as modules. Clone the library project
to the same root folder.
If you are having issue like [#40](https://github.com/NordicSemiconductor/Android-nRF-Toolbox/issues/40)
@@ -66,7 +66,7 @@ different service implementation but still the `BleManager` is used to manage ea
If the [useAutoConnect(boolean)](https://github.com/NordicSemiconductor/Android-BLE-Library/blob/e95a814f4c0ecd08a75e5f0e53c68e2b8dbdf70c/ble/src/main/java/no/nordicsemi/android/ble/ConnectRequest.java#L198)
method returns `true` for a connection, the manager will try to reconnect automatically to the device
if a link was lost. You will also be notified about a device that got away using
`onLinklossOccurred(BluetoothDevice)`.
`onDeviceDisconnected(ConnectionObserver.REASON_LINK_LOSS)`.
The `BleMulticonnectProfileService` implementation, used by Proximity profile, does not save addresses
of connected devices. When the service is killed it will not be able to reconnect to them after it's
@@ -83,7 +83,8 @@ Such approach is not demonstrated in nRF Toolbox.
At last, the `BleManager` can be accessed from a `ViewModel`
(see [Architecture Components](https://developer.android.com/topic/libraries/architecture/index.html)).
Check out the [Android nRF Blinky](https://github.com/NordicSemiconductor/Android-nRF-Blinky) app for sample code.
Check out the [Android nRF Blinky](https://github.com/NordicSemiconductor/Android-nRF-Blinky) app
for sample code.
### Nordic UART Service

View File

@@ -2,14 +2,14 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "no.nordicsemi.android.nrftoolbox"
minSdkVersion 18
targetSdkVersion 29
versionCode 76
versionName "2.8.4"
versionCode 77
versionName "2.9.0"
resConfigs "en"
vectorDrawables.useSupportLibrary = true
@@ -42,15 +42,15 @@ dependencies {
//noinspection GradleDependency
implementation 'com.google.android.gms:play-services-wearable:10.2.0'
implementation 'androidx.appcompat:appcompat:1.2.0-alpha02'
implementation 'androidx.preference:preference:1.1.0'
implementation 'com.google.android.material:material:1.2.0-alpha04'
implementation 'androidx.appcompat:appcompat:1.3.0-alpha01'
implementation 'androidx.preference:preference:1.1.1'
implementation 'com.google.android.material:material:1.2.0-alpha06'
implementation 'no.nordicsemi.android:log:2.2.0'
implementation 'no.nordicsemi.android.support.v18:scanner:1.4.3'
// The DFU Library is imported automatically from jcenter:
implementation 'no.nordicsemi.android:dfu:1.10.0'
implementation 'no.nordicsemi.android:dfu:1.10.3'
// if you desire to build the DFU Library, clone the
// https://github.com/NordicSemiconductor/Android-DFU-Library project into DFULibrary folder,
// add it as a module into the project structure and uncomment the following line
@@ -63,7 +63,7 @@ dependencies {
// Import the BLE Common Library.
// The BLE Common Library depends on BLE Library. It is enough to include the first one.
implementation 'no.nordicsemi.android:ble-common:2.2.0-alpha06'
implementation 'no.nordicsemi.android:ble-common:2.2.0'
// The BLE Common Library may be included from jcenter. If you want to modify the code,
// clone both projects from GitHub and replace the line above with the following
// (and also the according lines in the settings.gradle):

View File

@@ -50,7 +50,7 @@ public abstract class BatteryManager<T extends BatteryManagerCallbacks> extends
@IntRange(from = 0, to = 100) final int batteryLevel) {
log(LogContract.Log.Level.APPLICATION,"Battery Level received: " + batteryLevel + "%");
BatteryManager.this.batteryLevel = batteryLevel;
callbacks.onBatteryLevelChanged(device, batteryLevel);
mCallbacks.onBatteryLevelChanged(device, batteryLevel);
}
@Override

View File

@@ -92,7 +92,7 @@ public class BPMActivity extends BleProfileActivity implements BPMManagerCallbac
@Override
protected LoggableBleManager<BPMManagerCallbacks> initializeManager() {
final BPMManager manager = BPMManager.getBPMManager(getApplicationContext());
manager.setManagerCallbacks(this);
manager.setGattCallbacks(this);
return manager;
}

View File

@@ -99,7 +99,7 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
final float cuffPressure, final int unit,
@Nullable final Float pulseRate, @Nullable final Integer userID,
@Nullable final BPMStatus status, @Nullable final Calendar calendar) {
callbacks.onIntermediateCuffPressureReceived(device, cuffPressure, unit, pulseRate, userID, status, calendar);
mCallbacks.onIntermediateCuffPressureReceived(device, cuffPressure, unit, pulseRate, userID, status, calendar);
}
@Override
@@ -123,7 +123,7 @@ public class BPMManager extends BatteryManager<BPMManagerCallbacks> {
final int unit, @Nullable final Float pulseRate,
@Nullable final Integer userID, @Nullable final BPMStatus status,
@Nullable final Calendar calendar) {
callbacks.onBloodPressureMeasurementReceived(device, systolic, diastolic,
mCallbacks.onBloodPressureMeasurementReceived(device, systolic, diastolic,
meanArterialPressure, unit, pulseRate, userID, status, calendar);
}

View File

@@ -91,7 +91,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
}
/**
* BluetoothGatt callbacks for connection/disconnection, service discovery,
* BluetoothGatt mCallbacks for connection/disconnection, service discovery,
* receiving notification, etc.
*/
private class CGMManagerGattCallback extends BatteryManagerGattCallback {
@@ -129,7 +129,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
.fail((device, status) -> log(Log.WARN, "Could not read CGM Status characteristic"))
.enqueue();
// Set notification and indication callbacks
// Set notification and indication mCallbacks
setNotificationCallback(cgmMeasurementCharacteristic)
.with(new ContinuousGlucoseMeasurementDataCallback() {
@Override
@@ -157,7 +157,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
final CGMRecord record = new CGMRecord(timeOffset, glucoseConcentration, timestamp);
records.put(record.sequenceNumber, record);
callbacks.onCGMValueReceived(device, record);
mCallbacks.onCGMValueReceived(device, record);
}
@Override
@@ -234,11 +234,11 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
//noinspection SwitchStatementWithTooFewBranches
switch (requestCode) {
case RACP_OP_CODE_ABORT_OPERATION:
callbacks.onOperationAborted(device);
mCallbacks.onOperationAborted(device);
break;
default:
recordAccessRequestInProgress = false;
callbacks.onOperationCompleted(device);
mCallbacks.onOperationCompleted(device);
break;
}
}
@@ -247,12 +247,12 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
public void onRecordAccessOperationCompletedWithNoRecordsFound(@NonNull final BluetoothDevice device,
@RACPOpCode final int requestCode) {
recordAccessRequestInProgress = false;
callbacks.onOperationCompleted(device);
mCallbacks.onOperationCompleted(device);
}
@Override
public void onNumberOfRecordsReceived(@NonNull final BluetoothDevice device, final int numberOfRecords) {
callbacks.onNumberOfRecordsRequested(device, numberOfRecords);
mCallbacks.onNumberOfRecordsRequested(device, numberOfRecords);
if (numberOfRecords > 0) {
if (records.size() > 0) {
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
@@ -266,7 +266,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
}
} else {
recordAccessRequestInProgress = false;
callbacks.onOperationCompleted(device);
mCallbacks.onOperationCompleted(device);
}
}
@@ -276,9 +276,9 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
@RACPErrorCode final int errorCode) {
log(Log.WARN, "Record Access operation failed (error " + errorCode + ")");
if (errorCode == RACP_ERROR_OP_CODE_NOT_SUPPORTED) {
callbacks.onOperationNotSupported(device);
mCallbacks.onOperationNotSupported(device);
} else {
callbacks.onOperationFailed(device);
mCallbacks.onOperationFailed(device);
}
}
});
@@ -341,7 +341,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
*/
void clear() {
records.clear();
callbacks.onDataSetCleared(getBluetoothDevice());
mCallbacks.onDataSetCleared(getBluetoothDevice());
}
/**
@@ -354,7 +354,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(getBluetoothDevice());
mCallbacks.onOperationStarted(getBluetoothDevice());
recordAccessRequestInProgress = true;
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
@@ -371,7 +371,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(getBluetoothDevice());
mCallbacks.onOperationStarted(getBluetoothDevice());
recordAccessRequestInProgress = true;
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
@@ -401,7 +401,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(getBluetoothDevice());
mCallbacks.onOperationStarted(getBluetoothDevice());
recordAccessRequestInProgress = true;
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
@@ -421,7 +421,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
if (records.size() == 0) {
getAllRecords();
} else {
callbacks.onOperationStarted(getBluetoothDevice());
mCallbacks.onOperationStarted(getBluetoothDevice());
// Obtain the last sequence number
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
@@ -445,7 +445,7 @@ class CGMManager extends BatteryManager<CGMManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(getBluetoothDevice());
mCallbacks.onOperationStarted(getBluetoothDevice());
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();

View File

@@ -95,14 +95,14 @@ public class CSCManager extends BatteryManager<CSCManagerCallbacks> {
@FloatRange(from = 0) final float totalDistance,
@FloatRange(from = 0) final float distance,
@FloatRange(from = 0) final float speed) {
callbacks.onDistanceChanged(device, totalDistance, distance, speed);
mCallbacks.onDistanceChanged(device, totalDistance, distance, speed);
}
@Override
public void onCrankDataChanged(@NonNull final BluetoothDevice device,
@FloatRange(from = 0) final float crankCadence,
final float gearRatio) {
callbacks.onCrankDataChanged(device, crankCadence, gearRatio);
mCallbacks.onCrankDataChanged(device, crankCadence, gearRatio);
}
@Override

View File

@@ -164,7 +164,7 @@ public class CSCService extends BleProfileService implements CSCManagerCallbacks
private void startForegroundService(){
// when the activity closes we need to show the notification that user is connected to the peripheral sensor
// We start the service as a foreground service as Android 8.0 (Oreo) onwards kills any running background services
final Notification notification = createNotification(R.string.uart_notification_connected_message, 0);
final Notification notification = createNotification(R.string.csc_notification_connected_message, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_ID, notification);
} else {

View File

@@ -82,7 +82,7 @@ public class GlucoseActivity extends BleProfileExpandableListActivity implements
@Override
protected LoggableBleManager<GlucoseManagerCallbacks> initializeManager() {
final GlucoseManager manager = glucoseManager = GlucoseManager.getGlucoseManager(getApplicationContext());
manager.setManagerCallbacks(this);
manager.setGattCallbacks(this);
return manager;
}

View File

@@ -147,7 +147,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
// if there is no context information following the measurement data,
// notify callback about the new record
if (!contextInformationFollows)
callbacks.onDataSetChanged(device);
mCallbacks.onDataSetChanged(device);
});
}
});
@@ -189,7 +189,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
handler.post(() -> {
// notify callback about the new record
callbacks.onDataSetChanged(device);
mCallbacks.onDataSetChanged(device);
});
}
});
@@ -209,10 +209,10 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
//noinspection SwitchStatementWithTooFewBranches
switch (requestCode) {
case RACP_OP_CODE_ABORT_OPERATION:
callbacks.onOperationAborted(device);
mCallbacks.onOperationAborted(device);
break;
default:
callbacks.onOperationCompleted(device);
mCallbacks.onOperationCompleted(device);
break;
}
}
@@ -220,12 +220,12 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
@Override
public void onRecordAccessOperationCompletedWithNoRecordsFound(@NonNull final BluetoothDevice device,
@RACPOpCode final int requestCode) {
callbacks.onOperationCompleted(device);
mCallbacks.onOperationCompleted(device);
}
@Override
public void onNumberOfRecordsReceived(@NonNull final BluetoothDevice device, final int numberOfRecords) {
callbacks.onNumberOfRecordsRequested(device, numberOfRecords);
mCallbacks.onNumberOfRecordsRequested(device, numberOfRecords);
if (numberOfRecords > 0) {
if (records.size() > 0) {
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
@@ -238,7 +238,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
.enqueue();
}
} else {
callbacks.onOperationCompleted(device);
mCallbacks.onOperationCompleted(device);
}
}
@@ -248,9 +248,9 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
@RACPErrorCode final int errorCode) {
log(Log.WARN, "Record Access operation failed (error " + errorCode + ")");
if (errorCode == RACP_ERROR_OP_CODE_NOT_SUPPORTED) {
callbacks.onOperationNotSupported(device);
mCallbacks.onOperationNotSupported(device);
} else {
callbacks.onOperationFailed(device);
mCallbacks.onOperationFailed(device);
}
}
});
@@ -303,7 +303,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
records.clear();
final BluetoothDevice target = getBluetoothDevice();
if (target != null) {
callbacks.onOperationCompleted(target);
mCallbacks.onOperationCompleted(target);
}
}
@@ -320,7 +320,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(target);
mCallbacks.onOperationStarted(target);
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportLastStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
@@ -339,7 +339,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(target);
mCallbacks.onOperationStarted(target);
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportFirstStoredRecord())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
@@ -359,7 +359,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(target);
mCallbacks.onOperationStarted(target);
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.reportNumberOfAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();
@@ -385,7 +385,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
if (records.size() == 0) {
getAllRecords();
} else {
callbacks.onOperationStarted(target);
mCallbacks.onOperationStarted(target);
// obtain the last sequence number
final int sequenceNumber = records.keyAt(records.size() - 1) + 1;
@@ -426,7 +426,7 @@ public class GlucoseManager extends BatteryManager<GlucoseManagerCallbacks> {
return;
clear();
callbacks.onOperationStarted(target);
mCallbacks.onOperationStarted(target);
writeCharacteristic(recordAccessControlPointCharacteristic, RecordAccessControlPointData.deleteAllStoredRecords())
.with((device, data) -> log(LogContract.Log.Level.APPLICATION, "\"" + RecordAccessControlPointParser.parse(data) + "\" sent"))
.enqueue();

View File

@@ -183,7 +183,7 @@ public class HRActivity extends BleProfileActivity implements HRManagerCallbacks
@Override
protected LoggableBleManager<HRManagerCallbacks> initializeManager() {
final HRManager manager = HRManager.getInstance(getApplicationContext());
manager.setManagerCallbacks(this);
manager.setGattCallbacks(this);
return manager;
}

View File

@@ -99,7 +99,7 @@ public class HRManager extends BatteryManager<HRManagerCallbacks> {
@Override
public void onBodySensorLocationReceived(@NonNull final BluetoothDevice device,
@BodySensorLocation final int sensorLocation) {
callbacks.onBodySensorLocationReceived(device, sensorLocation);
mCallbacks.onBodySensorLocationReceived(device, sensorLocation);
}
})
.fail((device, status) -> log(Log.WARN, "Body Sensor Location characteristic not found"))
@@ -118,7 +118,7 @@ public class HRManager extends BatteryManager<HRManagerCallbacks> {
@Nullable final Boolean contactDetected,
@Nullable @IntRange(from = 0) final Integer energyExpanded,
@Nullable final List<Integer> rrIntervals) {
callbacks.onHeartRateMeasurementReceived(device, heartRate, contactDetected, energyExpanded, rrIntervals);
mCallbacks.onHeartRateMeasurementReceived(device, heartRate, contactDetected, energyExpanded, rrIntervals);
}
});
enableNotifications(heartRateCharacteristic).enqueue();

View File

@@ -87,7 +87,7 @@ public class HTManager extends BatteryManager<HTManagerCallbacks> {
@TemperatureUnit final int unit,
@Nullable final Calendar calendar,
@Nullable @TemperatureType final Integer type) {
callbacks.onTemperatureMeasurementReceived(device, temperature, unit, calendar, type);
mCallbacks.onTemperatureMeasurementReceived(device, temperature, unit, calendar, type);
}
});
enableIndications(htCharacteristic).enqueue();

View File

@@ -161,7 +161,7 @@ public class HTService extends BleProfileService implements HTManagerCallbacks {
private void startForegroundService(){
// when the activity closes we need to show the notification that user is connected to the peripheral sensor
// We start the service as a foreground service as Android 8.0 (Oreo) onwards kills any running background services
final Notification notification = createNotification(R.string.uart_notification_connected_message, 0);
final Notification notification = createNotification(R.string.hts_notification_connected_message, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_ID, notification);
} else {

View File

@@ -1,12 +1,13 @@
package no.nordicsemi.android.nrftoolbox.profile;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import android.util.Log;
import no.nordicsemi.android.ble.BleManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import no.nordicsemi.android.ble.BleManagerCallbacks;
import no.nordicsemi.android.ble.LegacyBleManager;
import no.nordicsemi.android.log.ILogSession;
import no.nordicsemi.android.log.LogContract;
import no.nordicsemi.android.log.Logger;
@@ -16,14 +17,14 @@ import no.nordicsemi.android.log.Logger;
*
* @param <T> the callbacks class.
*/
public abstract class LoggableBleManager<T extends BleManagerCallbacks> extends BleManager<T> {
public abstract class LoggableBleManager<T extends BleManagerCallbacks> extends LegacyBleManager<T> {
private ILogSession logSession;
/**
* The manager constructor.
* <p>
* After constructing the manager, the callbacks object must be set with
* {@link #setManagerCallbacks(BleManagerCallbacks)}.
* {@link #setGattCallbacks(BleManagerCallbacks)}.
*
* @param context the context.
*/

View File

@@ -141,7 +141,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
LoggableBleManager<BleManagerCallbacks> manager = bleManagers.get(device);
if (manager == null) {
bleManagers.put(device, manager = initializeManager());
manager.setManagerCallbacks(BleMulticonnectProfileService.this);
manager.setGattCallbacks(BleMulticonnectProfileService.this);
}
manager.setLogger(session);
manager.connect(device)
@@ -162,7 +162,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
* @param device target device to disconnect and forget
*/
public void disconnect(final BluetoothDevice device) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
if (manager != null && manager.isConnected()) {
manager.disconnect().enqueue();
}
@@ -175,7 +175,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
public final boolean isConnected(final BluetoothDevice device) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
return manager != null && manager.isConnected();
}
@@ -186,7 +186,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
* initializing. False otherwise.
*/
public final boolean isReady(final BluetoothDevice device) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
return manager != null && manager.isReady();
}
@@ -197,7 +197,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
*/
@SuppressWarnings("unused")
public final int getConnectionState(final BluetoothDevice device) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
return manager != null ? manager.getConnectionState() : BluetoothGatt.STATE_DISCONNECTED;
}
@@ -210,7 +210,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
@SuppressWarnings("deprecation")
@Deprecated
public int getBatteryValue(final BluetoothDevice device) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
if (manager != null)
return manager.getBatteryValue();
return 0;
@@ -228,27 +228,27 @@ public abstract class BleMulticonnectProfileService extends Service implements B
@Override
public void log(@NonNull final BluetoothDevice device, final int level, final String message) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
if (manager != null)
manager.log(level, message);
}
@Override
public void log(@NonNull final BluetoothDevice device, final int level, @StringRes final int messageRes, final Object... params) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
if (manager != null)
manager.log(level, messageRes, params);
}
@Override
public void log(final int level, @NonNull final String message) {
for (final BleManager<BleManagerCallbacks> manager : bleManagers.values())
for (final BleManager manager : bleManagers.values())
manager.log(level, message);
}
@Override
public void log(final int level, @StringRes final int messageRes, final Object... params) {
for (final BleManager<BleManagerCallbacks> manager : bleManagers.values())
for (final BleManager manager : bleManagers.values())
manager.log(level, messageRes, params);
}
}
@@ -405,7 +405,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
unregisterReceiver(bluetoothStateBroadcastReceiver);
// The managers map may not be empty if the service was killed by the system
for (final BleManager<BleManagerCallbacks> manager : bleManagers.values()) {
for (final BleManager manager : bleManagers.values()) {
// Service is being destroyed, no need to disconnect manually.
manager.close();
manager.log(Log.INFO, "Service destroyed");
@@ -432,7 +432,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
*/
protected void onBluetoothEnabled() {
for (final BluetoothDevice device : managedDevices) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
if (manager != null && !manager.isConnected())
manager.connect(device).enqueue();
}
@@ -598,7 +598,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
* @param device the target device
* @return the BleManager or null
*/
protected BleManager<? extends BleManagerCallbacks> getBleManager(final BluetoothDevice device) {
protected BleManager getBleManager(final BluetoothDevice device) {
return bleManagers.get(device);
}
@@ -617,7 +617,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
protected List<BluetoothDevice> getConnectedDevices() {
final List<BluetoothDevice> list = new ArrayList<>();
for (BluetoothDevice device : managedDevices) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
if (manager != null && manager.isConnected())
list.add(device);
}
@@ -630,7 +630,7 @@ public abstract class BleMulticonnectProfileService extends Service implements B
* @return <code>true</code> if device is connected to the sensor, <code>false</code> otherwise
*/
protected boolean isConnected(final BluetoothDevice device) {
final BleManager<BleManagerCallbacks> manager = bleManagers.get(device);
final BleManager manager = bleManagers.get(device);
return manager != null && manager.isConnected();
}
}

View File

@@ -81,7 +81,7 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
.with(new AlertLevelDataCallback() {
@Override
public void onAlertLevelChanged(@NonNull final BluetoothDevice device, final int level) {
callbacks.onLocalAlarmSwitched(device, level != ALERT_NONE);
mCallbacks.onLocalAlarmSwitched(device, level != ALERT_NONE);
}
});
// After connection, set the Link Loss behaviour on the tag.
@@ -152,7 +152,7 @@ class ProximityManager extends BatteryManager<ProximityManagerCallbacks> {
"\"" + AlertLevelParser.parse(data) + "\" sent"))
.done(device -> {
alertOn = on;
callbacks.onRemoteAlarmSwitched(device, on);
mCallbacks.onRemoteAlarmSwitched(device, on);
})
.fail((device, status) -> log(Log.WARN,
status == FailCallback.REASON_NULL_ATTRIBUTE ?

View File

@@ -47,7 +47,7 @@ import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import no.nordicsemi.android.ble.BleServerManagerCallbacks;
import no.nordicsemi.android.ble.observer.ServerObserver;
import no.nordicsemi.android.log.LogContract;
import no.nordicsemi.android.nrftoolbox.FeaturesActivity;
import no.nordicsemi.android.nrftoolbox.R;
@@ -55,7 +55,7 @@ import no.nordicsemi.android.nrftoolbox.ToolboxApplication;
import no.nordicsemi.android.nrftoolbox.profile.LoggableBleManager;
import no.nordicsemi.android.nrftoolbox.profile.multiconnect.BleMulticonnectProfileService;
public class ProximityService extends BleMulticonnectProfileService implements ProximityManagerCallbacks, BleServerManagerCallbacks {
public class ProximityService extends BleMulticonnectProfileService implements ProximityManagerCallbacks, ServerObserver {
@SuppressWarnings("unused")
private static final String TAG = "ProximityService";
@@ -179,7 +179,7 @@ public class ProximityService extends BleMulticonnectProfileService implements P
@Override
protected void onServiceCreated() {
serverManager = new ProximityServerManager(this);
serverManager.setManagerCallbacks(this);
serverManager.setServerObserver(this);
initializeAlarm();

View File

@@ -78,7 +78,7 @@ public class RSCManager extends BatteryManager<RSCManagerCallbacks> {
final float instantaneousSpeed, final int instantaneousCadence,
@Nullable final Integer strideLength,
@Nullable final Long totalDistance) {
callbacks.onRSCMeasurementReceived(device, running, instantaneousSpeed,
mCallbacks.onRSCMeasurementReceived(device, running, instantaneousSpeed,
instantaneousCadence, strideLength, totalDistance);
}
});

View File

@@ -210,7 +210,7 @@ public class RSCService extends BleProfileService implements RSCManagerCallbacks
private void startForegroundService(){
// when the activity closes we need to show the notification that user is connected to the peripheral sensor
// We start the service as a foreground service as Android 8.0 (Oreo) onwards kills any running background services
final Notification notification = createNotification(R.string.uart_notification_connected_message, 0);
final Notification notification = createNotification(R.string.rsc_notification_connected_message, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_ID, notification);
} else {

View File

@@ -123,7 +123,7 @@ public class TemplateManager extends BatteryManager<TemplateManagerCallbacks> {
@Override
public void onSampleValueReceived(@NonNull final BluetoothDevice device, final int value) {
// Let's lass received data to the service
callbacks.onSampleValueReceived(device, value);
mCallbacks.onSampleValueReceived(device, value);
}
@Override

View File

@@ -137,7 +137,7 @@ public class TemplateService extends BleProfileService implements TemplateManage
private void startForegroundService(){
// when the activity closes we need to show the notification that user is connected to the peripheral sensor
// We start the service as a foreground service as Android 8.0 (Oreo) onwards kills any running background services
final Notification notification = createNotification(R.string.uart_notification_connected_message, 0);
final Notification notification = createNotification(R.string.template_notification_connected_message, 0);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(NOTIFICATION_ID, notification);
} else {

View File

@@ -75,7 +75,7 @@ public class UARTManager extends LoggableBleManager<UARTManagerCallbacks> {
.with((device, data) -> {
final String text = data.getStringValue(0);
log(LogContract.Log.Level.APPLICATION, "\"" + text + "\" received");
callbacks.onDataReceived(device, text);
mCallbacks.onDataReceived(device, text);
});
requestMtu(260).enqueue();
enableNotifications(txCharacteristic).enqueue();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, Nordic Semiconductor
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
~
~ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
~
~ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~
~ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
~ software without specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
~ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
~ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/actionBarColor" >
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<corners android:radius="10dp" />
<solid android:color="#FF000000" />
</shape>
</item>
</ripple>

View File

@@ -24,7 +24,7 @@
android:color="@color/featurePressedColor" >
<item>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<shape>
<corners android:radius="10dp" />
<solid android:color="@color/featureColor" />

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, Nordic Semiconductor
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
~
~ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
~
~ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~
~ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
~ software without specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
~ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
~ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/button_p" android:state_pressed="true"/>
<item android:drawable="@drawable/button_n"/>
</selector>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, Nordic Semiconductor
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
~
~ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
~
~ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~
~ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
~ software without specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
~ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
~ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="10dp" />
<solid android:color="#000000" />
<stroke
android:width="5dp"
android:color="#00000000" />
</shape>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, Nordic Semiconductor
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
~
~ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
~
~ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~
~ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
~ software without specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
~ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
~ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<corners android:radius="10dp" />
<solid android:color="#000000" />
<stroke
android:width="5dp"
android:color="#99009CDE" />
</shape>

View File

@@ -24,7 +24,7 @@
<string name="dfu_feature_title">DFU</string>
<string name="dfu_service_title">nRF Toolbox DFU Proxy</string>
<string name="dfu_settings_title">DFU Settings</string>
<string name="dfu_lib_version">DFU Library version 1.10.0</string>
<string name="dfu_lib_version">DFU Library version 1.10.3</string>
<string name="dfu_feature_title_long">DEVICE FIRMWARE UPDATE</string>
<dimen name="dfu_feature_title_long_margin">-186dp</dimen>

View File

@@ -62,14 +62,6 @@
<item name="android:textAllCaps">false</item>
</style>
<style name="DrawerDivider">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">1dp</item>
<item name="android:background">#E5E5E5</item>
<item name="android:layout_marginTop">8dp</item>
<item name="android:layout_marginBottom">8dp</item>
</style>
<style name="Widget"/>
<style name="Widget.List">

View File

@@ -6,7 +6,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:3.6.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View File

@@ -1,6 +1,6 @@
#Mon Jan 27 13:05:59 CET 2020
#Wed May 06 09:23:52 CEST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip

View File

@@ -5,9 +5,9 @@ include ':app', ':wear', ':common'
// include ':ble', ':ble-common'
// project(':ble').projectDir = file('../Android-BLE-Library/ble')
// project(':ble-common').projectDir = file('../Android-BLE-Common-Library/ble-common')
// project(':ble-common').projectDir = file('../Android-BLE-Library/ble-common')
// Uncomment these lines if you want to import the DFULibrary as a project, not from jcenter:
// include ':dfu'
// project(':dfu').projectDir = file('../DFULibrary/dfu')
// project(':dfu').projectDir = file('../Android-DFU-Library/dfu')

View File

@@ -9,7 +9,7 @@ android {
applicationId "no.nordicsemi.android.nrftoolbox"
minSdkVersion 23
targetSdkVersion 29
versionCode 292847601 // target: 29, version: 2.8.4, build: 74, multi-APK: 01
versionCode 292907701 // target: 29, version: 2.9.0, build: 77, multi-APK: 01
versionName "2.8.4"
resConfigs "en"
}
@@ -37,10 +37,10 @@ configurations.all() { configuration -> exclude group: "org.apache.httpcomponent
dependencies {
implementation project(':common')
implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha01'
implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha03'
implementation 'androidx.percentlayout:percentlayout:1.0.0'
implementation 'com.google.android.support:wearable:2.5.0'
compileOnly 'com.google.android.wearable:wearable:2.5.0'
implementation 'com.google.android.support:wearable:2.7.0'
compileOnly 'com.google.android.wearable:wearable:2.7.0'
implementation 'no.nordicsemi.android.support.v18:scanner:1.4.3'

View File

@@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015, Nordic Semiconductor
~ All rights reserved.
~
~ Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
~
~ 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
~
~ 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the
~ documentation and/or other materials provided with the distribution.
~
~ 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this
~ software without specific prior written permission.
~
~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
~ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
~ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
~ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
~ USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<resources>
<dimen name="big_circle_radius">22dp</dimen>
<dimen name="small_circle_radius">18dp</dimen>
</resources>