screen_privacy 0.0.2+2 copy "screen_privacy: ^0.0.2+2" to clipboard
screen_privacy: ^0.0.2+2 copied to clipboard

Safeguard sensitive app content on both Android and iOS devices

screen_privacy #

This plugin provides functionalities to prevent screenshots and hide app content in the recent apps preview for both Android and iOS platforms. This can be useful for apps displaying sensitive information or media content.

Usage #

Installation #

Add screen_privacy as a dependency in your pubspec.yaml file.

Import #

import 'package:screen_privacy/screen_privacy.dart';

And then you can simply call functions of ScreenPrivacy class instance anywhere

Fine-grained Screenshot Control: #

  • Disable Screenshoting: ScreenPrivacy().disableScreenshot();
  • Enable Screenshoting: ScreenPrivacy().enableScreenshot();

Recent App Preview Management: #

  • Hide App Content: ScreenPrivacy().enablePrivacyScreen();
  • Reveal App Content: ScreenPrivacy().disablePrivacyScreen();

Use Case with AutoRoute #

This example showcases the utilization of the ScreenPrivacy plugin within an AutoRoute-based application, constructed with AutoTabsScaffold and BottomNavigationBar. It enables the selective prevention of screenshotting and concealment of app content in the recent apps preview specifically for a designated page. The functionality is limited to a single page, toggling between disabling/enabling screenshotting and hiding/revealing content in the recent apps preview. Note that once the page is navigated away from or a different tab route is accessed, this feature will cease to operate.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:auto_route/auto_route.dart';
import 'package:screen_privacy/screen_privacy.dart';

mixin ScreenPrivacyMixin<T extends StatefulWidget> on State<T> {
  TabsRouter? _watcher;
  AppLifecycleListener? _listener;
  VoidCallback? _navigationListener;
  bool _isNavigatedToDifferentTabRoute = false;
  bool _isIOSLifecycleUnblockedScreenshot = false;
  late final String _routeName;
  late final ScreenPrivacy _screenPrivacy;

  bool blockScreenshot();

  bool enablePrivacyScreen();

  @override
  void initState() {
    super.initState();
    _screenPrivacy = ScreenPrivacy();
    _listener = Platform.isIOS && enablePrivacyScreen()
            ? AppLifecycleListener(onStateChange: _onLifecycleChanged)
            : null;

    WidgetsBinding.instance.addPostFrameCallback(_initializer);
  }

  void _initializer(Duration timeStamp) {
    _routeName = context.router.current.name;
    final shouldListenNavigation =
            blockScreenshot() || (Platform.isAndroid && enablePrivacyScreen());

    if (Platform.isAndroid) {
      if (enablePrivacyScreen()) {
        _screenPrivacy.enablePrivacyScreen();
      } else if (blockScreenshot()) {
        _screenPrivacy.disableScreenshot();
      }
    } else if (Platform.isIOS) {
      if (blockScreenshot()) {
        _screenPrivacy.disableScreenshot();
      }
    }
    _watcher = shouldListenNavigation == false
            ? null
            : (context.watchTabsRouter
      ..addListener(
        _navigationListener = () {
          if (context.tabsRouter.topRoute.name == _routeName) {
            if (_isNavigatedToDifferentTabRoute) {
              _screenPrivacy.disableScreenshot();
              _isNavigatedToDifferentTabRoute = false;
            }
          } else {
            if (!_isNavigatedToDifferentTabRoute) {
              _screenPrivacy.enableScreenshot();
              _isNavigatedToDifferentTabRoute = true;
            }
          }
        },
      ));
  }

  void _onLifecycleChanged(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.resumed:
        _screenPrivacy.disablePrivacyScreen();
        if (_isIOSLifecycleUnblockedScreenshot) {
          _screenPrivacy.disableScreenshot();
          _isIOSLifecycleUnblockedScreenshot = false;
        }
        break;
      case AppLifecycleState.inactive:
        if (context.tabsRouter.topRoute.name == _routeName) {
          if (blockScreenshot()) {
            _screenPrivacy.enableScreenshot();
            _isIOSLifecycleUnblockedScreenshot = true;
          }
          _screenPrivacy.enablePrivacyScreen();
        }
        break;
      case AppLifecycleState.paused:
      case AppLifecycleState.detached:
      case AppLifecycleState.hidden:
        break;
    }
  }

  @override
  void dispose() {
    if (Platform.isAndroid) {
      if (enablePrivacyScreen()) {
        _screenPrivacy.disablePrivacyScreen();
      } else if (blockScreenshot()) {
        _screenPrivacy.enableScreenshot();
      }
    } else if (Platform.isIOS) {
      if (blockScreenshot()) {
        _screenPrivacy.enableScreenshot();
      }
    }

    final mNavigationListener = _navigationListener;
    if (mNavigationListener != null) {
      _watcher?.removeListener(mNavigationListener);
    }
    _listener?.dispose();
    super.dispose();
  }
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import '../screen_privacy_helper.dart';
import '../../../../navigation/navigation.dart';

