Motion Sensors in Android: Sensor API, Events, Batches

Device overheating due to incorrect sensor polling frequency is a typical problem. Battery discharge in an hour instead of a day. We've encountered a project where sensor fusion produced random quaternions on cheap phones. The solution – proper choice of virtual sensors and batch updates. Over 5 yea

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1All 1734 services
Motion Sensors in Android: Sensor API, Events, Batches
Medium
from 1 day to 3 days

Our competencies:

Frequently Asked Questions

Latest works

  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    597

Device overheating due to incorrect sensor polling frequency is a typical problem. Battery discharge in an hour instead of a day. We've encountered a project where sensor fusion produced random quaternions on cheap phones. The solution – proper choice of virtual sensors and batch updates. Over 5 years of experience and over 20 motion sensor projects behind us.

Android Sensor Framework provides access to 13+ sensor types via a single SensorManager. Accelerometer and gyroscope are hardware. TYPE_LINEAR_ACCELERATION, TYPE_ROTATION_VECTOR, TYPE_GRAVITY are virtual: computed from hardware via sensor fusion in firmware. The difference is that virtual sensors consume more CPU at high frequency and may be unavailable on budget devices. More details at Android Developers: Sensors Overview. Our experience: for precise orientation use TYPE_ROTATION_VECTOR, for linear acceleration – TYPE_LINEAR_ACCELERATION.

Registration and Lifecycle

class SensorViewModel(application: Application) : AndroidViewModel(application) { private val sensorManager = application.getSystemService(SENSOR_SERVICE) as SensorManager private val accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) private val gyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE) private val _sensorData = MutableStateFlow<SensorData>(SensorData.Empty) val sensorData: StateFlow<SensorData> = _sensorData.asStateFlow() private val sensorEventListener = object : SensorEventListener { override fun onSensorChanged(event: SensorEvent) { when (event.sensor.type) { Sensor.TYPE_ACCELEROMETER -> handleAccelerometer(event.values) Sensor.TYPE_GYROSCOPE -> handleGyroscope(event.values) } } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {} } fun startListening() { accelerometer?.let { sensorManager.registerListener( sensorEventListener, it, SensorManager.SENSOR_DELAY_GAME // ~20ms ) } } fun stopListening() { sensorManager.unregisterListener(sensorEventListener) } override fun onCleared() { stopListening() } } 

Key: unregisterListener strictly in onCleared() of ViewModel or in onPause() of Activity. A forgotten listener runs in the background, drains battery and can crash the app when Activity is destroyed.

Sampling Rates: Constants and Reality

Constant Nominal Delay Actual Frequency
SENSOR_DELAY_NORMAL 200 ms ~5 Hz
SENSOR_DELAY_UI 60 ms ~16 Hz
SENSOR_DELAY_GAME 20 ms ~50 Hz
SENSOR_DELAY_FASTEST 0 ms maximum hardware rate

Since Android API 9 you can set a custom interval in microseconds via registerListener(listener, sensor, samplingPeriodUs). For example, 10000 µs = 100 Hz.

SENSOR_DELAY_FASTEST on Snapdragon 8 Gen 2 can deliver up to 500 Hz on accelerometer – only needed for specialized applications (vibration analysis, balancing). For most tasks 50–100 Hz is enough.

Why Sensor Fusion in Android Requires Calibration?

Sensors on cheap devices have offsets and noise. Virtual sensors (TYPE_ROTATION_VECTOR) use built-in firmware calibration, but on old kernels they may drift. We test on devices from different vendors and add our own filter (Mahony/Madgwick) if needed.

TYPE_ROTATION_VECTOR – device orientation quaternion computed from accelerometer + gyroscope + magnetometer. More accurate than doing fusion manually:

val rotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) // In onSensorChanged: val rotationMatrix = FloatArray(9) SensorManager.getRotationMatrixFromVector(rotationMatrix, event.values) val orientationAngles = FloatArray(3) SensorManager.getOrientation(rotationMatrix, orientationAngles) val azimuth = Math.toDegrees(orientationAngles[0].toDouble()) // 0-360° from north val pitch = Math.toDegrees(orientationAngles[1].toDouble()) // -90 to +90° val roll = Math.toDegrees(orientationAngles[2].toDouble()) // -180 to +180° 

TYPE_LINEAR_ACCELERATION – accelerometer without gravity (similar to userAcceleration in iOS CoreMotion). Use instead of TYPE_ACCELEROMETER when you need to measure only dynamic acceleration.

How to Implement Fall Detection?

