Sensors API is an Android platform interface for accessing device hardware sensors. The API provides a unified way to obtain data from the accelerometer, gyroscope, magnetometer, light sensor, and other sensors. According to Google, 2026, over 95% of modern Android devices are equipped with at least three types of sensors, opening up broad opportunities for developing context-aware applications.
Key Takeaways
Sensors API is a software interface of the Android Framework that provides developers with access to a mobile device’s hardware sensors. The API has been part of the Android SDK since version 1.0 and is available through the android.hardware package. The interface abstracts differences between sensor implementations from different manufacturers — Qualcomm, MediaTek, Samsung Exynos — and provides a unified model for working with sensors.
The API allows three key operations: getting a list of available sensors, registering listeners to receive data, and managing the update rate. SensorManager acts as the central access point for all operations. The system notifies the application via the onSensorChanged callback, passing a SensorEvent object with an array of float values.
Over the course of Android’s existence, the API has gone through several stages of development. Version 2.3 (Gingerbread) introduced support for Batch Processing — grouping sensor events to reduce power consumption. Android 4.0 (Ice Cream Sandwich) added virtual sensors Gravity and Linear Acceleration. Starting with Android 8.0, the system restricted background access to sensors for enhanced privacy.
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensorList: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
sensorList.forEach { sensor ->
Log.d("Sensors", "${sensor.name} — ${sensor.type}")
}
Not all devices have the same set of sensors. An application must check the availability of a specific sensor before registering a listener. The Android Emulator supports only a limited set of sensors — accelerometer and magnetometer. Testing other sensors requires a physical device. Starting with Android 12, applications must declare sensor usage in the manifest.
Android classifies all sensors into three categories: Motion, Position, and Environment. Motion sensors include accelerometer, gyroscope, and step counter. Position sensors include magnetometer and orientation. Environment sensors include light, pressure, temperature, and humidity.
| Category | Sensors | Type (constant) | Physical/Virtual |
|---|---|---|---|
| Motion | Accelerometer | TYPE_ACCELEROMETER | Physical |
| Motion | Gyroscope | TYPE_GYROSCOPE | Physical |
| Motion | Step Counter | TYPE_STEP_COUNTER | Physical |
| Motion | Gravity | TYPE_GRAVITY | Virtual |
| Position | Magnetometer | TYPE_MAGNETIC_FIELD | Physical |
| Position | Rotation Vector | TYPE_ROTATION_VECTOR | Virtual |
| Environment | Light | TYPE_LIGHT | Physical |
| Environment | Pressure | TYPE_PRESSURE | Physical |
Accelerometer measures acceleration in m/s² along three axes — X, Y, and Z. Values include gravity (9.8 m/s² along the Z axis at rest). The gyroscope measures angular velocity in rad/s — the device’s rotation speed around each axis. The combination of these two sensors is used in navigation, games, and AR applications.
class SensorActivity : Activity(), SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
textView.text = "X: $x, Y: $y, Z: $z"
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
Magnetometer (TYPE_MAGNETIC_FIELD) measures the magnetic field in microteslas (µT) along three axes. It is used as a digital compass — combined with the accelerometer, it determines the device’s azimuth. Rotation Vector is a virtual sensor that fuses data from the gyroscope, accelerometer, and magnetometer for precise orientation determination.
Light sensor (TYPE_LIGHT) measures the ambient light level in lux (lx). It is used for automatic screen brightness adjustment. The pressure sensor (TYPE_PRESSURE) measures atmospheric pressure in hectopascals (hPa) — used in navigation applications to determine altitude above sea level.
Sensors API is built on a client-server architecture. The application acts as the client, and SensorManager acts as the Android system service. When the application registers a listener via registerListener, SensorManager communicates with the HAL (Hardware Abstraction Layer) — a low-level sensor driver running at the Linux kernel level.
The HAL driver receives raw data from the hardware chip, filters out noise, and passes it up the stack — through the SensorService (system process) to the application. Data is passed as a SensorEvent object containing an array of float values values and a timestamp in nanoseconds. The event rate depends on the selected delivery mode.
When registering a listener, the developer specifies the desired delay between events using the constants SENSOR_DELAY_NORMAL (200 ms), SENSOR_DELAY_UI (60 ms), SENSOR_DELAY_GAME (20 ms), and SENSOR_DELAY_FASTEST (0 ms — maximum rate). The actual rate may differ — the system optimizes power consumption.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(
this,
sensor,
SensorManager.SENSOR_DELAY_GAME
)
Starting with Android 2.3, sensors support batch mode — events are accumulated in a FIFO buffer and delivered in one batch. This allows the processor to stay in sleep mode longer, reducing power consumption by up to 60%. The buffer size depends on the sensor chip and is specified in the Sensor.fifoMaxEventCount field.
SensorManager is a system service available via getSystemService(Context.SENSOR_SERVICE). It provides methods for getting a list of sensors, getting a specific default sensor, and registering/unregistering listeners. SensorManager is a singleton — one instance for the entire application.
Before using a sensor, you must check its availability. The getDefaultSensor(type) method returns null if the sensor is not present on the device. Getting null without checking will result in a NullPointerException when registering a listener. The getSensorList(type) method returns a list of all sensors.
fun checkSensorAvailability(type: Int): Boolean {
val sensorManager =
getSystemService(Context.SENSOR_SERVICE) as SensorManager
return sensorManager.getDefaultSensor(type) != null
}
// Usage:
if (checkSensorAvailability(Sensor.TYPE_GYROSCOPE)) {
Log.d("Sensor", "Gyroscope available")
}
A listener is registered via registerListener(listener, sensor, delay). Important: you must unregister the listener in the onPause() method via unregisterListener(listener). If not done, the application will continue to receive sensor events, draining the battery even in the background. Android 8+ shows a warning in logcat about unregistered listeners.
The onAccuracyChanged(sensor, accuracy) method is called when sensor accuracy changes. Values: SENSOR_STATUS_ACCURACY_HIGH, MEDIUM, LOW, and UNRELIABLE. When receiving UNRELIABLE, sensor data should be ignored until accuracy is restored. For example, the magnetometer requires calibration — shaking the device in a figure-eight pattern.
Let’s look at practical examples of using the Sensors API in Android applications with Kotlin. The first example — determining screen orientation using the accelerometer. The second — reading magnetometer data with calibration. The third — a step detector using the step counter.
A combination of accelerometer and magnetometer is used to determine orientation. The SensorManager.getRotationMatrix() method computes the rotation matrix, and getOrientation() extracts pitch, roll, and azimuth angles. Azimuth — the angle relative to magnetic north in radians.
val gravity = FloatArray(3)
val geomagnetic = FloatArray(3)
val rotationMatrix = FloatArray(9)
val orientation = FloatArray(3)
SensorManager.getRotationMatrix(
rotationMatrix, null, gravity, geomagnetic
)
SensorManager.getOrientation(rotationMatrix, orientation)
// orientation[0] — azimuth, [1] — pitch, [2] — roll
val azimuthDeg = Math.toDegrees(orientation[0].toDouble())
The step counter (TYPE_STEP_COUNTER) returns the total number of steps taken by the user since the last device reboot. The sensor works at the hardware level — it is active even when the application is not running. To get steps per session, you need to save the initial value and calculate the difference.
var initialSteps = 0
var isInitialized = false
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_STEP_COUNTER) {
if (!isInitialized) {
initialSteps = event.values[0].toInt()
isInitialized = true
}
val currentSteps = event.values[0].toInt()
val sessionSteps = currentSteps - initialSteps
Log.d("Steps", "Steps per session: $sessionSteps")
}
}
The light sensor allows adapting the interface to ambient conditions. In low light (less than 10 lx), you can switch to dark mode. In bright sunlight (over 10000 lx), you can increase contrast. A moving average of the last 5 values is used for noise filtering.
Android provides several virtual sensors that do not have a direct hardware counterpart. A virtual sensor computes its readings based on a combination of physical sensors. This reduces the burden on the developer — the system itself implements data fusion algorithms.
The Gravity sensor (TYPE_GRAVITY) extracts the gravitational component from accelerometer readings using a low-pass filter. Linear Acceleration (TYPE_LINEAR_ACCELERATION), on the contrary, removes gravity and leaves only the device’s linear acceleration. The sum of Gravity and Linear Acceleration gives the raw accelerometer readings.
Rotation Vector — the most complex virtual sensor. It combines data from the gyroscope (high-frequency changes), accelerometer (gravity vector), and magnetometer (orientation relative to north). The result is a quaternion describing the absolute orientation of the device in space. It is used in AR applications and VR headsets.
Game Rotation Vector — a simplified version of Rotation Vector without using the magnetometer. This gives lower azimuth accuracy but higher update rate and stability. It is recommended for games where low latency is important rather than absolute orientation relative to north.
Sensors are among the most power-hungry device components. The accelerometer and gyroscope at maximum polling rate can drain the battery in 3–4 hours of continuous operation. Optimizing sensor usage is a critical task for any application using the Sensors API.
Do not use SENSOR_DELAY_FASTEST unnecessarily. For UI animations, SENSOR_DELAY_UI (60 ms) is sufficient. For screen orientation detection — SENSOR_DELAY_NORMAL (200 ms). The higher the rate, the more time the processor spends in an active state. The difference between NORMAL and FASTEST is up to 10x in power consumption.
Starting with Android 8.0 (API 26), background applications receive sensor events at a reduced rate. In Android 12+, background access to Motion and Position sensors requires the BODY_SENSORS_BACKGROUND permission. Unregister the listener when the application goes into the background — this extends device battery life.
Use batch processing via the registerListener(listener, sensor, delay, maxReportLatencyUs) method. The maxReportLatencyUs parameter sets the maximum event delivery latency in microseconds. With a value of 1000000 (1 second), events accumulate in the sensor’s FIFO buffer and are delivered once per second — the processor wakes up less frequently.
Frequently Asked Questions
The minimum set is an accelerometer and a magnetometer. These two sensors are present on over 95% of devices. Gyroscope, light sensor, and proximity sensor — on 70–80% of modern models. Other sensors (pressure, temperature, humidity, step counter) are less common and depend on the device’s price category.
TYPE_ACCELEROMETER returns full acceleration including gravity (9.8 m/s²). TYPE_LINEAR_ACCELERATION returns acceleration excluding gravity — only the device’s motion acceleration. If the device is lying still, the accelerometer will show 9.8 m/s² along the Z axis, while Linear Acceleration will show 0 on all axes.
Use getPackageManager().hasSystemFeature() with the appropriate constants: FEATURE_SENSOR_ACCELEROMETER, FEATURE_SENSOR_GYROSCOPE, FEATURE_SENSOR_PROXIMITY, and others. An alternative way is to call getDefaultSensor(type) and check the result for null. The first method is preferable for checking during initialization.
Raw sensor data contains noise. For smoothing, use a low-pass filter: newValue = alpha * rawValue + (1 — alpha) * previousValue. An alpha coefficient of 0.1–0.3 provides a good balance between responsiveness and smoothness. For the gyroscope, a high-pass filter is also applied to remove zero drift.
Yes, but with limitations. Starting with Android 8.0, the sensor event rate is reduced for background applications. Starting with Android 12, the BODY_SENSORS_BACKGROUND permission is required for background sensor access. For background work, it is recommended to use a Foreground Service with a notification.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also