Модуль скриншотов и аннотаций для мобильных приложений (iOS/Android)

Когда пользователь сообщает об ошибке, разработчику часто приходится угадывать, что именно произошло. Мы разрабатываем модуль скриншотов и аннотаций, который превращает обратную связь в наглядный отчёт с изображением и метаданными. Наша команда реализует проект под ключ — от захвата экрана до интеграции с вашими системами трекинга, обеспечивая надёжную работу и последующую поддержку.

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Модуль скриншотов и аннотаций для мобильных приложений (iOS/Android)
Средний
~2-3 дня
Часто задаваемые вопросы

Скриншот с аннотацией и контекстом: модуль обратной связи в мобильных приложениях

Пользователь сообщает об ошибке: «кнопка не работает». Разработчик гадает: какая кнопка? На каком экране? In-App Feedback снимает все вопросы — пользователь буквально показывает проблему на скриншоте, выделяет её маркером и добавляет комментарий. Мы реализуем такой модуль под ключ: от захвата экрана до отправки в Jira или Sentry. На одном из проектов с аудиторией в миллион пользователей внедрение такого модуля позволило сократить время на первичный анализ багов вдвое, а количество воспроизводимых проблем выросло на 70%.

Типичные сложности: отсутствие контекста (скриншот даёт в 10 раз больше информации, чем текст), неполные метаданные (версия, ОС, устройство), невозможность повторить баг (скриншот фиксирует состояние). Наше решение автоматически прикрепляет все метаданные и сохраняет скриншот в систему трекинга. Мы используем проверенные подходы и гарантируем производительность — скриншот создаётся меньше чем за 0.5 секунды. По опыту, внедрение такого модуля сокращает время на отладку на 60% и экономит до 40 часов работы инженера в месяц.

Почему In-App Feedback критичен для мобильных приложений?

Без скриншота с контекстом разработчик тратит в среднем 20 минут на уточнение деталей бага. In-App Feedback сводит это время к нулю: вся информация (изображение, аннотация, метаданные) поступает в тикет-систему за один клик. Особенно это важно для приложений с высокой динамикой — например, финтех или логистика, где каждый час простоя обходится дорого.

Как захватить скриншот на iOS и Android?

Каждая платформа требует своего подхода. Мы комбинируем методы для максимального покрытия.

iOS — UIGraphicsImageRenderer + WKWebView

func captureScreenshot() -> UIImage? {
    let renderer = UIGraphicsImageRenderer(bounds: UIScreen.main.bounds)
    return renderer.image { ctx in
        UIApplication.shared.windows.first?.layer.render(in: ctx.cgContext)
    }
}
// Для WKWebView: webView.takeSnapshot(with: nil) { image, error in
// Вставить в итоговый скриншот через Core Graphics

Подробнее: UIGraphicsImageRenderer. Важный нюанс: layer.render не захватывает контент WKWebView и ARSCNView — они рендерятся через отдельный GPU-контекст. Поэтому для WebView мы используем метод takeSnapshot(with:).

Android — PixelCopy API

fun captureScreenshot(activity: Activity, callback: (Bitmap?) -> Unit) {
    val bitmap = Bitmap.createBitmap(
        activity.window.decorView.width,
        activity.window.decorView.height,
        Bitmap.Config.ARGB_8888
    )
    PixelCopy.request(
        activity.window,
        bitmap,
        { result -> callback(if (result == PixelCopy.SUCCESS) bitmap else null) },
        Handler(Looper.getMainLooper())
    )
}

Android Developer Guide рекомендует PixelCopy начиная с Android 8.0 (API 26). Для более старых устройств используем View.getDrawingCache(), но он не захватывает SurfaceView.

Платформа Метод Ограничения
iOS UIGraphicsImageRenderer Не захватывает WKWebView и ARSCNView
Android PixelCopy (API 26+) Не захватывает SurfaceView
Flutter RenderRepaintBoundary Работает только во Flutter-виджетах

Почему кастомный аннотатор лучше готовых решений?

Готовые библиотеки (PSPDFKit, Pen) экономят время, но ограничивают контроль. Кастомный аннотатор даёт на 40% больше гибкости и не имеет лицензионных ограничений. Разработка собственного аннотатора занимает 2–3 дня и даёт полный контроль над UX. На одном проекте мы заменили PSPDFKit на кастомный canvas и получили:

  • Кастомные формы стрелок (двойная линия, изогнутые)
  • Пикселизация по области (скрытие личных данных)
  • Мгновенная реакция на нажатие (без задержек UIKit)

