The background-sensors library is an Android library that allows to collect data from the IMU sensors (i.e., accelerometer and gyroscope) and the magnetometer (if they are present in the device).
The aim of this library is to ensure the data collection from the requested sensors even when the application is in background and the screen's device is off (i.e., idle device). To do so, the data collection is carried on a foreground service and using a wake lock, as proposed by González-Pérez et al. to ensure a systematic data collection.
To install the library you have to add the dependency in your build.gradle:
dependencies {
implementation 'io.github.geotecinit:background-sensors:1.4.0'
}Tip
If you are considering to create a new library extending the features of
background-sensors, use api instead of implementation. If you are extending the library
directly in an application, implementation should work.
The library has the following requirements:
- A device running Android 5.0 (API level 21) or higher.
- (Optional) For apps targeting an API level 31 or higher and willing to collect data from the sensors at a sampling rate higher than 200Hz, the following permission must be added:
<uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS" />The usage of the library is pretty straightforward. The sensors are defined in the enum BaseSensor, and
the SensorManager can be used to know which ones of them are available in the device.
To manage the data collection, an instance of the ServiceManager must be created injecting
a SensorRecordingService. We offer two implementations of this service: the BaseSensorRecordingService and
the NTPSyncedSensorRecordingService (syncs the system clock with an NTP server to label the collected samples with the most accurate timestamp). Then,
the ServiceManager instance can be used to start and stop the data collection.
To start the data collection, a CollectionConfiguration must be provided, indicating the type of sensor
to collect data from, the sensor delay (i.e., time between samples) and the batch size
(i.e., how many samples to report at the same time). Also, a RecordCallback must be provided to receive the collected data.
The next example illustrates the steps.
public class Demo extends Activity {
private SensorManager sensorManager;
private ServiceManager serviceManager;
protected void onCreate() {
// ...
sensorManager = new SensorManager(context);
serviceManager = new ServiceManager(this, BaseSensorRecordingService.class);
// or...
serviceManager = new ServiceManager(this, NTPSyncedSensorRecordingService.class);
// ...
}
public void setupUI() {
List<Sensor> availableSensors = sensorManager.availableSensors(BaseSensor.values());
// ...
}
public void startCollection(Sensor sensor) {
CollectionConfiguration config = new CollectionConfiguration(
sensor,
android.hardware.SensorManager.SENSOR_DELAY_GAME, // Sensor delay
50 // Batch size
);
serviceManager.startCollection(config, records -> {
// ...
});
}
}Tip
A full example can be found in DemoActivity
As the library uses a foreground service for the data collection, a notification is shown while the service
is working. Starting from Android 13 onwards, the notification will not be show unless the POST_NOTIFICATION
permission is requested. You can do so by calling the serviceManager.enableServiceNotification() method.
The notification has some default texts and icons, but you can override these settings.
To change the notification's texts add these strings to your strings.xml with the desired values:
<resources>
<!-- ... -->
<string name="sensor_recording_channel_description">Sensorization</string> <!-- Channel name -->
<string name="sensorization_notification_title">Sensorization</string> <!-- Notification's title -->
<string name="sensorization_notification_text">Collecting data from sensors</string> <!-- Notification's body text -->
<!-- ... -->
</resources>To change the notification's icon add a drawable named ic_sensor_service.xml
| Value | Description |
|---|---|
ACCELEROMETER |
Represents the accelerometer sensor. |
GYROSCOPE |
Represents the gyroscope sensor. |
MAGNETOMETER |
Represents the magnetometer sensor. |
The BaseSensor enum implements the interface Sensor,
so some methods use Sensor as parameters and return types.
| Method | Return type | Description |
|---|---|---|
availableSensors(Sensor[] sensors) |
List<Sensor> |
From the provided sensors, returns the ones available in the device. |
isSensorAvailable(Sensor sensor) |
boolean |
Returns true if the specified sensor is available in the device . |
| Field | Type | Description |
|---|---|---|
sensor |
Sensor |
Sensor of the collection configuration. |
sensorDelay |
int |
Sampling rate (i.e., time between samples). Use constants defined in the native android.hardware.SensorManager or a value in nanoseconds. |
batchSize |
int |
Quantity of sensor samples to be reported each time. |
Base record of the library. Its purpose is to be extended by other classes to create specific type of records.
| Field | Type | Description |
|---|---|---|
sensor |
Sensor |
Sensor of the collection configuration. |
timestamp |
long |
Timestamp at which the record was collected. |
Specific record for the samples obtained from triaxial sensors (i.e., accelerometer, gyroscope and magnetometer).
| Field | Type | Description |
|---|---|---|
x |
float |
Value of the component x of the sensor. |
y |
float |
Value of the component y of the sensor. |
z |
float |
Value of the component z of the sensor. |
| Method | Return type | Description |
|---|---|---|
onRecordsCollected(List<T> sensors) |
void |
Receives a list of collected records (i.e., sensor samples) . |
T is a generic type, in this case, any type extending the class Record.
| Method | Return type | Description |
|---|---|---|
enableServiceNotification |
void |
Requests permission POST_NOTIFICATION to show the collection service notification in Android 13+. |
startCollection(CollectionConfiguration config, RecordCallback callback) |
void |
Starts data collection for the sensor specified in the configuration. |
stopCollection(Sensor sensor) |
void |
Stops data collection for the specified sensor. |
Important
The collection on a specific sensor can only be started once. This means that
if you want to change the sensorDelay or the batchSize for a sensor that is already being
collected, you must stop the collection first and then start it again with the new configuration.
The library can be extended to support other sensors, for example, the heart rate monitor of a WearOS smartwatch.
To extend the functionality, the developer must follow the next steps:
- Create its own enum of sensors implementing the
Sensorinterface. - Create its own records extending the
Recordclass. - Create a new collector manager extending the
CollectorManagerclass, implementing the methods for start and stop the collection. - Create a new service extending the
SensorRecordingServiceservice, and implement the method to return the collector manager created at 3. Declare the new service into theAndroidManifest.xml. - Ready to go! Just inject the class reference of the new service to the
ServiceManager.
The CollectorManager is an
abstract class the new collectors should extend to obtain data from new sensors.
The CollectorManager
constructor requires a Context and a TimeProvider.
The aim of the TimeProvider
is to be used to set the timestamp of the collected records. A DefaultTimeProvider implementation is
provided in the library, which provides the timestamp taking into account the internal clock of the phone.
However, the developer might be interested to take into account other time, such as the time of a NTP server.
In that case, he/she can create its own TimeProvider.
| Methods | Description |
|---|---|
startCollectingFrom(CollectionConfiguration config, RecordCallback callback) |
Starts the collection with the specified configuration. |
stopCollectingFrom(Sensor sensor) |
Stops the collection of the specified sensor. |
ensureStopCollecting() |
Stops the collection for all sensors that could be being collected. |
For an example implementation you can refer to BaseCollectorManager.
Note
The developer is in charge of requesting the required permissions for the new sources, in case they are needed.
Apache License 2.0
See LICENSE.
The development of this library has been possible thanks to the Spanish Ministry of Universities (grant FPU19/05352).