no_screenshot 0.3.6
no_screenshot: ^0.3.6 copied to clipboard
Flutter plugin to enable, disable, toggle or stream screenshot activities in your application.
no_screenshot #
A Flutter plugin to disable screenshots, block screen recording, detect screenshot events, and show a custom image overlay in the app switcher on Android, iOS, macOS, and Linux.
Features #
| Feature | Android | iOS | macOS | Linux |
|---|---|---|---|---|
| Disable screenshot & screen recording | ✅ | ✅ | ✅ | ⚠️ |
| Enable screenshot & screen recording | ✅ | ✅ | ✅ | ⚠️ |
| Toggle screenshot protection | ✅ | ✅ | ✅ | ⚠️ |
| Listen for screenshot events (stream) | ✅ | ✅ | ✅ | ✅ |
| Screenshot file path | ❌ | ❌ | ✅ | ✅ |
| Image overlay in app switcher / recents | ✅ | ✅ | ✅ | ⚠️ |
| LTR & RTL language support | ✅ | ✅ | ✅ | ✅ |
⚠️ Linux limitations: Linux compositors (Wayland / X11) do not expose a
FLAG_SECURE-equivalent API, so screenshot prevention and image overlay are best-effort — the state is tracked and persisted, but the compositor cannot be instructed to hide the window content. Screenshot detection works reliably viaGFileMonitor(inotify).
Note: State is automatically persisted via native SharedPreferences / UserDefaults. You do not need to track
didChangeAppLifecycleState.
Note:
screenshotPathis only available on macOS (via Spotlight /NSMetadataQuery) and Linux (viaGFileMonitor/ inotify). On Android and iOS the path is not accessible due to platform limitations — the field will contain a placeholder string. UsewasScreenshotTakento detect screenshot events on all platforms.
Installation #
Add no_screenshot to your pubspec.yaml:
dependencies:
no_screenshot: ^0.3.6
Then run:
flutter pub get
Quick Start #
import 'package:no_screenshot/no_screenshot.dart';
final noScreenshot = NoScreenshot.instance;
// Disable screenshots & screen recording
await noScreenshot.screenshotOff();
// Re-enable screenshots & screen recording
await noScreenshot.screenshotOn();
// Toggle between enabled / disabled
await noScreenshot.toggleScreenshot();
Usage #
1. Screenshot & Screen Recording Protection #
Block or allow screenshots and screen recording with a single method call.
final _noScreenshot = NoScreenshot.instance;
// Disable screenshots (returns true on success)
Future<void> disableScreenshot() async {
final result = await _noScreenshot.screenshotOff();
debugPrint('screenshotOff: $result');
}
// Enable screenshots (returns true on success)
Future<void> enableScreenshot() async {
final result = await _noScreenshot.screenshotOn();
debugPrint('screenshotOn: $result');
}
// Toggle the current state
Future<void> toggleScreenshot() async {
final result = await _noScreenshot.toggleScreenshot();
debugPrint('toggleScreenshot: $result');
}
Enable / Disable Screenshot
| Android | iOS |
|---|---|
![]() |
![]() |
2. Screenshot Monitoring (Stream) #
Listen for screenshot events in real time. Monitoring is off by default -- you must explicitly start it.
final _noScreenshot = NoScreenshot.instance;
// 1. Subscribe to the stream
_noScreenshot.screenshotStream.listen((snapshot) {
debugPrint('Protection active: ${snapshot.isScreenshotProtectionOn}');
debugPrint('Screenshot taken: ${snapshot.wasScreenshotTaken}');
debugPrint('Path: ${snapshot.screenshotPath}');
});
// 2. Start monitoring
await _noScreenshot.startScreenshotListening();
// 3. Stop monitoring when no longer needed
await _noScreenshot.stopScreenshotListening();
The stream emits a ScreenshotSnapshot object:
| Property | Type | Description |
|---|---|---|
isScreenshotProtectionOn |
bool |
Whether screenshot protection is currently active |
wasScreenshotTaken |
bool |
Whether a screenshot was just captured |
screenshotPath |
String |
File path of the screenshot (macOS & Linux only — see note below) |
Screenshot path availability: The actual file path of a captured screenshot is only available on macOS (via Spotlight /
NSMetadataQuery) and Linux (viaGFileMonitor/ inotify). On Android and iOS, the operating system does not expose the screenshot file path to apps — the field will contain a placeholder string. Always usewasScreenshotTakento detect screenshot events reliably across all platforms.
| Android | iOS |
|---|---|
![]() |
![]() |
macOS Screenshot Monitoring #
On macOS, screenshot monitoring uses three complementary detection methods — no special permissions required:
| Method | What it detects |
|---|---|
NSMetadataQuery (Spotlight) |
Screenshots saved to disk — provides the actual file path |
NSWorkspace process monitor |
screencaptureui process launch & termination — tracks the screenshot lifecycle |
| Pasteboard polling | Clipboard-only screenshots (Cmd+Ctrl+Shift+3/4) — detected when image data appears on the pasteboard while screencaptureui is active or recently exited |
Note: Pasteboard-based detection is scoped to the
screencaptureuiprocess window (running or terminated < 3 s ago) to avoid false positives from normal copy/paste. When "Show Floating Thumbnail" is disabled in macOS screenshot settings, thescreencaptureuiprocess does not launch; in that case only file-saved screenshots are detected viaNSMetadataQuery.
Linux Screenshot Monitoring #
On Linux, screenshot monitoring uses GFileMonitor (inotify) to watch common screenshot directories for new files:
| Directory | Why |
|---|---|
~/Pictures/Screenshots/ |
Default location for GNOME Screenshot and many other tools |
~/Pictures/ |
Fallback — some tools save directly here |
| XDG pictures directory | Respects $XDG_PICTURES_DIR if it differs from ~/Pictures |
Detected screenshot tool naming patterns include: GNOME Screenshot, Spectacle (KDE), Flameshot, scrot, Shutter, maim, and any file containing "screenshot" in its name.
3. Image Overlay (App Switcher / Recents) #
Show a custom image when the app appears in the app switcher or recents screen. This prevents sensitive content from being visible in thumbnails.
final _noScreenshot = NoScreenshot.instance;
// Toggle the image overlay on/off (returns the new state)
Future<void> toggleOverlay() async {
final isActive = await _noScreenshot.toggleScreenshotWithImage();
debugPrint('Image overlay active: $isActive');
}
Setup: Place your overlay image in the platform-specific asset locations:
- Android:
android/app/src/main/res/drawable/image.png - iOS: Add an image named
imageto your asset catalog (Runner/Assets.xcassets/image.imageset/) - macOS: Add an image named
imageto your asset catalog (Runner/Assets.xcassets/image.imageset/) - Linux: Best-effort — the state is tracked but compositors control task switcher thumbnails
When enabled, the overlay image is shown whenever the app goes to the background or appears in the app switcher. Screenshot protection is also automatically activated.
| Android | iOS |
|---|---|
![]() |
![]() |
macOS Demo #
All features (screenshot protection, monitoring, and image overlay) on macOS:
| macOS |
|---|
![]() |
RTL Language Support #
This plugin works correctly with both LTR (left-to-right) and RTL (right-to-left) languages such as Arabic and Hebrew. On iOS 26+, the internal screenshot prevention mechanism uses forceLeftToRight semantics to avoid a layout shift to the right when the device language is set to Arabic or another RTL language (see flutter/flutter#175523).
The example app includes an RTL toggle to verify correct behavior:
| RTL Support (iOS) |
|---|
![]() |
API Reference #
| Method | Return Type | Description |
|---|---|---|
NoScreenshot.instance |
NoScreenshot |
Singleton instance of the plugin |
screenshotOff() |
Future<bool> |
Disable screenshots & screen recording |
screenshotOn() |
Future<bool> |
Enable screenshots & screen recording |
toggleScreenshot() |
Future<bool> |
Toggle screenshot protection on/off |
toggleScreenshotWithImage() |
Future<bool> |
Toggle image overlay mode (returns new state) |
startScreenshotListening() |
Future<void> |
Start monitoring for screenshot events |
stopScreenshotListening() |
Future<void> |
Stop monitoring for screenshot events |
screenshotStream |
Stream<ScreenshotSnapshot> |
Stream of screenshot activity events |
Contributors #
Thanks to everyone who has contributed to this project!
![]() @fonkamloic |
![]() @zhangyuanyuan-bear |
![]() @BranislavKljaic96 |
![]() @qk7b |
![]() @T-moz |
![]() @ggiordan |
![]() @Musaddiq625 |
![]() @albertocappellina-intesys |
![]() @kefeh |
License #
BSD 3-Clause License. See LICENSE for details.
















