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
Sensor
interface. - Create its own records extending the
Record
class. - Create a new collector manager extending the
CollectorManager
class, implementing the methods for start and stop the collection. - Create a new service extending the
SensorRecordingService
service, 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).