secure_window 2.0.6

  • Readme
  • Changelog
  • Example
  • Installing
  • 0

secure_window #

This plugin allow you to protect your application content from view on demand

Pluggin in iOS is in swift

Pluggin in Android is in Kotlin / AndroidX libraries

Usage #

Installation #

Add secure_window as a dependency in your pubspec.yaml file (what?).

Import #

Import secure_window:

import 'package:secure_window/secure_window.dart';

Add a top level SecureWindow

SecureApplication(
        onNeedUnlock: (secure) => print(
            'need unlock maybe use biometric to confirm and then use sercure.unlock()'),
        child: MyAppContent(),
)

Put the content you want to protect in a SecureGate (could be the whole app)

SecureGate(
          blurr: 5,
          lockedBuilder: (context, secureNotifier) => Center(
              child: RaisedButton(
            child: Text('test'),
            onPressed: () => secureNotifier.unlock(),
          )),
          child: YouProtectedWidget(),
)

API Docs #

API Reference

Basic understanding #

The library is mainly controller via the SecureWindowController which can be

secured #

if the user switch app or leave app the content will not be visible in the app switcher and when it goes back to the app it will lock it

locked #

the child of the SecureGates will be hidden bellow the blurry barrier

paused #

even if secured SecureGates will not activate when user comes back to the app

Example #

Look at example app to see a use case

Authentication #

This tool does not impose a way to authenticate the user to give them back access to their content

You are free to use your own Widget/Workflow to allow user to see their content once locked (cf SecureApplication widget argument onNeedUnlock)

Therefore you can use any method you like:

  • Your own Widget for code Authentication
  • biometrics with the local_auth package
  • ...

Android #

On Android as soon as you secure the application the user will not be able to capture the screen in the app (even if unlocked) We might give an option to allow screenshot as an option if need arise

iOS #

Contrary to Android we create a native frosted view over your app content so that content is not visible in the app switcher. When the user gets back to the app we wait for ~500ms to remove this view to allow time for the app to woke and flutter gate to draw

Widgets #

SecureApplication #

Api Doc this widget is required and need to be a parent of any Gate it provides to its descendant a SecureWindowProvider that allow you to secure or open the application

You can pass you own initialized SecureWindowController if you want to set default values

SecureGate #

Api Doc The child of this widget will be below a blurry barrier (control the amount of blurr and opacity with its arguments) if the provided SecureWindowController is locked

Native workings #

Android #

When locked we set the secure flag to true

activity?.window?.addFlags(LayoutParams.FLAG_SECURE)

When opened we remove the secure flag

activity?.window?.clearFlags(LayoutParams.FLAG_SECURE)

iOS #

When app will become inactive we add a top view with a blurr filter We remove this app 500ms after the app become active to avoid your content form being breifly visible

Because we all want to see code in a Readme #

Widget build(BuildContext context) {
    var width = MediaQuery.of(context).size.width * 0.8;
    return MaterialApp(
      home: SecureApplication(
        onNeedUnlock: (secure) async {
          print(
              'need unlock maybe use biometric to confirm and then sercure.unlock() or you can use the lockedBuilder');
          // var authResult = authMyUser();
          // if (authResul) {
          //  secure.unlock();
          //  return SecureWindowAuthenticationStatus.SUCCESS;
          //}
          // else {
          //  return SecureWindowAuthenticationStatus.FAILED;
          //}
          return null;
        },
        onAuthenticationFailed: () async {
          // clean you data
          setState(() {
            failedAuth = true;
          });
          print('auth failed');
        },
        onAuthenticationSucceed: () async {
          // clean you data

          setState(() {
            failedAuth = false;
          });
          print('auth success');
        },
        child: SecureGate(
          blurr: blurr,
          opacity: opacity,
          lockedBuilder: (context, secureNotifier) => Center(
              child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              RaisedButton(
                child: Text('UNLOCK'),
                onPressed: () => secureNotifier.authSuccess(unlock: true),
              ),
              RaisedButton(
                child: Text('FAIL AUTHENTICATION'),
                onPressed: () => secureNotifier.authFailed(unlock: true),
              ),
            ],
          )),
          child: Scaffold(
            appBar: AppBar(
              title: const Text('Secure Window Example'),
            ),
            body: Center(
              child: Builder(builder: (context) {
                var valueNotifier = SecureWindowProvider.of(context);
                return ListView(
                  children: <Widget>[
                    Text('This is secure content'),
                    RaisedButton(
                      onPressed: () => valueNotifier.secure(),
                      child: Text('secure'),
                    ),
                    RaisedButton(
                      onPressed: () => valueNotifier.open(),
                      child: Text('open'),
                    ),
                    if (failedAuth == null)
                      Text(
                          'Lock the app then switch to another app and come back'),
                    if (failedAuth != null)
                      failedAuth
                          ? Text(
                              'Auth failed we cleaned sensitive data',
                              style: TextStyle(color: Colors.red),
                            )
                          : Text(
                              'Auth success',
                              style: TextStyle(color: Colors.green),
                            ),
                    FlutterLogo(
                      size: width,
                    ),
                    RaisedButton(
                      onPressed: () => valueNotifier.lock(),
                      child: Text('manually lock'),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        children: <Widget>[
                          Text('Blurr:'),
                          Expanded(
                            child: Slider(
                                value: blurr,
                                min: 0,
                                max: 100,
                                onChanged: (v) => setState(() => blurr = v)),
                          ),
                          Text(blurr.floor().toString()),
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        children: <Widget>[
                          Text('opacity:'),
                          Expanded(
                            child: Slider(
                                value: opacity,
                                min: 0,
                                max: 1,
                                onChanged: (v) => setState(() => opacity = v)),
                          ),
                          Text((opacity * 100).floor().toString() + "%"),
                        ],
                      ),
                    ),
                  ],
                );
              }),
            ),
          ),
        ),
      ),
    );
  }