  1. Use accelerometer at 50 Hz.
  2. Apply a high-pass filter to separate gravity:
    val gravity = FloatArray(3) val linearAccel = FloatArray(3) val alpha = 0.8f // In onSensorChanged for TYPE_ACCELEROMETER: gravity[0] = alpha * gravity[0] + (1 - alpha) * event.values[0] gravity[1] = alpha * gravity[1] + (1 - alpha) * event.values[1] gravity[2] = alpha * gravity[2] + (1 - alpha) * event.values[2] linearAccel[0] = event.values[0] - gravity[0] linearAccel[1] = event.values[1] - gravity[1] linearAccel[2] = event.values[2] - gravity[2] val magnitude = sqrt( linearAccel[0].pow(2) + linearAccel[1].pow(2) + linearAccel[2].pow(2) ) 

    For wearable devices (elderly, miners) this method works well.

    How to Organize Background Monitoring Without Excessive Battery Drain?

    Use batch updates (maxReportLatencyUs) and JobScheduler for periodic processing. Avoid virtual sensors in background – they consume CPU constantly. For simple activity detection (steps, stillness) accelerometer at 5-10 Hz with a 1-second batch (1000 ms) is enough.

    Activity Classification

    Patterns: walking – regular peaks 1.5–2.5 m/s² at 1.5–2.5 Hz. Riding – low-frequency vibrations < 0.5 Hz. Still – magnitude < 0.1 m/s². For classification use a simple threshold detector or a machine learning model (e.g., random forest) – this improves accuracy to 95%.

    Batch Updates (Android 4.4+)

    SensorManager.flush() and the maxReportLatencyUs parameter in registerListener allow accumulating data in hardware FIFO and receiving batches. Useful for background apps – sensor collects data while CPU sleeps, wakes up every N seconds, delivers everything at once:

    sensorManager.registerListener( listener, accelerometer, 10_000, // samplingPeriodUs = 100 Hz 500_000 // maxReportLatencyUs = 500 ms batch ) 

    FIFO size varies across chipsets (512–4096 samples). On overflow, old data is replaced – consider this for long sessions.

    What's Included in Sensor Integration Work

    • Analysis – sensor selection for the scenario (navigation, activity tracking, wearables)
    • Architecture – ViewModel/Service, lifecycle handling, sensor battery optimization
    • Implementation – registration, filtering, event classification (fall, steps, turns)
    • Testing – on real devices (5+ models with different chipsets)
    • Support – API documentation, team training, up to 6-month code warranty

    Comparison of Sensor Fusion Approaches

    Characteristic TYPE_ROTATION_VECTOR (built-in) Manual Madgwick/Mahony
    Accuracy on high-end devices ±1° ±2-3° after calibration
    CPU consumption Low High (200+ updates/s)
    Support on budget phones Often missing Works everywhere
    Integration complexity Minimal Requires parameter tuning

    Our experience: for 90% of projects built-in virtual sensors suffice. Manual fusion is only needed for AR/VR or working with outdated SoCs.

    Timeline

    Basic integration of 1–2 sensors with data processing – from 3 to 5 business days. Multi-sensor algorithm with activity classification, background recording and analytics – from 2 to 4 weeks. Cost is calculated individually after requirements analysis. Timeframes are specified after auditing your project.

    Our team has over 5 years of experience and over 20 successful projects with motion sensors. Order a consultation – we'll assess feasibility and propose an architecture for your scenario. Get a quality integration with up to 6-month code warranty.

    For more details on Sensor API, refer to the official Android documentation.