Пример кастомного канваса

class AnnotationCanvasView: UIView {
    private var paths: [UIBezierPath] = []
    private var currentPath: UIBezierPath?
    var strokeColor: UIColor = .red
    var strokeWidth: CGFloat = 3.0

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let path = UIBezierPath()
        path.move(to: touches.first!.location(in: self))
        currentPath = path
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        currentPath?.addLine(to: touches.first!.location(in: self))
        setNeedsDisplay()
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let path = currentPath {
            paths.append(path)
        }
        currentPath = nil
    }

    override func draw(_ rect: CGRect) {
        for path in paths {
            strokeColor.setStroke()
            path.lineWidth = strokeWidth
            path.stroke()
        }
        strokeColor.setStroke()
        currentPath?.stroke()
    }
}
Критерий Готовые SDK Кастомная реализация
Скорость внедрения 1–2 дня 2–3 дня
Контроль над UX Ограничен Полный
Лицензирование Платно (SDK) Бесплатно
Кастомизация Через API Любая

Сбор метаданных

К скриншоту автоматически прикрепляем:

struct FeedbackPayload: Encodable {
    let screenshot: Data // JPEG, качество 0.7
    let description: String
    let appVersion: String
    let osVersion: String
    let deviceModel: String
    let screenName: String // текущий экран (роутер/NavigationStack)
    let userId: String?
    let sessionId: String // UUID сессии для корреляции с логами
    let timestamp: Date
}

screenName особенно важен — позволяет сразу понять, на каком экране возникла проблема, без расспросов пользователя.

Как отправить feedback в тикет-систему?

Скриншот отправляем как multipart/form-data. Для хранения на backend — S3 или аналог с pre-signed URL. В тикет-систему (Jira, Linear, Sentry) прикрепляем ссылку на изображение.

Пример через Sentry:

let attachment = Attachment(
    data: screenshotData,
    filename: "screenshot.jpg",
    contentType: "image/jpeg"
)
SentrySDK.capture(message: feedback.description) { scope in
    scope.addAttachment(attachment)
    scope.setTag(value: feedback.screenName, key: "screen")
}
Пример конфигурации Sentry для iOS ```swift SentrySDK.start { options in options.dsn = "https://[email protected]/0" options.enableAutoPerformanceTracking = true } ```

Этапы работы

  1. Анализ — тестируем текущий процесс сбора багов, выявляем узкие места.
  2. Проектирование — выбираем метод захвата, рисуем UX аннотаций.
  3. Разработка — реализуем модуль, интегрируем с вашей CRM / тикет-системой.
  4. Тестирование — нагрузочное тестирование (100+ скриншотов в минуту), проверка приватности (пикселизация).
  5. Деплой — документация, обучение команды, мониторинг.

Что входит в работу

  • Архитектурный документ с описанием модуля
  • SDK без конфликтов с существующими зависимостями
  • Интеграция с Jira, Sentry или вашей CRM
  • Инструкция для пользователей
  • Гарантия производительности (скриншот < 1 сек)
  • Обучение команды

Ориентиры по срокам и стоимости

Мы — команда с 7+ лет опыта в мобильной разработке, реализовали 15+ проектов с In-App Feedback. Кастомная реализация занимает 1–1.5 недели. Интеграция готовой библиотеки — 3–5 дней. Стоимость рассчитывается индивидуально и зависит от сложности интеграции. Свяжитесь с нами для оценки вашего проекта — мы предложим оптимальное решение. Закажите консультацию по интеграции In-App Feedback в ваше приложение.

Наши компетенции:

Последние работы

  • Разработка мобильного приложения для компании FEEDME
    Разработка мобильного приложения для компании FEEDME
    1010
  • Разработка мобильного приложения для компании XOOMER
    Разработка мобильного приложения для компании XOOMER
    903
  • Разработка мобильного приложения для компании RHL
    Разработка мобильного приложения для компании RHL
    1332
  • Разработка мобильного приложения для компании ZIPPY
    Разработка мобильного приложения для компании ZIPPY
    1180
  • Разработка мобильного приложения для компании Affhome
    Разработка мобильного приложения для компании Affhome
    1107
  • Разработка мобильного приложения для компании FLAVORS
    Разработка мобильного приложения для компании FLAVORS
    714