Датчики движения в Android: Sensor API, события, батчи

Перегрев устройства из-за неправильной частоты опроса датчиков — типичная проблема. Разряд батареи за час вместо дня. Мы сталкивались с проектом, где sensor fusion выдавал случайные кватернионы на дешёвых телефонах. Решение — правильный выбор виртуальных датчиков и батч-обновлений. Более 5 лет опыта

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Датчики движения в Android: Sensor API, события, батчи
Средний
от 1 дня до 3 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    895
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    782
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1216
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    1079
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    1002
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    597

Перегрев устройства из-за неправильной частоты опроса датчиков — типичная проблема. Разряд батареи за час вместо дня. Мы сталкивались с проектом, где sensor fusion выдавал случайные кватернионы на дешёвых телефонах. Решение — правильный выбор виртуальных датчиков и батч-обновлений. Более 5 лет опыта и более 20 проектов с датчиками движения — за нашими плечами.

Android Sensor Framework предоставляет доступ к 13+ типам датчиков через единый SensorManager. Акселерометр и гироскоп — аппаратные. TYPE_LINEAR_ACCELERATION, TYPE_ROTATION_VECTOR, TYPE_GRAVITY — виртуальные: вычисляются из аппаратных через sensor fusion в firmware. Разница в том, что виртуальные датчики потребляют больше CPU при высокой частоте и могут быть недоступны на бюджетных устройствах. Подробнее — в Android Developer: Sensors Overview. Наш опыт показывает: для точной ориентации используйте TYPE_ROTATION_VECTOR, для линейного ускорения — TYPE_LINEAR_ACCELERATION.

Регистрация и жизненный цикл

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() } } 

Ключевое: unregisterListener строго в onCleared() ViewModel или в onPause() Activity. Забытый listener работает в фоне, жрёт батарею и может крашить приложение при уничтожении Activity.

Частоты опроса: константы и реальность

Константа Номинальная задержка Реальная частота
SENSOR_DELAY_NORMAL 200 мс ~5 Гц
SENSOR_DELAY_UI 60 мс ~16 Гц
SENSOR_DELAY_GAME 20 мс ~50 Гц
SENSOR_DELAY_FASTEST 0 мс максимум железа

С Android API 9 можно задавать произвольный интервал в микросекундах через registerListener(listener, sensor, samplingPeriodUs). Например, 10000 мкс = 100 Гц.

SENSOR_DELAY_FASTEST на Snapdragon 8 Gen 2 даёт до 500 Гц на акселерометре — это нужно только для специализированных приложений (анализ вибраций, балансировка). Для большинства задач 50–100 Гц достаточно.

Почему Sensor Fusion в Android требует калибровки?

Датчики на дешёвых устройствах имеют смещения и шум. Виртуальные датчики (TYPE_ROTATION_VECTOR) используют встроенную калибровку firmware, но на старых ядрах могут дрейфовать. Мы тестируем на аппаратах разных вендоров и при необходимости добавляем свой фильтр (Mahony/Madgwick) для коррекции.

TYPE_ROTATION_VECTOR — кватернион ориентации устройства, вычисленный из акселерометра + гироскопа + магнитометра. Точнее чем делать fusion вручную:

val rotationVector = sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) // В 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° от севера val pitch = Math.toDegrees(orientationAngles[1].toDouble()) // -90 до +90° val roll = Math.toDegrees(orientationAngles[2].toDouble()) // -180 до +180° 

TYPE_LINEAR_ACCELERATION — акселерометр без гравитации (аналог userAcceleration в iOS CoreMotion). Используем вместо TYPE_ACCELEROMETER когда нужно измерять только динамическое ускорение.

Как реализовать детекцию падения?

  1. Используйте акселерометр с частотой 50 Гц.
  2. Примените высокочастотный фильтр для отделения гравитации:
    val gravity = FloatArray(3) val linearAccel = FloatArray(3) val alpha = 0.8f // В onSensorChanged для 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) ) 

    Для носимых устройств (пожилые люди, шахтёры) этот метод отлично работает.

    Как организовать фоновый мониторинг без перерасхода батареи?

    Используйте батч-обновления (maxReportLatencyUs) и JobScheduler для периодической обработки. Виртуальные датчики в фоне лучше не использовать — они потребляют CPU постоянно. Для простой детекции активности (шаги, покой) достаточно акселерометра с частотой 5-10 Гц и батчем в 1 секунду (1000 мс).

    Классификация активностей

    Паттерны: ходьба — регулярные пики 1.5–2.5 м/с² с частотой 1.5–2.5 Гц. Езда — низкочастотные вибрации < 0.5 Гц. Покой — magnitude < 0.1 м/с². Для классификации используйте простой пороговый детектор или модель машинного обучения (например, случайный лес) — это улучшает точность до 95%.

    Батч-обновления (Android 4.4+)

    SensorManager.flush() и параметр maxReportLatencyUs в registerListener позволяют накапливать данные в hardware FIFO и получать пачками. Полезно для фоновых приложений — сенсор копит данные, пока CPU спит, просыпается раз в N секунд, отдаёт всё сразу:

    sensorManager.registerListener( listener, accelerometer, 10_000, // samplingPeriodUs = 100 Гц 500_000 // maxReportLatencyUs = 500 мс batch ) 

    Объём FIFO у разных чипсетов разный (512–4096 семплов). При переполнении старые данные вытесняются — учитываем при длительных сессиях.

    Что входит в работу по интеграции датчиков

    • Анализ — выбор датчиков под сценарий (навигация, трекинг активности, носимые устройства)
    • Архитектура — ViewModel/Service, обработка lifecycle, сенсорная оптимизация батареи
    • Реализация — регистрация, фильтрация, классификация событий (падение, шаги, повороты)
    • Тестирование — на реальных устройствах (5+ моделей с разными чипсетами)
    • Поддержка — документация API, обучение команды, гарантия на код до 6 месяцев

    Сравнение подходов к sensor fusion

    Характеристика TYPE_ROTATION_VECTOR (встроенный) Ручной Madgwick/Mahony
    Точность на дорогих устройствах ±1° ±2-3° после калибровки
    Потребление CPU Низкое Высокое (обновление 200+ раз/с)
    Поддержка на бюджетных телефонах Часто нет Работает везде
    Сложность интеграции Минимальная Требуется настройка параметров

    Наш опыт: для 90% проектов хватает встроенных виртуальных датчиков. Ручной fusion нужен только для AR/VR или работы с устаревшими SoC.

    Сроки

    Базовая интеграция 1–2 датчиков с обработкой данных — от 3 до 5 рабочих дней. Многодатчиковый алгоритм с классификацией активностей, фоновой записью и аналитикой — от 2 до 4 недель. Стоимость рассчитывается индивидуально после анализа требований. Временные рамки уточняем после аудита вашего проекта.

    Наша команда — более 5 лет опыта и более 20 успешных проектов с датчиками движения. Закажите консультацию — оценим feasibility и предложим архитектуру под ваш сценарий. Получите качественную интеграцию с гарантией на код до 6 месяцев.

    Подробнее о Sensor API читайте в официальной документации Android.