2.0.6 #

  • PLEASE USE NEW SECURE_APPLICATION package

2.0.5 #

  • fixes

2.0.4 #

  • fixes

2.0.3 #

  • fix SecureWindowController without listening to updates

2.0.2 #

  • you can now get SecureWindowController without listening to updates

2.0.1 #

  • you can now temporary pause the gate from appearing [SecureWindowController.pause()] for example when you show a native screen like the image picker

2.0.0 #

  • new stream for authentication status [SecureWindowController.authenticationEvents]
  • new callback for [SecureApplication]: [SecureApplication.onAuthenticationFailed] and [SecureApplication.onAuthenticationSucceed]

1.0.1 #

  • Update README

1.0.0 #

  • Working on iOS and Android

0.0.1 #

  • Initial release

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:secure_window/secure_window.dart';

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  bool failedAuth;
  double blurr = 20;
  double opacity = 0.6;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    var width = MediaQuery.of(context).size.width * 0.8;
    return MaterialApp(
      home: SecureApplication(
        onNeedUnlock: (secure) async {
          print(
              'need unlock maybe use biometric to confirm and then sercure.unlock() or you can use the lockedBuilder');
          // var authResult = authMyUser();
          // if (authResul) {
          //  secure.unlock();
          //  return SecureWindowAuthenticationStatus.SUCCESS;
          //}
          // else {
          //  return SecureWindowAuthenticationStatus.FAILED;
          //}
          return null;
        },
        onAuthenticationFailed: () async {
          // clean you data
          setState(() {
            failedAuth = true;
          });
          print('auth failed');
        },
        onAuthenticationSucceed: () async {
          // clean you data

          setState(() {
            failedAuth = false;
          });
          print('auth success');
        },
        child: SecureGate(
          blurr: blurr,
          opacity: opacity,
          lockedBuilder: (context, secureNotifier) => Center(
              child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              RaisedButton(
                child: Text('UNLOCK'),
                onPressed: () => secureNotifier.authSuccess(unlock: true),
              ),
              RaisedButton(
                child: Text('FAIL AUTHENTICATION'),
                onPressed: () => secureNotifier.authFailed(unlock: true),
              ),
            ],
          )),
          child: Scaffold(
            appBar: AppBar(
              title: const Text('Secure Window Example'),
            ),
            body: Center(
              child: Builder(builder: (context) {
                var valueNotifier = SecureWindowProvider.of(context);
                return ListView(
                  children: <Widget>[
                    Text('This is secure content'),
                    ValueListenableBuilder<SecureWindowState>(
                      valueListenable: valueNotifier,
                      builder: (context, state, _) => state.secured
                          ? Column(
                              children: <Widget>[
                                RaisedButton(
                                  onPressed: () => valueNotifier.secure(),
                                  child: Text('Open app'),
                                ),
                                state.paused
                                    ? RaisedButton(
                                        onPressed: () =>
                                            valueNotifier.unpause(),
                                        child: Text('resume security'),
                                      )
                                    : RaisedButton(
                                        onPressed: () => valueNotifier.pause(),
                                        child: Text('pause security'),
                                      ),
                              ],
                            )
                          : RaisedButton(
                              onPressed: () => valueNotifier.secure(),
                              child: Text('Secure app'),
                            ),
                    ),
                    if (failedAuth == null)
                      Text(
                          'Lock the app then switch to another app and come back'),
                    if (failedAuth != null)
                      failedAuth
                          ? Text(
                              'Auth failed we cleaned sensitive data',
                              style: TextStyle(color: Colors.red),
                            )
                          : Text(
                              'Auth success',
                              style: TextStyle(color: Colors.green),
                            ),
                    FlutterLogo(
                      size: width,
                    ),
                    RaisedButton(
                      onPressed: () => valueNotifier.lock(),
                      child: Text('manually lock'),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        children: <Widget>[
                          Text('Blurr:'),
                          Expanded(
                            child: Slider(
                                value: blurr,
                                min: 0,
                                max: 100,
                                onChanged: (v) => setState(() => blurr = v)),
                          ),
                          Text(blurr.floor().toString()),
                        ],
                      ),
                    ),
                    Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: Row(
                        children: <Widget>[
                          Text('opacity:'),
                          Expanded(
                            child: Slider(
                                value: opacity,
                                min: 0,
                                max: 1,
                                onChanged: (v) => setState(() => opacity = v)),
                          ),
                          Text((opacity * 100).floor().toString() + "%"),
                        ],
                      ),
                    ),
                  ],
                );
              }),
            ),
          ),
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  secure_window: ^2.0.6

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:secure_window/secure_window.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
0
Health:
Code health derived from static analysis. [more]
--
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
--
Overall:
Weighted score of the above. [more]
0
Learn more about scoring.

This package is not analyzed, because it is discontinued.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.3.0 <3.0.0