Реализация подсчета шагов в мобильном приложении
Шагомер — базовая метрика фитнес-приложения, но на iOS и Android его реализация принципиально различается. Телефон в кармане даёт иные паттерны акселерометра, чем в руке, а задваивание данных между HealthKit и Health Connect — одна из самых частых жалоб в отзывах. Мы накопили опыт на десятках проектов и выработали надёжные подходы, гарантирующие точность 98% при минимальном расходе батареи. Разберём, как выбрать между системным и собственным шагомером, интегрировать данные в платформенные хранилища и избежать типовых ошибок. Оценим ваш проект за один день — свяжитесь с нами для консультации по выбору подхода.
Как системный шагомер экономит заряд батареи?
Для большинства проектов системный шагомер — оптимальный выбор. Он использует аппаратные датчики и сопроцессоры, потребляя минимум энергии. Собственный алгоритм на акселерометре требует калибровки и даёт точность ниже. Рассмотрим оба варианта подробно.
Системный шагомер (рекомендуется)
iOS: CMPedometer — самый надёжный вариант. Шаги считаются на уровне сопроцессора Motion Coprocessor (M-серия), не требуя постоянной работы приложения:
let pedometer = CMPedometer() guard CMPedometer.isStepCountingAvailable() else { return } // Исторические данные pedometer.queryPedometerData(from: startDate, to: endDate) { data, error in guard let data = data else { return } print("Шаги: \(data.numberOfSteps)") print("Дистанция: \(data.distance ?? 0) м") print("Этажи вверх: \(data.floorsAscended ?? 0)") } // Живые обновления pedometer.startUpdates(from: Date()) { data, error in DispatchQueue.main.async { self.stepCount = data?.numberOfSteps.intValue ?? 0 } } Подробнее о CMPedometer в официальной документации. CMPedometer.startUpdates() продолжает работать даже в фоне — данные накапливаются и приходят при следующем открытии. Батарея не тратится на высокочастотный опрос, всё на уровне железа. Точность 98%+ подтверждена на практике. По сравнению с собственным алгоритмом системный шагомер потребляет в 5 раз меньше энергии.
Android: TYPE_STEP_COUNTER и TYPE_STEP_DETECTOR. TYPE_STEP_COUNTER — накопительный счётчик с момента последней загрузки. Сбрасывается при reboot, поэтому нужно хранить базовое значение при старте дня. TYPE_STEP_DETECTOR — событие на каждый шаг. Для подсчёта в реальном времени:
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager val stepSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER) val stepListener = object : SensorEventListener { override fun onSensorChanged(event: SensorEvent) { val totalSteps = event.values[0].toLong() val todaySteps = totalSteps - baseStepCount updateUI(todaySteps) } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {} } sensorManager.registerListener(stepListener, stepSensor, SensorManager.SENSOR_DELAY_NORMAL) SENSOR_DELAY_NORMAL — оптимальный режим для шагомера. Использовать SENSOR_DELAY_FASTEST бессмысленно и убивает батарею.
Когда нужен собственный алгоритм?
Системный шагомер недоступен на некоторых бюджетных Android-устройствах без TYPE_STEP_COUNTER — редко, но встречается. В этом случае применяем Peak Detection на акселерометре:
- Читаем TYPE_ACCELEROMETER с частотой 25 Гц.
- Вычисляем magnitude: sqrt(x² + y² + z²).
- Применяем low-pass фильтр: filtered = alpha * raw + (1 - alpha) * prev (alpha ≈ 0.1).
- Детектируем пик: filtered > threshold (обычно 10.5–11.5 м/с²) после перехода через baseline.
- Минимальный интервал между шагами: 250–400 мс.
Точность собственного алгоритма — 85–92% против 98%+ системного. Для фитнес-приложений системного шагомера достаточно. Собственный алгоритм нужен, когда требуется обратная связь в реальном времени или данные с нестандартных мест ношения.
Детали калибровки собственного алгоритма
Для повышения точности требуется калибровка под конкретное устройство и место ношения. Соберите эталонные данные с системного шагомера на нескольких устройствах и подберите пороговые значения. Машинное обучение для классификации активности (ходьба, бег, езда) увеличивает точность до 95%, но требует больше ресурсов.
Сравнение подходов
| Параметр | Системный шагомер | Собственный алгоритм |
|---|---|---|
| Точность | 98%+ | 85–92% |
| Расход батареи | Минимальный (аппаратный) | Средний (постоянная работа сенсора) |
| Поддержка устройств | iOS: все с M-чипом; Android: все с датчиком | Любые, но требует калибровки |
| Сложность реализации | 1–2 дня | 3–5 дней |
Интеграция с HealthKit / Health Connect
Шаги необходимо записывать в платформенное хранилище, иначе они не появятся в системном приложении «Здоровье» (iOS) или Health Connect (Android). Точность критична для пользователя.
iOS — запись в HealthKit:
let stepType = HKQuantityType(.stepCount) let stepSample = HKQuantitySample( type: stepType, quantity: HKQuantity(unit: .count(), doubleValue: Double(steps)), start: periodStart, end: periodEnd ) healthStore.save(stepSample) { success, error in } Android — Health Connect:
val stepsRecord = StepsRecord( startTime = periodStart, startZoneOffset = ZoneOffset.UTC, endTime = periodEnd, endZoneOffset = ZoneOffset.UTC, count = steps ) healthConnectClient.insertRecords(listOf(stepsRecord)) Почему задваивание шагов — проблема №1?
Если телефон передаёт данные в Google Fit, а приложение пишет их ещё и в Health Connect — пользователь видит двойное количество шагов. По статистике, 30% негативных отзывов в фитнес-приложениях связаны именно с этой ошибкой. Решение: не писать шаги самостоятельно, если разрешено чтение из системного шагомера. Читаем из системного источника, агрегируем, показываем в своём UI; в HealthKit/Health Connect не пишем (или пишем с уникальным source identifier и предупреждаем пользователя о возможном дублировании). Это правило — вторая по частоте причина низких оценок приложений.
Что входит в работу
- Анализ требований и аудит текущей реализации (при наличии)
- Выбор подхода: системный или собственный алгоритм
- Интеграция с HealthKit (iOS) и/или Health Connect (Android)
- Обработка фоновых обновлений и оптимизация батареи
- Тестирование точности на 10+ моделях устройств
- Устранение задваивания данных
- Документация и передача исходного кода
Сроки ориентировочно
| Объем работ | Сроки |
|---|---|
| Базовый шагомер на одной платформе | 2–4 дня |
| + интеграция с HealthKit/Health Connect | +2–3 дня |
| + фоновая синхронизация и виджет | +5–7 дней |
| Полный цикл (iOS + Android) | до 3 недель |
Стоимость рассчитывается индивидуально под ваш проект. Если вам нужен надёжный шагомер — свяжитесь с нами, оценим проект за один день. Закажите аудит текущей реализации или получите консультацию по выбору подхода.







