| // Copyright 2013 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // ignore_for_file: public_member_api_docs |
| |
| import 'dart:async'; |
| |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/services.dart'; |
| import 'package:local_auth/local_auth.dart'; |
| |
| void main() { |
| runApp(MyApp()); |
| } |
| |
| class MyApp extends StatefulWidget { |
| @override |
| _MyAppState createState() => _MyAppState(); |
| } |
| |
| class _MyAppState extends State<MyApp> { |
| final LocalAuthentication auth = LocalAuthentication(); |
| _SupportState _supportState = _SupportState.unknown; |
| bool? _canCheckBiometrics; |
| List<BiometricType>? _availableBiometrics; |
| String _authorized = 'Not Authorized'; |
| bool _isAuthenticating = false; |
| |
| @override |
| void initState() { |
| super.initState(); |
| auth.isDeviceSupported().then( |
| (bool isSupported) => setState(() => _supportState = isSupported |
| ? _SupportState.supported |
| : _SupportState.unsupported), |
| ); |
| } |
| |
| Future<void> _checkBiometrics() async { |
| late bool canCheckBiometrics; |
| try { |
| canCheckBiometrics = await auth.canCheckBiometrics; |
| } on PlatformException catch (e) { |
| canCheckBiometrics = false; |
| print(e); |
| } |
| if (!mounted) { |
| return; |
| } |
| |
| setState(() { |
| _canCheckBiometrics = canCheckBiometrics; |
| }); |
| } |
| |
| Future<void> _getAvailableBiometrics() async { |
| late List<BiometricType> availableBiometrics; |
| try { |
| availableBiometrics = await auth.getAvailableBiometrics(); |
| } on PlatformException catch (e) { |
| availableBiometrics = <BiometricType>[]; |
| print(e); |
| } |
| if (!mounted) { |
| return; |
| } |
| |
| setState(() { |
| _availableBiometrics = availableBiometrics; |
| }); |
| } |
| |
| Future<void> _authenticate() async { |
| bool authenticated = false; |
| try { |
| setState(() { |
| _isAuthenticating = true; |
| _authorized = 'Authenticating'; |
| }); |
| authenticated = await auth.authenticate( |
| localizedReason: 'Let OS determine authentication method', |
| useErrorDialogs: true, |
| stickyAuth: true); |
| setState(() { |
| _isAuthenticating = false; |
| }); |
| } on PlatformException catch (e) { |
| print(e); |
| setState(() { |
| _isAuthenticating = false; |
| _authorized = 'Error - ${e.message}'; |
| }); |
| return; |
| } |
| if (!mounted) { |
| return; |
| } |
| |
| setState( |
| () => _authorized = authenticated ? 'Authorized' : 'Not Authorized'); |
| } |
| |
| Future<void> _authenticateWithBiometrics() async { |
| bool authenticated = false; |
| try { |
| setState(() { |
| _isAuthenticating = true; |
| _authorized = 'Authenticating'; |
| }); |
| authenticated = await auth.authenticate( |
| localizedReason: |
| 'Scan your fingerprint (or face or whatever) to authenticate', |
| useErrorDialogs: true, |
| stickyAuth: true, |
| biometricOnly: true); |
| setState(() { |
| _isAuthenticating = false; |
| _authorized = 'Authenticating'; |
| }); |
| } on PlatformException catch (e) { |
| print(e); |
| setState(() { |
| _isAuthenticating = false; |
| _authorized = 'Error - ${e.message}'; |
| }); |
| return; |
| } |
| if (!mounted) { |
| return; |
| } |
| |
| final String message = authenticated ? 'Authorized' : 'Not Authorized'; |
| setState(() { |
| _authorized = message; |
| }); |
| } |
| |
| Future<void> _cancelAuthentication() async { |
| await auth.stopAuthentication(); |
| setState(() => _isAuthenticating = false); |
| } |
| |
| @override |
| Widget build(BuildContext context) { |
| return MaterialApp( |
| home: Scaffold( |
| appBar: AppBar( |
| title: const Text('Plugin example app'), |
| ), |
| body: ListView( |
| padding: const EdgeInsets.only(top: 30), |
| children: <Widget>[ |
| Column( |
| mainAxisAlignment: MainAxisAlignment.center, |
| children: <Widget>[ |
| if (_supportState == _SupportState.unknown) |
| const CircularProgressIndicator() |
| else if (_supportState == _SupportState.supported) |
| const Text('This device is supported') |
| else |
| const Text('This device is not supported'), |
| const Divider(height: 100), |
| Text('Can check biometrics: $_canCheckBiometrics\n'), |
| ElevatedButton( |
| child: const Text('Check biometrics'), |
| onPressed: _checkBiometrics, |
| ), |
| const Divider(height: 100), |
| Text('Available biometrics: $_availableBiometrics\n'), |
| ElevatedButton( |
| child: const Text('Get available biometrics'), |
| onPressed: _getAvailableBiometrics, |
| ), |
| const Divider(height: 100), |
| Text('Current State: $_authorized\n'), |
| if (_isAuthenticating) |
| ElevatedButton( |
| onPressed: _cancelAuthentication, |
| child: Row( |
| mainAxisSize: MainAxisSize.min, |
| children: const <Widget>[ |
| Text('Cancel Authentication'), |
| Icon(Icons.cancel), |
| ], |
| ), |
| ) |
| else |
| Column( |
| children: <Widget>[ |
| ElevatedButton( |
| child: Row( |
| mainAxisSize: MainAxisSize.min, |
| children: const <Widget>[ |
| Text('Authenticate'), |
| Icon(Icons.perm_device_information), |
| ], |
| ), |
| onPressed: _authenticate, |
| ), |
| ElevatedButton( |
| child: Row( |
| mainAxisSize: MainAxisSize.min, |
| children: <Widget>[ |
| Text(_isAuthenticating |
| ? 'Cancel' |
| : 'Authenticate: biometrics only'), |
| const Icon(Icons.fingerprint), |
| ], |
| ), |
| onPressed: _authenticateWithBiometrics, |
| ), |
| ], |
| ), |
| ], |
| ), |
| ], |
| ), |
| ), |
| ); |
| } |
| } |
| |
| enum _SupportState { |
| unknown, |
| supported, |
| unsupported, |
| } |