youverify_liveness_sdk 0.0.2
youverify_liveness_sdk: ^0.0.2 copied to clipboard
A Flutter plugin for YouVerify's KYC Liveness SDK — supports real-time liveness detection on Android and iOS via Flutter Method Channels.
YouVerify Liveness SDK for Flutter #
A Flutter plugin that integrates YouVerify's KYC Liveness Detection SDK into your Flutter applications. Perform real-time liveness verification on Android and iOS with support for multiple task types, full branding customization, and sandbox/production environment switching.
Table of Contents #
- Requirements
- Project Overview
- Installation
- Platform Setup
- Getting Your Credentials
- Usage
- Configuration Reference
- Task Types
- Callbacks & Results
- Example App
- Troubleshooting
- Support
Requirements #
Flutter & Dart #
| Requirement | Version |
|---|---|
| Dart SDK | >=3.0.0 <4.0.0 |
| Flutter | >=3.10.0 |
Platform Minimum Versions #
| Platform | Minimum Version |
|---|---|
| Android | minSdk 24 |
| iOS | 13.0 |
Device Requirements #
- Physical device recommended: Liveness detection uses the camera and face detection. While the app may run on simulators/emulators, camera-based features require a physical device for full functionality.
- Camera: Required for all liveness tasks.
- Microphone: Optional; only needed if
allowAudiois enabled for narrated instructions.
Project Overview #
The YouVerify Liveness SDK plugin provides:
- Real-time liveness detection — Verify that a live person is present (not a photo or video replay).
- Multiple task types — Complete The Circle, Yes or No, Motions, Blink, and combinations.
- Branding customization — Match the SDK UI to your app’s look and feel.
- Sandbox & production — Test with sandbox credentials, then switch to live for production.
Installation #
Add the plugin to your app's pubspec.yaml:
dependencies:
flutter:
sdk: flutter
youverify_liveness_sdk: ^0.0.1
If using a local path (e.g. for development):
dependencies:
youverify_liveness_sdk:
path: ../youverify_liveness_sdk
Then run:
flutter pub get
Platform Setup #
Android #
- NDK ABI filters — Add the following to your app module's
android/app/build.gradle(orbuild.gradle.kts):
android {
defaultConfig {
ndk {
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a", "x86"))
}
}
}
- Permissions — Ensure your app requests camera (and optionally microphone) permissions. The plugin uses the camera for liveness detection. If your
AndroidManifest.xmldoes not already include them, add:
<uses-permission android:name="android.permission.CAMERA" />
<!-- Optional: only if allowAudio is true -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
iOS #
- Camera & Microphone usage descriptions — Add the following keys to your
ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>This app uses the camera for liveness detection to verify your identity.</string>
<key>NSMicrophoneUsageDescription</key>
<string>This app may use the microphone for audio instructions during liveness verification.</string>
-
MediaPipe linker fix — The YouVerify Liveness SDK uses MediaPipe for face detection. CocoaPods can inject duplicate or conflicting MediaPipe framework flags (
MediaPipeTasksCommon,MediaPipeTasksVision) into the build, which leads to linker errors or runtime issues such as the camera not showing or the flow getting stuck at "Detecting face...". The script below removes these conflicting flags from the xcconfig files after eachpod install, ensuring the camera and face detection work correctly. This step is required for the plugin to function on iOS.Add this post-install block to your
ios/Podfile(inside the existingpost_install do |installer|block, afterflutter_additional_ios_build_settings):
# YouVerify SDK: Fix MediaPipe linker conflicts
target_name = "Runner"
debug_xcconfig_path = "#{installer.pods_project.project_dir}/Target Support Files/Pods-#{target_name}/Pods-#{target_name}.debug.xcconfig"
release_xcconfig_path = "#{installer.pods_project.project_dir}/Target Support Files/Pods-#{target_name}/Pods-#{target_name}.release.xcconfig"
[debug_xcconfig_path, release_xcconfig_path].each do |xcconfig_path|
if File.exist?(xcconfig_path)
xcconfig = File.read(xcconfig_path)
xcconfig.gsub!(/-framework\s+"MediaPipeTasksCommon"/, '')
xcconfig.gsub!(/-framework\s+"MediaPipeTasksVision"/, '')
xcconfig.gsub!(/-force_load\s+"?[^"]*libMediaPipeTasksCommon.*\.a"?/, '')
File.write(xcconfig_path, xcconfig)
end
end
- CocoaPods — After adding the plugin and updating the Podfile, run:
cd ios && pod install && cd ..
Getting Your Credentials #
You need two credentials from YouVerify to use this plugin:
1. API Token #
Your API token is used to authenticate requests to the YouVerify API. Never expose it in frontend code. Obtain it from your secure backend or use it only in trusted environments.
- How to get it: Getting your API Key
- Note: API keys created in the Test portal work only in the Sandbox environment. Keys from the Live portal work in Production.
2. Public Merchant Key #
Your Public Merchant Key (also called publicMerchantID) identifies your merchant account.
- How to get it: Getting your Public Merchant Key
- Note: Use the key from the Test portal for sandbox; use the Live portal key for production.
Security recommendation #
Recommended: Store credentials in a Flutter environment (e.g. flutter_dotenv, --dart-define, or a .env file) and load them at runtime. Credentials must not be checked into version control or exposed in any public or shared location (including hardcoding in source files).
Environment Summary #
| Portal | Environment | Use Case |
|---|---|---|
| Test | Sandbox | Development & testing |
| Live | Production | Real verification |
Usage #
1. Initialize the SDK #
import 'package:youverify_liveness_sdk/youverify_liveness_sdk.dart';
final sdk = YouverifyLivenessSdk();
await sdk.initialize(
config: YVLivenessConfig(
apiToken: 'your_api_token', // From your backend or secured location
publicKey: 'your_public_merchant_key', // From your backend or secured location
deviceCorrelationId: 'device_${DateTime.now().millisecondsSinceEpoch}', // Unique device/session ID for correlation (e.g. device ID or session UUID)
environment: YVEnvironment.sandbox, // Use YVEnvironment.live for production
user: YVUser(
firstName: 'John',
lastName: 'Doe',
email: 'john@example.com',
),
branding: YVBranding(
name: 'MyApp',
color: '#0A2463',
showPoweredBy: true,
poweredByText: 'Powered by YouVerify',
),
allowAudio: false,
),
onSuccess: (result) {
// Handle success — result contains faceImage, livenessClip, etc.
},
onFailure: (result) {
// Handle failure — consider retrying on session errors
},
onClose: () {
// Handle closing —
},
);
2. Start Liveness #
// Use default tasks from config (or SDK defaults)
await sdk.startLiveness();
// Or pass specific tasks
await sdk.startLiveness(tasks: [
YVTask.motions(difficulty: YVTaskDifficulty.medium, maxNods: 3, maxBlinks: 3),
YVTask.blink(maxBlinks: 3),
]);
3. Dispose When Done #
@override
void dispose() {
sdk.dispose();
super.dispose();
}
Configuration Reference #
YVLivenessConfig #
| Parameter | Type | Required | Description |
|---|---|---|---|
apiToken |
String |
Yes | Your YouVerify API token. Obtain from your backend. |
publicKey |
String |
Yes | Your Public Merchant Key. |
deviceCorrelationId |
String |
Yes | Unique device/session identifier (e.g. device_${timestamp}). |
environment |
YVEnvironment |
No | YVEnvironment.sandbox or YVEnvironment.live. Default: sandbox. |
user |
YVUser? |
No | User details (firstName required, lastName/email optional). |
branding |
YVBranding? |
No | UI branding (color, logo, poweredBy, etc.). |
tasks |
List<YVTask>? |
No | Default tasks when startLiveness is called without tasks. |
allowAudio |
bool |
No | Narrate instructions during tasks. Default: false. |
metadata |
Map<String, dynamic>? |
No | Additional metadata for the session. |
YVUser #
| Parameter | Type | Required | Description |
|---|---|---|---|
firstName |
String |
Yes | User's first name. |
lastName |
String? |
No | User's last name. |
email |
String? |
No | User's email. |
YVBranding #
| Parameter | Type | Description |
|---|---|---|
name |
String? |
Brand name shown in the UI. |
color |
String? |
Hex or RGB color (e.g. #0A2463). |
logo |
String? |
URL to your logo image. |
logoAlt |
String? |
Alt text for logo. |
hideLogo |
bool? |
Hide logo. |
showPoweredBy |
bool? |
Show "Powered By" footer. |
poweredByText |
String? |
Custom "Powered By" text. |
poweredByLogo |
String? |
URL for "Powered By" logo. |
Task Types #
| Task | Description | Key Parameters |
|---|---|---|
| Complete The Circle | User traces an imaginary circle with head movement. | difficulty, timeout |
| Yes or No | User answers yes/no questions by tilting head (right = yes, left = no). | questions, difficulty, timeout |
| Motions | User performs nods, blinks, and mouth movements. | maxNods, maxBlinks, difficulty, timeout |
| Blink | User blinks a set number of times. | maxBlinks, difficulty, timeout |
Task Examples #
// Complete The Circle
YVTask.completeTheCircle(difficulty: YVTaskDifficulty.medium)
// Yes or No
YVTask.yesOrNo(
difficulty: YVTaskDifficulty.medium,
questions: [
YVQuestion(
question: 'Is Nigeria a country?',
answer: true,
errorMessage: 'Read the question again',
),
YVQuestion(question: 'Is the sky green?', answer: false),
],
)
// Motions
YVTask.motions(maxNods: 3, maxBlinks: 3, difficulty: YVTaskDifficulty.medium)
// Blink
YVTask.blink(maxBlinks: 3, difficulty: YVTaskDifficulty.easy)
// Multi-task (run multiple tasks in sequence)
[
YVTask.blink(maxBlinks: 2),
YVTask.motions(maxNods: 2, maxBlinks: 2),
]
Difficulty Levels #
YVTaskDifficulty.easyYVTaskDifficulty.medium(default)YVTaskDifficulty.hard
Callbacks & Results #
YVLivenessResult #
| Property | Type | Description |
|---|---|---|
passed |
bool |
Whether the liveness check passed. |
faceImage |
String? |
Base64 or URL of captured face image. |
livenessClip |
String? |
Base64 or URL of liveness video clip. |
metadata |
Map<String, dynamic>? |
Session metadata. |
error |
YVLivenessError? |
Error details when passed is false. |
YVLivenessError #
| Property | Type | Description |
|---|---|---|
key |
String |
Error identifier (e.g. invalid_or_expired_session, session_token_error). |
message |
String? |
Human-readable error message. |
isSessionError |
bool |
True for session-related errors; consider reinitializing. |
Session Error Handling #
When result.error?.isSessionError is true, the session may have expired. Reinitialize the SDK and retry:
void _handleFailure(YVLivenessResult result) {
if (result.error?.isSessionError == true) {
// Session expired — reinitialize and retry
_initialize();
return;
}
// Handle other failures
}
Example App #
The example folder contains a complete integration sample. To run it:
-
Clone or open the project containing the plugin and example app.
-
Add your credentials — In
example/lib/screens/home_screen.dart, update the_configgetter with your API token and public key (or load them from a secure source):
YVLivenessConfig get _config => YVLivenessConfig(
apiToken: 'YOUR_API_TOKEN',
publicKey: 'YOUR_PUBLIC_MERCHANT_KEY',
deviceCorrelationId: 'device_${DateTime.now().millisecondsSinceEpoch}',
environment: YVEnvironment.sandbox,
user: const YVUser(firstName: 'Ada', lastName: 'Lovelace', email: 'ada@example.com'),
branding: const YVBranding(
name: 'DemoApp',
color: '#0A2463',
showPoweredBy: true,
poweredByText: 'Powered by YouVerify',
),
allowAudio: false,
);
- Install dependencies:
cd example
flutter pub get
- iOS: Run
pod installin theiosfolder:
cd example/ios && pod install && cd ../..
- Run on a physical device:
cd example
flutter run
The example app demonstrates:
- SDK initialization with config
- Starting different task types (Complete The Circle, Yes or No, Motions, Blink, Multi-Task)
- Handling success, failure, and close callbacks
- Session expiry handling and reinitialization
- Error display and result cards
Troubleshooting #
"No view controller available for presentation" (iOS) #
Ensure the app has a visible window and that you are not calling startLiveness before the Flutter view is attached. Avoid calling from initState before the first frame; use WidgetsBinding.instance.addPostFrameCallback or a button press.
Camera not showing / "Detecting face..." stuck #
- Use a physical device — The iOS Simulator does not support the camera.
- Grant camera permission — When prompted, allow camera access. Check Settings → Privacy & Security → Camera for your app.
- Rebuild — Run
flutter clean, thenflutter pub get, thencd ios && pod installfor iOS.
Session fetch failed #
- Verify your API token and Public Merchant Key are correct.
- Ensure you are using sandbox credentials with
YVEnvironment.sandboxand live credentials withYVEnvironment.live. - Check network connectivity.
Build errors after plugin update #
flutter clean
flutter pub get
cd ios && pod install && cd ..
flutter run
Support #
- Documentation: YouVerify Docs
- API Key: Getting your API Key
- Public Merchant Key: Getting your Public Merchant Key
- Issues: GitHub Issues
Credits #
This Flutter plugin is an independent, third-party integration of the YouVerify Liveness SDK for Flutter. It is not officially developed, maintained, or endorsed by YouVerify. The underlying native Liveness SDK is developed by YouVerify.