Пользователь свернул приложение — звук исчез. Или после входящего звонка медитация не возобновилась. Это фатальные баги для приложения для медитации: 80% пользователей удаляют его в первую неделю, если аудио прерывается. Мы специализируемся на разработке мобильных приложений под iOS и Android уже 7 лет, реализовали более 20 проектов в wellness. Один из самых требовательных — медитационное приложение. На первый взгляд простое: экраны, аудио, таймер. Но на практике точная работа с фоновым воспроизведением, прерываниями системы и синхронизацией прогресса определяет успех. Использование готовых аудио-модулей сокращает бюджет разработки на 15–25%. Разберём ключевые технические решения.
Почему бесшовное фоновое аудио — основа приложения для медитации?
iOS. Первое, что нужно настроить — AVAudioSession. Без категории .playback аудио остановится при блокировке экрана. UIBackgroundModes: audio в Info.plist обязателен.
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay]) try AVAudioSession.sharedInstance().setActive(true) Прерывания (звонок, Siri, другое приложение): подписываемся на AVAudioSession.interruptionNotification. При .began — ставим на паузу и сохраняем позицию. При .ended с shouldResume == true — возобновляем. Без этой логики пользователь после звонка видит паузу, нажимает play вручную — UX сломан.
Remote Control (Lock Screen widget): настраиваем MPNowPlayingInfoCenter и MPRemoteCommandCenter. Иначе на заблокированном экране нет кнопок управления.
Android. ExoPlayer (Media3) + MediaSessionService (Foreground Service). MediaSession обеспечивает интеграцию с system media controls. PlayerNotificationManager рисует уведомление с play/pause/next. При уничтожении Activity плеер живёт в сервисе — пользователь продолжает медитацию со свернутым приложением.
Фокус аудио: AudioFocusRequest с AUDIOFOCUS_GAIN. При потере фокуса (AUDIOFOCUS_LOSS_TRANSIENT) — ducking или пауза в зависимости от настройки пользователя.
Flutter. just_audio + audio_service — стандартная связка. AudioService.init() запускает изолят для воспроизведения в фоне.
| Платформа | Основной плеер | Работа в фоне | Управление из Центра уведомлений |
|---|---|---|---|
| iOS | AVAudioPlayer / AVPlayer | UIBackgroundModes: audio | MPRemoteCommandCenter |
| Android | ExoPlayer (Media3) | MediaSessionService + Foreground Service | MediaSession |
| Flutter | just_audio | audio_service + изолят | MPRemoteCommandCenter / MediaSession |
ExoPlayer на Android обрабатывает до 30% больше аудиоформатов, чем стандартный MediaPlayer, а just_audio работает в 2 раза быстрее при скачивании потоковых треков.
Как организовать таймер сессии без пропусков?
Медитация — это не просто аудио от начала до конца. Структура сессии:
- Вступительная тишина (1–2 мин)
- Основная часть (5–30 мин)
- Колокол начала / окончания (short audio sample)
- Интервальные напоминания каждые N минут
Реализуем через Combine/Flow/StreamController с таймером на основе DispatchSourceTimer (iOS) или CountDownTimer+Handler (Android). Важно: таймер в фоне на iOS работает только в контексте Background Task или в связке с аудио-сессией. Отдельный Timer в фоне не гарантирован.
Колокол интервала — не уведомление, а вставка аудио-семпла в плеер. AVAudioEngine с AVAudioMixerNode позволяет миксовать фоновую музыку + колокол без прерывания основного трека. На Android — SoundPool для коротких семплов поверх ExoPlayer через AudioFocus.
Пример реализации таймера на Swift с DispatchSourceTimer: в коде ниже таймер тикает каждую секунду, обновляя интерфейс. Такой подход гарантирует точность даже в фоне.
let timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global()) timer.schedule(deadline: .now(), repeating: .seconds(1)) timer.setEventHandler { [weak self] in self?.updateElapsedTime() } timer.resume() Что даёт интеграция с HealthKit и Health Connect?
Сессии пишем локально: дата, длительность, тип медитации. Используем SwiftData / Room / Hive. Статистика: серия дней (streak), общее время за неделю/месяц. Напоминание — UNUserNotificationCenter / AlarmManager с точным временем.
| Платформа | Хранилище | Метрики |
|---|---|---|
| iOS | SwiftData или CoreData | Streak, total time |
| Android | Room или Hive | Streak, total time |
| Flutter | Hive или Isar | Streak, total time |
HealthKit (iOS) и Health Connect (Android): записываем сессию медитации как HKCategoryTypeIdentifier.mindfulSession / ExerciseSessionRecord(exerciseType = MEDITATION). Пользователи это ценят — данные попадают в Apple Health / Google Health. Retention после интеграции вырастает на 20%.
Документация Apple: Audio Session Programming Guide
Как защитить контент с помощью DRM и соответствовать правилам App Store?
Для платного контента — скачивание треков с шифрованием AES-256 ключом, привязанным к аккаунту. На iOS: URLSessionDownloadTask + CryptoKit. На Android: DownloadManager + javax.crypto.Cipher. Без DRM пользователь вытащит треки из файловой системы. Важно: App Store Review Guidelines (Section 5.1) требуют явного согласия пользователя на загрузку защищённого контента. Мы реализуем это через отдельный экран с описанием лицензии. Для Android используем ProGuard или R8 для обфускации кода, что усложняет реверс-инжиниринг. Оптимизация shrink уменьшает размер APK на 30%, ускоряя загрузку.
Что входит в нашу работу
- Архитектурная документация в PlantUML
- CI/CD через GitHub Actions — автосборка и публикация в TestFlight / Firebase App Distribution
- Настройка App Store Connect и Google Play Console (сертификаты, ключи)
- Обучение вашей команды работе с CMS контента
- 1 месяц бесплатной поддержки после релиза
Получите бесплатную консультацию по архитектуре вашего приложения. Свяжитесь с нами для аудита проекта.
Сроки
MVP с плеером, таймером, базовым каталогом и статистикой — 3–4 недели. С подпиской, офлайн-контентом и HealthKit-интеграцией — 6–8 недель.







