simple_biometric 0.1.1
simple_biometric: ^0.1.1 copied to clipboard
A Flutter plugin for easy implementation of biometric authentication (fingerprint, face ID, etc.) on Android and iOS, with support for different biometric types and error handling.
Simple Biometric #
A robust and easy-to-use Flutter plugin for implementing biometric authentication (Fingerprint, Face ID, Iris) on Android and iOS.
Features #
- 🔐 Unified API: Single method to trigger native biometric prompts on both platforms.
- 🤖 Android Support: Detects Fingerprint, Face, and Iris hardware.
- 🍎 iOS Support: Detects Face ID and Touch ID.
- 🛠 Hardware Detection: Check if biometric hardware is present and available.
- 🎨 Customization: Configure titles, descriptions, and cancel buttons for the prompt.
⚙️ Configuration #
Android #
-
Activity Setup: Ensure your
MainActivityextendsFlutterFragmentActivity(required forBiometricPrompt).File:
android/app/src/main/.../MainActivity.ktimport io.flutter.embedding.android.FlutterFragmentActivity class MainActivity: FlutterFragmentActivity() { } -
Permissions: Add the biometric permission to your manifest.
File:
android/app/src/main/AndroidManifest.xml<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
iOS #
Add usage descriptions to your Info.plist to explain why you need biometric access.
File: ios/Runner/Info.plist
<key>NSFaceIDUsageDescription</key>
<string>We need your face to unlock the app securely.</string>
<key>NSTouchIDUsageDescription</key>
<string>We need your fingerprint to unlock the app securely.</string>
📚 API Reference #
Import the package:
import 'package:simple_biometric/simple_biometric.dart';
Methods #
| Method | Returns | Description |
|---|---|---|
showBiometricPrompt(...) |
Future<BiometricStatusResult> |
Triggers the native authentication dialog. |
getAndroidBiometricTypes() |
Future<List<AndroidBiometricType>> |
(Android Only) Returns a list of available biometric hardware (e.g. [fingerprint, face]). |
isAndroidBiometricHardwareAvailable() |
Future<bool> |
(Android Only) Returns true if any biometric hardware functions. |
getIOSBiometricType() |
Future<IOSBiometricType> |
(iOS Only) Returns the supported biometric type (e.g. faceId, touchId). |
Enums #
BiometricStatusResult
Result of showBiometricPrompt.
authSuccess: User verified successfully.authFailed: Verification failed (wrong fingerprint/face).noBiometrics: No biometrics enrolled/configured in settings.noHardware: Device lacks biometric sensors.biometricLockout: Temporarily locked (too many attempts).biometricLockoutPermanent: Permanently locked (requires PIN/Pattern to reset).
AndroidBiometricType
fingerprint,face,iris,none,unknown.
IOSBiometricType
touchId,faceId,none,unknown.
💡 Usage Examples #
1. Basic Authentication #
Trigger the prompt and handle the result.
final _simpleBiometric = SimpleBiometric();
Future<void> authenticate() async {
final result = await _simpleBiometric.showBiometricPrompt(
title: 'Login',
description: 'Please verify your identity',
cancelText: 'Cancel',
);
if (result == BiometricStatusResult.authSuccess) {
print("Welcome back!");
} else {
print("Auth failed: $result");
}
}
2. Checking Capabilities (Advanced) #
Check what specifically is available to show the correct UI.
// Android: Check for multiple types
if (Platform.isAndroid) {
final types = await _simpleBiometric.getAndroidBiometricTypes();
if (types.contains(AndroidBiometricType.face)) {
print("Device supports Face Unlock");
}
}
// iOS: Check for specific type
if (Platform.isIOS) {
final type = await _simpleBiometric.getIOSBiometricType();
if (type == IOSBiometricType.faceId) {
print("Device supports Face ID");
}
}
3. Smart Login Button Example 🌟 #
Here is a widget that dynamically adapts its icon and text based on the available biometric type (Face vs Fingerprint).
class BiometricLoginButton extends StatefulWidget {
final VoidCallback onAuthSuccess;
const BiometricLoginButton({super.key, required this.onAuthSuccess});
@override
State<BiometricLoginButton> createState() => _BiometricLoginButtonState();
}
class _BiometricLoginButtonState extends State<BiometricLoginButton> {
final SimpleBiometric _biometric = SimpleBiometric();
IconData _icon = Icons.fingerprint; // Default
String _label = "Login"; // Default
@override
void initState() {
super.initState();
_detectBiometricType();
}
Future<void> _detectBiometricType() async {
if (Platform.isIOS) {
final iosType = await _biometric.getIOSBiometricType();
if (iosType == IOSBiometricType.faceId) {
setState(() {
_icon = Icons.face;
_label = "Login with Face ID";
});
} else if (iosType == IOSBiometricType.touchId) {
setState(() {
_icon = Icons.fingerprint;
_label = "Login with Touch ID";
});
}
} else if (Platform.isAndroid) {
final androidTypes = await _biometric.getAndroidBiometricTypes();
if (androidTypes.contains(AndroidBiometricType.face)) {
setState(() {
_icon = Icons.face;
_label = "Login with Face";
});
} else if (androidTypes.contains(AndroidBiometricType.fingerprint)) {
setState(() {
_icon = Icons.fingerprint;
_label = "Login with Fingerprint";
});
}
}
}
Future<void> _handleTap() async {
final result = await _biometric.showBiometricPrompt(
title: 'Sign In',
description: _label,
cancelText: 'Cancel',
);
if (result == BiometricStatusResult.authSuccess) {
widget.onAuthSuccess();
}
}
@override
Widget build(BuildContext context) {
return ElevatedButton.icon(
icon: Icon(_icon),
label: Text(_label),
onPressed: _handleTap,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
),
);
}
}
Author #
Maintained by MickeyGR.
Support #
If you find this library useful, consider buying me a coffee!
Contributing #
Contributions are welcome! Please feel free to submit a Pull Request.
License #
This project is licensed under the MIT License - see the LICENSE file for details.