Shake-to-Report — паттерн, при котором пользователь или тестировщик встряхивает устройство и получает форму отправки бага. Автоматически захватываются скриншот и диагностическая информация. Внутри команды он удобнее TestFlight feedback, а для бета-тестеров порог входа намного ниже, чем заполнять форму вручную. Мы внедрили Shake-to-Report в десятках проектов. Это сократило среднее время репорта на 70% — вместо 3 минут пользователь тратит 15 секунд. На одном из проектов с аудиторией 500 000 пользователей после внедрения количество качественных репортов выросло в 3 раза. Типичная боль: тестировщик видит баг, но не может быстро описать контекст. Разработчику приходится переспрашивать. 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 — и ваши тестировщики перестанут тратить время на описание контекста.







