Meditation App Development
Meditation app looks simple: screens, audio, timer. In reality — precise background playback, system interruptions handling and quiet progress syncing. If audio interrupts on incoming call and doesn't resume — user deletes app in a week.
Audio Player: Background Playback and Interruptions
iOS. AVAudioSession setup — first thing do right:
try AVAudioSession.sharedInstance().setCategory(.playback, mode: .default, options: [.mixWithOthers, .allowAirPlay])
try AVAudioSession.sharedInstance().setActive(true)
Without .playback category audio stops on screen lock. UIBackgroundModes: audio in Info.plist mandatory.
Interruptions (call, Siri, another app): subscribe to AVAudioSession.interruptionNotification. On .began — pause and save position. On .ended with shouldResume == true — resume. Without this logic user after call sees pause, manually taps play — UX broken.
Remote Control (Lock Screen widget): configure MPNowPlayingInfoCenter and MPRemoteCommandCenter. Otherwise locked screen has no controls.
Android. ExoPlayer (Media3) + MediaSessionService (Foreground Service). MediaSession provides system media controls integration. PlayerNotificationManager draws notification with play/pause/next. On Activity destruction player lives in service — user continues meditation with closed app.
Audio focus: AudioFocusRequest with AUDIOFOCUS_GAIN. On focus loss (AUDIOFOCUS_LOSS_TRANSIENT) — ducking or pause depending on user setting.
Flutter. just_audio + audio_service — standard combo. AudioService.init() runs isolate for background playback.
Session Timer and Meditation Structure Management
Meditation — not just audio from start to end. Session structure:
- Opening silence (1-2 min)
- Main part (5-30 min)
- Start/end bell (short audio sample)
- Interval reminders every N minutes
Implement via Combine/Flow/StreamController with timer based on DispatchSourceTimer (iOS) or CountDownTimer+Handler (Android). Important: background timer on iOS works only in Background Task context or paired with audio session. Standalone Timer in background not guaranteed.
Interval bell — not notification but audio insertion into player. AVAudioEngine with AVAudioMixerNode allows mixing background music + bell without main track interruption. On Android — SoundPool for short samples over ExoPlayer via AudioFocus.
Progress and Statistics
Sessions write locally: date, duration, meditation type. SwiftData / Room / Hive. Statistics: day streak, total time this week/month. Reminder — UNUserNotificationCenter / AlarmManager with precise time.
HealthKit (iOS) and Health Connect (Android): record session as HKCategoryTypeIdentifier.mindfulSession / ExerciseSessionRecord(exerciseType = MEDITATION). Users value this — data goes to Apple Health / Google Health.
Content: Offline and DRM
For paid content — download tracks with AES-256 encryption with key tied to account. On iOS: URLSessionDownloadTask + CryptoKit. On Android: DownloadManager + javax.crypto.Cipher. Without DRM user extracts tracks from file system.
Timeline
MVP with player, timer, basic catalog and statistics — 3-4 weeks. With subscription, offline content and HealthKit integration — 6-8 weeks.







