Реализация датчиков движения в Android-приложении

TRUETECH занимается разработкой, поддержкой и обслуживанием мобильных приложений iOS, Android, PWA. Имеем большой опыт и экспертизу для публикации мобильных приложений в популярные маркеты Google Play, App Store, Amazon, AppGallery и другие.
Разработка и поддержка любых видов мобильных приложений:
Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 1735 услуг
Реализация датчиков движения в Android-приложении
Средняя
от 1 рабочего дня до 3 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_mobile-applications_feedme_467_0.webp
    Разработка мобильного приложения для компании FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Разработка мобильного приложения для компании XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Разработка мобильного приложения для компании RHL
    1054
  • image_mobile-applications_zippy_411_0.webp
    Разработка мобильного приложения для компании ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Разработка мобильного приложения для компании Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Разработка мобильного приложения для компании FLAVORS
    445

Реализация датчиков движения в Android-приложении

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

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

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

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 когда нужно измерять только динамическое ускорение.

Детекция конкретных событий

Определение ходьбы vs езды

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

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

Детекция падения

Для носимых устройств (пожилые люди, шахтёры): свободное падение → magnitude < 0.5g в течение > 300 мс → удар → magnitude > 3g. Это триггер для отправки SOS.

Батч-обновления (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 семплов). При переполнении старые данные вытесняются — учитываем при длительных сессиях.

Сроки

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