flutter_liveness_detection_randomized_plugin
A Flutter plugin for liveness detection with randomized challenge response method
A Flutter plugin for liveness detection with randomized challenge response method
{"sdk":"flutter"}^2.0.2^0.13.20.10.6^2.0.5^4.0.15^2.1.3^2.4.0^1.18.0^2.1.2^2.2.2{"sdk":"flutter"}^4.0.0English project snapshot. Visit GitHub for the latest content.
A Flutter plugin for liveness detection with randomized challenge response method with an interaction mechanism between the user and the system in the form of a movement challenge that indicates life is detected on the face. This plugin helps implement secure biometric authentication by detecting real human presence through dynamic facial verification challenges.
Crafted with love by Bagus Subagja ❤️
Feel free to fork and modify this package to suit your needs - that's much more enjoyable and respectful 😊
Slide 16_9 - 1
https://github.com/user-attachments/assets/f7266dc9-c4a2-4fba-8684-0ead2f678180
useLegacyPackaging — no longer needed with modern AGPgoogle_mlkit_face_detection updated to 0.13.2LivenessDetectionConfigcontext and config parameterscustomizedLabel must not be null when useCustomizedLabel is trueSlide 16_9 - 9 Face stretching already fixed on this version
Add this to your package's pubspec.yaml file:
dependencies:
flutter_liveness_detection_randomized_plugin: ^1.2.1
final String? response = await FlutterLivenessDetectionRandomizedPlugin.instance.livenessDetection(
context: context,
config: LivenessDetectionConfig(
// Camera & Image Settings
cameraResolution: ResolutionPreset.medium, // Camera resolution
imageQuality: 100, // Image quality (0-100)
isEnableMaxBrightness: true, // Auto brightness adjustment
// Detection Settings
durationLivenessVerify: 60, // Detection timeout in seconds
showDurationUiText: false, // Show countdown timer
startWithInfoScreen: true, // Show tutorial screen
// UI Settings
isDarkMode: false, // Dark/light theme
showCurrentStep: true, // Show step counter
isEnableSnackBar: true, // Show result notifications
shuffleListWithSmileLast: true, // Randomize challenges with smile last
// Customization
useCustomizedLabel: false, // Enable custom labels
customizedLabel: LivenessDetectionLabelModel(
blink: '', // Empty string = skip challenge
lookDown: '', // Skip this challenge
lookLeft: null, // null = use default "Look LEFT"
lookRight: 'Turn Right', // Custom label
lookUp: 'Look Up Please', // Custom label
smile: null, // null = use default "Smile"
),
// Security Features
enableCooldownOnFailure: true, // Enable cooldown after failures
maxFailedAttempts: 3, // Failed attempts before cooldown
cooldownMinutes: 10, // Cooldown duration
),
);
cameraResolution: Camera quality (ResolutionPreset.low/medium/high)imageQuality: Output image quality 0-100 (default: 100)isEnableMaxBrightness: Auto brightness adjustment (default: true)durationLivenessVerify: Detection timeout in seconds (default: 45)showDurationUiText: Show countdown timer (default: false)startWithInfoScreen: Show tutorial before detection (default: false)isDarkMode: Dark theme mode (default: true)showCurrentStep: Show current step number (default: false)isEnableSnackBar: Show success/failure notifications (default: true)shuffleListWithSmileLast: Randomize challenges with smile at end (default: true)useCustomizedLabel: Enable custom challenge labels (default: false)customizedLabel: Custom labels for each challenge typeenableCooldownOnFailure: Enable cooldown after failed attempts (default: true)maxFailedAttempts: Number of failures before cooldown (default: 3)cooldownMinutes: Cooldown duration in minutes (default: 10)The plugin includes an automatic cooldown mechanism to prevent brute force attempts:
You can customize challenge labels or skip certain challenges:
'' to skip a challengenull to keep default labeluseCustomizedLabel: true, customizedLabel must not be nullimport 'package:flutter_liveness_detection_randomized_plugin/index.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: ElevatedButton(
onPressed: () async {
final result = await FlutterLivenessDetectionRandomizedPlugin.instance.livenessDetection(
context: context,
config: LivenessDetectionConfig(
startWithInfoScreen: true,
isDarkMode: false,
showCurrentStep: true,
isEnableSnackBar: true,
),
);
if (result != null) {
// Liveness detection successful
print('Face captured: $result');
} else {
// Detection failed or cancelled
print('Detection failed');
}
},
child: Text('Start Liveness Detection'),
),
),
),
);
}
}
Add camera permission to your android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA"/>
Minimum SDK version: 24
Add camera usage description to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is required for liveness detection</string>
The example app includes 8 comprehensive liveness scenarios to test all features:
LivenessDetectionConfig(
shuffleListWithSmileLast: true,
startWithInfoScreen: true,
// Standard settings
)
LivenessDetectionConfig(
shuffleListWithSmileLast: false,
durationLivenessVerify: 30,
startWithInfoScreen: false,
)
LivenessDetectionConfig(
isDarkMode: true,
cameraResolution: ResolutionPreset.high,
durationLivenessVerify: 60,
)
LivenessDetectionConfig(
useCustomizedLabel: true,
customizedLabel: LivenessDetectionLabelModel(
blink: 'Kedip 2-3 Kali',
lookUp: 'Lihat ke Atas',
smile: 'Tersenyum Lebar',
),
)
LivenessDetectionConfig(
useCustomizedLabel: true,
customizedLabel: LivenessDetectionLabelModel(
blink: 'Blink Eyes',
lookDown: '', // Skip
lookLeft: '', // Skip
lookRight: '', // Skip
lookUp: 'Look Up Please',
smile: 'Smile Wide',
),
)
LivenessDetectionConfig(
showDurationUiText: true,
enableCooldownOnFailure: true,
maxFailedAttempts: 2,
cooldownMinutes: 5,
)
LivenessDetectionConfig(
isEnableMaxBrightness: false,
isEnableSnackBar: false,
showCurrentStep: false,
)
LivenessDetectionConfig(
isDarkMode: true,
cameraResolution: ResolutionPreset.high,
showDurationUiText: true,
enableCooldownOnFailure: true,
useCustomizedLabel: true,
customizedLabel: LivenessDetectionLabelModel(
blink: '👁️ Kedipkan Mata',
smile: '😊 Senyum Manis',
),
)
All parameters are now consolidated into the LivenessDetectionConfig object:
Before:
await plugin.livenessDetection(
context: context,
config: LivenessDetectionConfig(...),
isEnableSnackBar: true,
shuffleListWithSmileLast: true,
showCurrentStep: true,
isDarkMode: false,
);
After:
await plugin.livenessDetection(
context: context,
config: LivenessDetectionConfig(
isEnableSnackBar: true,
shuffleListWithSmileLast: true,
showCurrentStep: true,
isDarkMode: false,
// ... other parameters
),
);