Представьте: пользователь вводит PIN в банковском приложении, а в это время на устройстве запущен screen recorder — вредоносное ПО или даже «родная» запись экрана. Зафиксировать могут не только код, но и процесс авторизации, просмотр конфиденциальных документов. Мы сталкивались с такими сценариями десятки раз и знаем, как защитить приложение от этой угрозы. Запись экрана — более серьёзная угроза, чем скриншот, так как позволяет захватить динамический ввод и анимации. На iOS встроенный Screen Recorder и AirPlay-миррoring работают системно, а на Android MediaProjection API доступен сторонним приложениям с разрешения пользователя (но вредоносное ПО получает его обманом). Наш опыт — 5+ лет в мобильной безопасности, десятки проектов с защитой чувствительных данных.
Как работает FLAG_SECURE на Android?
FLAG_SECURE — основной инструмент защиты на Android, но он бесполезен против HDMI capture card или физической камеры, направленной на экран. Это ограничение самой платформы, с которым нужно мириться или использовать DRM (например, Widevine). Для остальных сценариев флаг надёжно блокирует MediaProjection API.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE
)
setContentView(R.layout.activity_main)
}
Флаг блокирует захват через MediaProjection: запись экрана получит чёрный прямоугольник вместо содержимого Activity. Работает для системного рекордера и сторонних приложений, использующих MediaProjection API. Для Jetpack Compose — тот же подход на уровне Activity, Compose контент находится внутри того же Window. Android Developer Documentation: WindowManager.LayoutParams.FLAG_SECURE
Как обнаружить запись экрана на iOS?
iOS не предоставляет API для блокировки записи, но дает мощный инструмент обнаружения — UIScreen.isCaptured и UIScreen.capturedDidChangeNotification. Мы используем его в каждом проекте с защитой контента. isCaptured возвращает true при активной встроенной записи, AirPlay-миррoring или захвате через QuickTime. При этом он не срабатывает для скриншота одного кадра — это важное отличие от Android FLAG_SECURE. Правильная реакция — не крэш, не логаут, а скрытие чувствительного контента:
private var cancellables = Set<AnyCancellable>()
func setupScreenCaptureProtection() {
NotificationCenter.default.publisher(
for: UIScreen.capturedDidChangeNotification
)
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
self?.updateContentVisibility()
}
.store(in: &cancellables)
// проверяем текущее состояние при запуске
updateContentVisibility()
}
private func updateContentVisibility() {
let isBeingRecorded = UIScreen.main.isCaptured
sensitiveContainerView.isHidden = isBeingRecorded
if isBeingRecorded {
recordingWarningView.isHidden = false
}
}
recordingWarningView — замена-заглушка, которую пользователь видит при записи вместо данных. Это и защита, и UX-объяснение почему контент скрылся.
SwiftUI вариант
struct SensitiveContentView: View {
@State private var isScreenBeingRecorded = UIScreen.main.isCaptured
var body: some View {
Group {
if isScreenBeingRecorded {
RecordingBlockerView()
} else {
ActualSensitiveContent()
}
}
.onReceive(
NotificationCenter.default.publisher(
for: UIScreen.capturedDidChangeNotification
)
) { _ in
isScreenBeingRecorded = UIScreen.main.isCaptured
}
}
}
Flutter и React Native
Оба кросс-платформенных фреймворка требуют нативных плагинов для этой функциональности. Flutter: flutter_windowmanager на Android выставляет FLAG_SECURE. Для iOS нужен platform channel с нативной Swift реализацией — готовых надёжных пакетов нет, пишем сами. React Native: react-native-flag-secure-android для Android, для iOS — нативный модуль через NativeModules.
Аудит переключателя задач
| Платформа | Механизм защиты App Switcher | Примечание |
|---|---|---|
| iOS | Оверлейное View в sceneWillResignActive |
Требует программного перекрытия |
| Android | FLAG_SECURE |
Работает автоматически |
iOS: перекрываем оверлейным View в sceneWillResignActive:
func sceneWillResignActive(_ scene: UIScene) {
overlayView.isHidden = false
}
func sceneDidBecomeActive(_ scene: UIScene) {
overlayView.isHidden = true
}
Android: FLAG_SECURE покрывает и этот кейс — App Switcher превью тоже будет чёрным.
Сравнение подходов: FLAG_SECURE vs UIScreen.isCaptured
| Характеристика | FLAG_SECURE (Android) | UIScreen.isCaptured (iOS) |
|---|---|---|
| Тип защиты | Блокировка захвата | Обнаружение и реакция |
| Производительность | 0% overhead | Минимальная задержка (1–2 мс) |
| Защита от аппаратного захвата | Нет | Нет |
| Простота внедрения | Один флаг в Kotlin | Подписка на уведомления в Swift |
| Покрытие (скриншоты) | Да | Только видео |
FLAG_SECURE в 3 раза быстрее реагирует на захват, чем polling альтернатив, но не покрывает hardware-атаки. На iOS обнаружение срабатывает мгновенно (<10 мс после начала записи).
Наш подход к реализации: что входит в работу
Мы предлагаем реализацию защиты под ключ. В стоимость входит:
- Аудит текущей архитектуры приложения на уязвимости захвата экрана.
- Проектирование защиты: выбор оптимальных методов под ваш фреймворк и версию SDK.
- Реализация на нативном коде (Swift/Kotlin) или через плагины для Flutter/React Native.
- Тестирование на 5 реальных устройствах с разными версиями ОС.
- Документация по архитектуре защиты и инструкция для разработчиков.
- Обучающий вебинар для команды (30 минут).
Сроки: 1–3 дня в зависимости от количества экранов с чувствительным контентом. Утечка PIN-кода через запись экрана может обойтись бизнесу в миллионы рублей — инвестиция в 30–60 тысяч рублей оправдана многократно. Получите консультацию — мы оценим проект бесплатно и предложим оптимальное решение.
Полная реализация защиты от записи экрана на Android + iOS, включая защиту App Switcher превью и обработку состояния isCaptured — 1–3 дня в зависимости от фреймворка и количества экранов с чувствительным контентом. Свяжитесь с нами, чтобы начать. Мы гарантируем внедрение без багов и полную консультацию по поддержке.







