Skip to content

Flutter plugin to enable, disable or toggle screenshot support in your application.

License

Notifications You must be signed in to change notification settings

FlutterPlaza/no_screenshot

no_screenshot

no_screenshot Pub Star on Github Flutter Website

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, and macOS.

Features

Feature Android iOS macOS
Disable screenshot & screen recording
Enable screenshot & screen recording
Toggle screenshot protection
Listen for screenshot events (stream)
Image overlay in app switcher / recents

Note: State is automatically persisted via native SharedPreferences / UserDefaults. You do not need to track didChangeAppLifecycleState.

Installation

Add no_screenshot to your pubspec.yaml:

dependencies:
  no_screenshot: ^0.3.3-beta.1

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');
}

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 Path of the captured screenshot (when available)

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 image to your asset catalog (Runner/Assets.xcassets/image.imageset/)
  • macOS: Add an image named image to your asset catalog (Runner/Assets.xcassets/image.imageset/)

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.

Full Example

Below is a complete example showing all features together. See the full source in example/lib/main.dart.

import 'package:flutter/material.dart';
import 'package:no_screenshot/no_screenshot.dart';
import 'package:no_screenshot/screenshot_snapshot.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'No Screenshot Example',
      theme: ThemeData(
        colorSchemeSeed: Colors.deepPurple,
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  final _noScreenshot = NoScreenshot.instance;
  bool _isMonitoring = false;
  bool _isOverlayImageOn = false;
  ScreenshotSnapshot _latestSnapshot = ScreenshotSnapshot(
    isScreenshotProtectionOn: false,
    wasScreenshotTaken: false,
    screenshotPath: '',
  );

  @override
  void initState() {
    super.initState();
    _noScreenshot.screenshotStream.listen((value) {
      setState(() => _latestSnapshot = value);
      if (value.wasScreenshotTaken) {
        debugPrint('Screenshot taken at path: ${value.screenshotPath}');
      }
    });
  }

  // ── Screenshot Protection ──────────────────────────────────────────

  Future<void> _disableScreenshot() async {
    final result = await _noScreenshot.screenshotOff();
    debugPrint('screenshotOff: $result');
  }

  Future<void> _enableScreenshot() async {
    final result = await _noScreenshot.screenshotOn();
    debugPrint('screenshotOn: $result');
  }

  Future<void> _toggleScreenshot() async {
    final result = await _noScreenshot.toggleScreenshot();
    debugPrint('toggleScreenshot: $result');
  }

  // ── Screenshot Monitoring ──────────────────────────────────────────

  Future<void> _startMonitoring() async {
    await _noScreenshot.startScreenshotListening();
    setState(() => _isMonitoring = true);
  }

  Future<void> _stopMonitoring() async {
    await _noScreenshot.stopScreenshotListening();
    setState(() => _isMonitoring = false);
  }

  // ── Image Overlay ─────────────────────────────────────────────────

  Future<void> _toggleScreenshotWithImage() async {
    final result = await _noScreenshot.toggleScreenshotWithImage();
    debugPrint('toggleScreenshotWithImage: $result');
    setState(() => _isOverlayImageOn = result);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('No Screenshot Example')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          // Screenshot protection buttons
          ElevatedButton(
            onPressed: _disableScreenshot,
            child: const Text('Disable Screenshot'),
          ),
          ElevatedButton(
            onPressed: _enableScreenshot,
            child: const Text('Enable Screenshot'),
          ),
          ElevatedButton(
            onPressed: _toggleScreenshot,
            child: const Text('Toggle Screenshot'),
          ),

          const Divider(),

          // Monitoring buttons
          ElevatedButton(
            onPressed: _startMonitoring,
            child: const Text('Start Monitoring'),
          ),
          ElevatedButton(
            onPressed: _stopMonitoring,
            child: const Text('Stop Monitoring'),
          ),
          Text('Monitoring: $_isMonitoring'),
          Text('Last snapshot: $_latestSnapshot'),

          const Divider(),

          // Image overlay toggle
          ElevatedButton(
            onPressed: _toggleScreenshotWithImage,
            child: const Text('Toggle Image Overlay'),
          ),
          Text('Overlay active: $_isOverlayImageOn'),
        ],
      ),
    );
  }
}

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 @qk7b @T-moz @ggiordan @Musaddiq625 @albertocappellina-intesys @kefeh

License

BSD 3-Clause License. See LICENSE for details.

About

Flutter plugin to enable, disable or toggle screenshot support in your application.

Resources

License

Code of conduct

Contributing

Stars

Watchers

Forks

Packages

No packages published

Contributors 10