@RoutePage()
class SensitiveDataPage extends StatefulWidget {
  const SensitiveDataPage({super.key});

  @override
  State<SensitiveDataPage> createState() => _SensitiveDataPageState();
}

class _SensitiveDataPageState extends State<SensitiveDataPage> with ScreenPrivacyMixin<SensitiveDataPage> {
  @override
  bool blockScreenshot() {
    return true;
  }

  @override
  bool enablePrivacyScreen() {
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Colors.blueGrey,
      body: Center(
        child: Image(
          image: NetworkImage(
            'https://images.unsplash.com/photo-1512850183-6d7990f42385?q=80&w=1974&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D',
          ),
        ),
      ),
    );
  }
}

The following example shows how to use the ScreenPrivacy plugin in an AutoRoute-based application, utilizing AutoTabsScaffold and BottomNavigationBar, to disable screenshotting and/or conceal app content in the recent apps preview for the entire application.

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:screen_privacy/screen_privacy.dart';

mixin ScreenPrivacyMixin<T extends StatefulWidget> on State<T> {
  AppLifecycleListener? _listener;
  late final ScreenPrivacy _screenPrivacy;
  bool _isIOSLifecycleUnblockedScreenshot = false;

  bool blockScreenshot();

  bool enablePrivacyScreen();

  @override
  void initState() {
    super.initState();
    _screenPrivacy = ScreenPrivacy();
    _listener = Platform.isIOS && enablePrivacyScreen()
            ? AppLifecycleListener(onStateChange: _onLifecycleChanged)
            : null;

    WidgetsBinding.instance.addPostFrameCallback(_initializer);
  }

  void _initializer(Duration timeStamp) {
    if (Platform.isAndroid) {
      if (enablePrivacyScreen()) {
        _screenPrivacy.enablePrivacyScreen();
      } else if (blockScreenshot()) {
        _screenPrivacy.disableScreenshot();
      }
    } else if (Platform.isIOS) {
      if (blockScreenshot()) {
        _screenPrivacy.disableScreenshot();
      }
    }
  }

  void _onLifecycleChanged(AppLifecycleState state) {
    switch (state) {
      case AppLifecycleState.resumed:
        _screenPrivacy.disablePrivacyScreen();
        if (_isIOSLifecycleUnblockedScreenshot) {
          _screenPrivacy.disableScreenshot();
          _isIOSLifecycleUnblockedScreenshot = false;
        }
        break;
      case AppLifecycleState.inactive:
        if (blockScreenshot()) {
          _screenPrivacy.enableScreenshot();
          _isIOSLifecycleUnblockedScreenshot = true;
        }
        _screenPrivacy.enablePrivacyScreen();

        break;
      case AppLifecycleState.paused:
      case AppLifecycleState.detached:
      case AppLifecycleState.hidden:
        break;
    }
  }

  @override
  void dispose() {
    if (Platform.isAndroid) {
      if (enablePrivacyScreen()) {
        _screenPrivacy.disablePrivacyScreen();
      } else if (blockScreenshot()) {
        _screenPrivacy.enableScreenshot();
      }
    } else if (Platform.isIOS) {
      if (blockScreenshot()) {
        _screenPrivacy.enableScreenshot();
      }
    }

    _listener?.dispose();
    super.dispose();
  }
}
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import '../screen_privacy_helper.dart';

@RoutePage()
class MyApp extends AutoRouter {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with ScreenPrivacyMixin {
  @override
  bool blockScreenshot() {
    return true;
  }

  @override
  bool enablePrivacyScreen() {
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return AutoTabsScaffold(
      homeIndex: 0,
      routes: const [],
      restorationId: 'AutoTabsScaffold',
      bottomNavigationBuilder: (context, tabsRouter) {
        return BottomNavigationBar(items: const []);
      },
    );
  }
}
6
likes
140
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

Safeguard sensitive app content on both Android and iOS devices

Repository (GitHub)
View/report issues

Documentation

API reference

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on screen_privacy

Packages that implement screen_privacy