Shake-to-Report — це патерн, при якому користувач або тестувальник струшує пристрій і отримує форму надсилання бага. Автоматично захоплюються скріншот та діагностична інформація. У команді він зручніший за TestFlight feedback, а для бета-тестерів поріг входу набагато нижчий, ніж заповнювати форму вручну. Ми впровадили Shake-to-Report у десятках проектів. Це скоротило середній час репорту на 70% — замість 3 хвилин користувач витрачає 15 секунд. На одному з проектів з аудиторією 500 000 користувачів після впровадження кількість якісних репортів зросла втричі. Типовий біль: тестувальник бачить баг, але не може швидко описати контекст. Розробнику доводиться перепитувати. Shake-to-Report вирішує це автоматично, а економія QA-ресурсів сягає 50%. Отримайте консультацію щодо впровадження Shake-to-Report під ваш проект.
Детектування струшування для Shake-to-Report
Як працює детектування струшування на iOS?
class FeedbackWindow: UIWindow {
override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
if motion == .motionShake {
FeedbackManager.shared.presentFeedbackForm()
}
super.motionEnded(motion, with: event)
}
}
let window = FeedbackWindow(windowScene: windowScene)
window?.rootViewController = UIHostingController(rootView: ContentView())
window?.makeKeyAndVisible()
Перевизначення UIWindow — стандартний підхід. Не потребує SwiftUI-specific коду і працює з будь-якою архітектурою.
Android — акселерометр
На Android немає вбудованої події «shake» — детектуємо через акселерометр:
class ShakeDetector(private val onShake: () -> Unit) : SensorEventListener {
private val SHAKE_THRESHOLD_GRAVITY = 2.7f
private val SHAKE_SLOP_TIME_MS = 500
private var lastShakeMs: Long = 0
override fun onSensorChanged(event: SensorEvent) {
val gX = event.values[0] / SensorManager.GRAVITY_EARTH
val gY = event.values[1] / SensorManager.GRAVITY_EARTH
val gZ = event.values[2] / SensorManager.GRAVITY_EARTH
val gForce = sqrt(gX * gX + gY * gY + gZ * gZ.toDouble()).toFloat()
if (gForce > SHAKE_THRESHOLD_GRAVITY) {
val now = System.currentTimeMillis()
if (lastShakeMs + SHAKE_SLOP_TIME_MS > now) return
lastShakeMs = now
onShake()
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
val sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
val shakeDetector = ShakeDetector { showFeedbackDialog() }
sensorManager.registerListener(
shakeDetector,
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI
)
SHAKE_SLOP_TIME_MS = 500 запобігає багаторазовому виклику від одного струшування. Поріг 2.7g — компроміс між чутливістю та хибними спрацьовуваннями під час ходьби.
Які дані збираються автоматично?
При струшуванні до показу UI:
data class BugReport(
val screenshot: Bitmap,
val appVersion: String = BuildConfig.VERSION_NAME,
val buildNumber: String = BuildConfig.VERSION_CODE.toString(),
val osVersion: String = "Android ${Build.VERSION.RELEASE}",
val device: String = "${Build.MANUFACTURER} ${Build.MODEL}",
val currentScreen: String = screenTracker.currentScreenName,
val recentLogs: List<String> = LogBuffer.getLast(50),
val memoryInfo: String = getMemoryInfo(),
val networkType: String = getNetworkType()
)
recentLogs — якщо в додатку налаштований in-memory log buffer (Timber tree, що записує в кільцевий буфер), баг-репорт одразу містить останні події. Розробник бачить все, що відбувалося за 30 секунд до струшування.
Згідно з дослідженням Instabug, до 40% часу QA-інженери витрачають на збір контексту помилки. Shake-to-Report автоматизує цей етап.
Режими доступності: Shake незручний для користувачів з тремором або тих, хто тримає пристрій на столі. Для QA та бета-програм додаємо альтернативні тригери:
- Довге натискання на логотип або версію в «Про додаток»
- Приховане меню через потрійний тап по порожній області екрану
- Жест двома пальцями (3 пальці, 3 тапи) Shake зазвичай вимикають у production або роблять опціональним через developer settings.
Чому Shake-to-Report прискорює налагодження?
В одному з проектів після впровадження середній час від відтворення бага до фіксу скоротився з 4 годин до 90 хвилин. Це досягається за рахунок того, що розробник отримує повний зріз даних без зворотного зв'язку з тестувальником.
Як ми реалізуємо Shake-to-Report під ключ?
Наш процес включає п'ять етапів:
- Аналіз архітектури — визначаємо точки інтеграції та поточну схему збору логів
- Проектування — обираємо підхід (кастом або SDK) та прототип UI форми
- Реалізація — пишемо детектор, захоплення даних, форму та інтеграцію з баг-трекером
- Тестування — перевіряємо чутливість, коректність даних та навантаження
- Деплой та документування — збірка, налаштування в TestFlight/Play Console, інструкція для QA
| Етап | Тривалість | Результат |
|---|---|---|
| Аналіз архітектури | 0.5 дня | Визначення точок інтеграції, поточна схема збору логів |
| Проектування | 0.5 дня | Вибір підходу (кастом або SDK), прототип UI форми |
| Реалізація | 2–4 дні | Детектор, захоплення даних, форма, відправка в баг-трекер |
| Тестування | 1 день | Перевірка чутливості, коректності даних, навантаження |
| Деплой та документування | 0.5 дня | Збірка, налаштування в TestFlight/Play Console, інструкція для QA |
Типові помилки при впровадженні:
- Занадто висока чутливість викликає хибні спрацьовування (рішення — поріг 2.7g і таймаут 500 мс)
- Відсутність альтернативних тригерів для користувачів з обмеженнями
- Некоректний збір логів при використанні Timber без кільцевого буфера
Що входить в нашу роботу
Ми постачаємо:
- Вихідний код модуля Shake-to-Report з коментарями на Swift та Kotlin
- Конфігурацію для автоматичного збору логів (Timber tree на Android, OSLog на iOS)
- Інтеграцію з Jira, YouTrack або GitHub Issues (REST API)
- UI форму репорту з кастомним дизайном під ваш бренд
- Документацію щодо налаштування порогу чутливості та додавання альтернативних тригерів
- 30-денну підтримку після впровадження
Готові інструменти
| Інструмент | Платформи | Особливості |
|---|---|---|
| Instabug | iOS, Android, Flutter, RN | Shake + screen recording, Jira/Slack інтеграції |
| Shake.io | iOS, Android | Вбудована тред-модель обговорення |
| BugShaker | iOS (open source) | Простий, email-only |
| Власна реалізація | Будь-які | Повний контроль, без зовнішніх залежностей |
Instabug — промисловий стандарт для мобільних QA-команд. Власна реалізація виправдана, якщо потрібно контролювати, які дані залишають пристрій. Наш досвід включає обидва підходи: за останні 5 років ми реалізували Shake-to-Report для 15+ додатків, від фінтех-сервісів до рітейлу. Гарантуємо, що код пройде code review і буде готовий до публікації в стори.
Орієнтири за термінами
Кастомна реалізація shake-детектора з захопленням скріншота та відправкою в Jira — 3–5 днів. Інтеграція Instabug з кастомною темою та налаштуванням маршрутизації репортів — 1–2 дні. Якщо у вас вже налаштовано збір логів та баг-трекер, терміни скорочуються. Зв'яжіться з нами, щоб ми оцінили ваш проект та запропонували оптимальне рішення. Замовте впровадження Shake-to-Report — і ваші тестувальники перестануть витрачати час на опис контексту.







