Hướng dẫn tích hợp Flash Liveness SDK cho Flutter
Phiên bản plugin hiện tại: 1.6.14.
Plugin flashliveness_flutter là wrapper cho Flash Liveness SDK native Android/iOS. App Flutter cần cấu hình cả dependency Flutter và cấu hình native tương ứng.
1. Yêu cầu
| Hạng mục | Yêu cầu |
|---|---|
| Flutter | >=3.38.5 <4.0.0 |
| Dart SDK | ^3.10.4 |
| Android | minSdk 24, Java 17 khuyến nghị |
| iOS | Deployment target 13.0+; khuyến nghị 14.0+ nếu dự án có MLKit/TensorFlow pods |
| Package access | Có quyền truy cập private repo eidasvn/flash-liveness-flutter và package native liên quan |
2. Cài đặt package
Thêm dependency từ git tag vào pubspec.yaml:
dependencies:
flashliveness_flutter:
git:
url: https://x-access-token:GITHUB_TOKEN@github.com/eidasvn/flash-liveness-flutter.git
ref: 1.6.14
Sau đó chạy:
flutter pub get
ref phải khớp chính xác tag release. Vì repo private, môi trường build CI/CD cũng cần được cấp token hoặc SSH key phù hợp.
3. Import và khởi tạo
import 'package:flashliveness_flutter/flashliveness_flutter.dart';
final sdk = FlashlivenessFlutter();
4. Setup SDK
Phải gọi setup thành công trước khi gọi registerFace hoặc mở FlashLivenessLiveCheckView.
final setupRes = await sdk.setup(
appId: 'YOUR_APP_ID',
url: 'https://api.your-domain.com',
publicKey: 'YOUR_PUBLIC_KEY',
privateKey: 'YOUR_PRIVATE_KEY',
deviceId: 'OPTIONAL_DEVICE_ID',
faceImage: 'OPTIONAL_FACE_IMAGE',
optionHeader: {
'Authorization': 'Bearer your_token',
'x-device-platform': 'flutter',
},
optionRequest: {
'env': 'prod',
},
imageResizeConfig: const ImageResizeConfig(
maxDimension: 640,
compression: 95,
),
);
| Tham số | Bắt buộc | Ghi chú |
|---|---|---|
appId | Có | Mã ứng dụng/đối tác được backend cấp |
url | Có | Base URL API liveness |
publicKey | Có | Public key |
privateKey | Có | Private key |
deviceId | Không | Nếu null/empty, native SDK tự sinh device ID |
faceImage | Không | Chỉ truyền khi flow đã có ảnh khuôn mặt đúng format native SDK yêu cầu |
optionHeader | Không | Header mặc định cho request native |
optionRequest | Không | Param mặc định cho init transaction/live check |
imageResizeConfig | Không | Resize/nén ảnh trước khi SDK xử lý |
Kết quả setup thường có dạng:
{
'success': true,
'deviceId': '...'
}
5. Register face
final result = await sdk.registerFace(
imageBytes,
headers: {
'Authorization': 'Bearer your_token',
},
);
Lưu ý:
- Cần gọi
setupthành công trước. - Android yêu cầu
imageByteskhông rỗng. - iOS hỗ trợ truyền
Uint8List(0)để native SDK mở flow chọn/chụp ảnh đăng ký bằng UI native. headerslà optional; trên iOS sẽ được merge vớioptionHeaderđã truyền ởsetup.
6. Mở live check native view
Hiển thị FlashLivenessLiveCheckView trong màn hình riêng, full-screen hoặc gần full-screen để camera view có kích thước ổn định.
FlashLivenessLiveCheckView(
readIdCardRequestId: 'optional-request-id',
faceMatchNoteDisplayMode: FaceMatchNoteDisplayMode.showOnce,
faceMatchMaskConfig: const FaceMatchMaskConfig(
maskBackgroundColor: '#66000000',
ovalStrokeColor: '#00A7FF',
textBackgroundColor: '#00A7FF',
textColor: '#FFFFFFFF',
instructionTopInset: 120.0,
instructionMessageMap: {
0: 'Khuôn mặt hợp lệ',
7: 'Không tìm thấy khuôn mặt',
10: 'Giữ yên khuôn mặt',
14: 'Phát hiện nhiều khuôn mặt',
},
),
faceMatchNoteConfig: const FaceMatchNoteConfig(
textColor: '#1F2937',
buttonTextColor: '#FFFFFF',
buttonBackgroundColor: '#00A7FF',
titleText: 'Lưu ý trước khi xác thực',
messageText: 'Đưa điện thoại ngang tầm mắt và đặt khuôn mặt vào giữa khung.',
environmentTitleText: 'Ánh sáng',
environmentDescriptionText: 'Đầy đủ',
sunglassesTitleText: 'Không',
sunglassesDescriptionText: 'Đeo kính râm',
maskTitleText: 'Không',
maskDescriptionText: 'Đeo khẩu trang',
buttonTitleText: 'Tôi đã hiểu',
),
onEvent: (event) {
debugPrint('FlashLiveness event: $event');
},
)
readIdCardRequestId là required trong widget. Nếu không có request ID, truyền chuỗi rỗng ''.
7. Tùy biến UI live check
FaceMatchNoteDisplayMode:
| Giá trị | Ý nghĩa |
|---|---|
hidden | Ẩn note hướng dẫn |
showOnce | Hiển thị một lần |
always | Luôn hiển thị |
Nếu không truyền faceMatchNoteDisplayMode, Android và iOS fallback về hidden.
FaceMatchMaskConfig:
| Thuộc tính | Ý nghĩa |
|---|---|
maskBackgroundColor | Màu nền mask |
ovalStrokeColor | Màu viền oval |
textBackgroundColor | Màu nền text hướng dẫn |
textColor | Màu chữ hướng dẫn |
instructionTopInset | Khoảng cách top inset của instruction |
instructionMessageMap | Message theo mã hướng dẫn/validation |
FaceMatchNoteConfig:
| Thuộc tính | Ý nghĩa |
|---|---|
textColor | Màu chữ |
buttonTextColor | Màu chữ button |
buttonBackgroundColor | Màu nền button |
titleText | Tiêu đề popup |
messageText | Nội dung mô tả |
environmentTitleText / environmentDescriptionText | Nội dung cảnh báo môi trường/ánh sáng |
sunglassesTitleText / sunglassesDescriptionText | Nội dung cảnh báo kính râm |
maskTitleText / maskDescriptionText | Nội dung cảnh báo khẩu trang/che mặt |
buttonTitleText | Text button xác nhận |
Màu truyền dạng string hex, ví dụ #00A7FF, #FFFFFFFF. Plugin chuyển tiếp xuống native; validate/parse cụ thể do SDK native xử lý.
8. Event callback
onEvent nhận Map từ native. Các type thường gặp:
| Type | Ý nghĩa |
|---|---|
started | Session liveness đã bắt đầu |
success | Xác thực thành công, có result payload |
failure | Xác thực thất bại hoặc backend trả lỗi nghiệp vụ |
action | Action/intermediate callback từ native Android SDK |
retry | Người dùng chọn thử lại trong flow iOS |
cancel | Người dùng hủy/bỏ qua |
error | Lỗi hệ thống hoặc cấu hình |
Payload success/failure thường có dạng:
{
'type': 'success',
'message': '...',
'result': {
'status': 200,
'message': '...',
'requestId': '...',
'code': '...',
'signature': '...',
'success': true,
'faceImage': '...',
'faceRegisterId': '...',
'livenessImage': '...',
'transactionId': '...',
'data': {
'faceMatchingScore': 0.98,
'livenessType': '...',
'livenessScore': 0.99,
'faceMatchingResult': true,
},
},
}
Khi nhận success, app thường đóng màn hình liveness và tiếp tục business flow.
9. Clear data
await sdk.clearAllData();
API này xóa state/data native SDK đang giữ, đóng live check view đang chạy và reset config đã setup. Sau khi clear, app cần gọi setup lại trước khi registerFace hoặc live check.
10. Cấu hình Android native
Trong AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.CAMERA" />
Đảm bảo minSdk >= 24.
Nếu gặp lỗi resolve native dependency, bổ sung Maven repo:
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/eidasvn/flash-liveness-android")
credentials {
username = "GITHUB_USERNAME"
password = "GITHUB_TOKEN"
}
}
}
}
Nếu dùng FlashLivenessLiveCheckView và gặp lỗi Activity must extend ComponentActivity, đổi MainActivity sang FlutterFragmentActivity.
11. Cấu hình iOS native
Đặt deployment target tối thiểu 13.0:
platform :ios, '13.0'
use_frameworks! :linkage => :static
Thêm quyền camera trong Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Ứng dụng cần quyền camera để xác thực liveness.</string>
Sau khi flutter pub get, chạy:
cd ios
pod install
Các block Podfile nâng cao như pre_install dynamic_framework_pods hoặc can thiệp BUILD_LIBRARY_FOR_DISTRIBUTION, SWIFT_SERIALIZE_DEBUGGING_OPTIONS, IPHONEOS_DEPLOYMENT_TARGET không bắt buộc cho mọi dự án. Chỉ thêm khi dự án gặp conflict pod/build cụ thể với MLKit/TensorFlow hoặc framework linkage.
12. Thứ tự tích hợp đề nghị
- Thêm package và chạy
flutter pub get. - Cấu hình native Android/iOS.
- Gọi
setupkhi app sẵn sàng hoặc ngay trước khi dùng SDK. - Nếu cần, gọi
registerFaceđể đăng ký ảnh khuôn mặt. - Mở
FlashLivenessLiveCheckViewvà xử lýonEvent. - Gọi
clearAllDatakhi muốn reset state SDK.