Реалізація захисту від скриншотів екрана у мобільному додатку
Банківський додаток показує баланс, номер рахунку, деталі транзакцій — все це може бути на скриншоті в галереї, прочитано іншим додатком або утекти через облачний бекап. На iOS скриншот автоматично зберігається в Photos. На Android додатки з необхідними дозволами можуть читати MediaStore. Захист від скриншотів — стандартне вимогу у фінтех та медичних додатках.
Android: FLAG_SECURE
Один рядок, який працює:
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE)
FLAG_SECURE робить два речі: забороняє системним інструментам створювати скриншот вікна (кнопка «скриншот» не працює, повертає пустий екран) та позначає поверхню як захищену — інші додатки не можуть захопити вміст через MediaProjection.
Краще місце — onCreate Activity до setContentView. Для Fragment-based додатку на одній Activity — застосовується до всього додатку одразу.
Нюанс: FLAG_SECURE працює для системного API скриншотів. Фізична камера, яка знімає екран — ніщо не блокує програмно.
iOS: UIScreen та WindowScene
На iOS немає прямого еквіваленту FLAG_SECURE. Стандартний підхід — реагувати на скриншот, а не блокувати його.
Виявлення скриншота:
NotificationCenter.default.addObserver(
forName: UIApplication.userDidTakeScreenshotNotification,
object: nil,
queue: .main
) { _ in
// логувати, показати попередження, інвалідувати сесію
}
Перекриття контенту при скриншоті. Скриншот створюється системою до того, як уведомлення дійде в додаток — неможливо заблокувати постфактум. Альтернатива: підписатися на UIScreen.capturedDidChangeNotification (спрацьовує коли починається захват екрана, включаючи AirPlay-дзеркалювання та QuickTime) та преvetively скрити чутливий контент.
NotificationCenter.default.addObserver(
forName: UIScreen.capturedDidChangeNotification,
object: nil,
queue: .main
) { [weak self] _ in
self?.sensitiveView.isHidden = UIScreen.main.isCaptured
}
Працює для запису екрана та дзеркалювання, але не для натискання кнопки скриншота — isCaptured не стає true при одиничному знімку.
Трюк з Keychain та SecureTextField. Для текстових полів з чутливими даними — isSecureTextEntry = true. iOS автоматично розмиває вміст такого поля на скриншотах системного додатку Passbook/Notes та у перемикачі задач.
Overlay-підхід. При переході в фон (sceneWillResignActive) показуємо UIWindow з заглушкою поверх додатку:
func sceneWillResignActive(_ scene: UIScene) {
privacyWindow?.isHidden = false
}
func sceneDidBecomeActive(_ scene: UIScene) {
privacyWindow?.isHidden = true
}
Захищає превю в App Switcher — стандартна практика для фінтех-додатків.
React Native та Flutter
React Native: react-native-flag-secure-android для Android, користувацький нативний модуль для iOS. Для Flutter — пакет flutter_windowmanager на Android, нативний platform channel для iOS overlay.
Термін реалізації: Android FLAG_SECURE + iOS overlay при переході в фон + реакція на capturedDidChangeNotification — близько 1 дня з тестуванням на обох платформах.







