Розробка мобільного додатку для музею (аудіогід)
Відвідувач бере телефон, підходит до експонату — автоматично починається розповідь. Або сканує QR. Або вводит номер з таблички. Три сценарії, один екран — й все повинно працювати офлайн, тому що музейний Wi-Fi рідко бивав надійним.
Автоматичне визначення експонату
Найцікавіший сценарій — proximity-триггер без дій користувача.
iBeacon / Bluetooth LE. Маячки у кожного експонату (Estimote, Kontakt.io). iOS: CLLocationManager.startRangingBeacons(satisfying:) — отримуємо список маячків з proximity (.immediate / .near / .far) та rssi. Вибираємо найближчий з .immediate та запускаємо аудіо. Важливо: не реагуємо на кожну зміну proximity — debounce 2-3 секунди, інакше аудіо переключається при випадкових флуктуаціях сигналу.
Android: BluetoothLeScanner з фільтром по UUID виробника маячків. AltBeacon library спрощує ranging. Foreground Service потрібен для сканування в фоні — поки додаток активний, достатньо звичайного сканування.
QR-сканування. Резервний варіант. iOS: VNDetectBarcodesRequest (Vision) — швидше ніж AVMetadataOutput для однократного сканування. Android: ML Kit Barcode Scanning. Flutter: mobile_scanner.
Ввід номера вручну. Завжди як фолбек — на випадок севшого Bluetooth або відсутності маячків.
Офлайн-контент та структура даних
Музей з 200 експонатів — це 200 аудіофайлів, зображення та тексти. Разом 300-500 МБ. Стратегія завантаження:
- При першому запуску скачуємо «легковесний» пакет: тексти, превью 200px, метаданні (UUID маячків, номери експонатів)
- Аудіо скачуємо порціонно або по потребі з кешуванням
Структура сховища: CoreData/Room для метаданих експонатів (id, title, beacon_uuid, qr_code, languages). Аудіофайли — в Application Support/filesDir з маппингом id → path. SQLite запит «знайди експонат по UUID маячка» — миттєвий.
Багатомовність: користувач обирає мову на початку. Аудіо та тексти зберігаються з суфіксом мови. Скачуємо лише обрану мову — економимо місце.
Аудіоплеєр експонату
AVPlayer (iOS) / ExoPlayer Media3 (Android) / just_audio (Flutter). Особливості для аудіогіду:
- Автостоп при відході від експонату (proximity повернулась до .far)
- Прогрес зберігається: повернулись до експонату — продовжує з місця паузи
- Швидкість відтворення: 0.8x для літніх відвідувачів, 1.5x для швидких
- Lock screen controls через
MPNowPlayingInfoCenter(iOS) /MediaSession(Android)
Інтерактивна карта експозиції
Карта залів з точками експонатів. Не Google Maps — музей не хочет зовнішніх залежностей та платежів. Використовуємо SVG-карту залів: в додатку це WKWebView з інтерактивним SVG (iOS), WebView (Android) або flutter_svg з GestureDetector (Flutter).
Або нативна реалізація на Canvas/CustomPainter: завантажуємо PNG-карту як підкладку, рисуємо точки експонатів поверх з масштабуванням (pinch-to-zoom).
Поточне місцезнаходження відвідувача на карті — через той же iBeacon ranging: визначаємо зал по набору видимих маячків з сильним сигналом. Не GPS — в будівлі не працює.
CMS для сотрудників музею
Адміністратор оновлює тексти та аудіо без релізу додатку. Бекенд: простий REST API + S3 для медіафайлів. Додаток при запуску перевіряє version маніфесту — якщо змінився, скачує дельту.
Строки: додаток з QR-скануванням, офлайн-контентом, аудіоплеєром та картою залів — 4-6 тижнів. З iBeacon proximity та CMS — 7-9 тижнів.







