Chuyển tới nội dung chính

Hướng dẫn tích hợp Flash Liveness SDK cho Android

Phiên bản SDK hiện tại: 1.7.23.

Tài liệu này dành cho ứng dụng Android native Kotlin/Java tích hợp trực tiếp io.liveness.flash:sdk-android.

1. Yêu cầu

Hạng mụcYêu cầu
Android SDKminSdk 24, compileSdk 34 khuyến nghị
Java/Kotlin targetJava 17/Kotlin JVM target 17 khuyến nghị
Package accessCó quyền đọc GitHub Packages của eidasvn/flash-liveness-android
Thiết bị testThiết bị thật có camera

2. Cấu hình repository

Thêm GitHub Packages repository vào settings.gradle hoặc root build.gradle:

dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://maven.pkg.github.com/eidasvn/flash-liveness-android")
credentials {
username = "GITHUB_USERNAME"
password = "GITHUB_PERSONAL_ACCESS_TOKEN"
}
}
}
}

Token cần có quyền read:packages và quyền truy cập repository private.

3. Thêm dependency

Trong build.gradle của module app:

dependencies {
implementation("io.liveness.flash:sdk-android:1.7.23")
implementation("com.google.mlkit:face-detection:16.1.7")
}

SDK đã khai báo transitive dependencies cho CameraX và TensorFlow Lite. App host chỉ cần khai báo thêm dependency ngoài khi dự án có conflict version cụ thể.

4. Khai báo quyền

Trong AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

Trước khi gọi SDK, app nên request runtime permission CAMERA. Nếu người dùng từ chối quyền, không start SDK; hãy hiển thị hướng dẫn mở quyền trong Settings.

5. ProGuard/R8

Nếu bật minify, thêm rule:

-keep class com.liveness.sdk.corev4.model.** { *; }
-keep interface com.liveness.sdk.corev4.utils.CallbackLivenessListener { *; }

6. Khởi tạo cấu hình

SDK dùng LivenessRequest để nhận thông tin tích hợp và cấu hình UI:

val livenessRequest = LivenessRequest(
baseURL = "https://your-api-domain.com",
appId = "YOUR_APP_ID",
secret = "YOUR_SECRET",
privateKey = "YOUR_RSA_PRIVATE_KEY",
publicKey = "YOUR_RSA_PUBLIC_KEY",
verifyLevel = VerifyLevel.MEDIUM,
isDebug = BuildConfig.DEBUG,
faceMatchNoteDisplayMode = FaceMatchNoteDisplayMode.SHOW_ONCE,
imageResizeConfig = ImageResizeConfig(
maxDimension = 1024,
compression = 95
)
)

LiveNessSDK.setConfigSDK(this, livenessRequest)

faceMatchNoteDisplayMode hỗ trợ:

Giá trịÝ nghĩa
HIDDENKhông hiển thị note trước khi scan
SHOW_ONCEChỉ hiển thị lần đầu trên thiết bị
ALWAYSLuôn hiển thị trước mỗi lần scan

7. Tùy biến ảnh và giao diện

ImageResizeConfig áp dụng cho ảnh gửi lên API verify liveness và ảnh trả về callback/result.

Thuộc tínhKiểuGiá trị khuyến nghị
maxDimensionInt1024; SDK giới hạn hợp lệ trong khoảng 1..4096
compressionInt90..95; SDK giới hạn hợp lệ trong khoảng 0..100

Ví dụ tùy biến overlay và note:

val maskConfig = FaceMatchMaskConfig(
maskBackgroundColor = "#66000000",
ovalStrokeColor = "#00A7FF",
textBackgroundColor = "#00A7FF",
textColor = "#FFFFFFFF",
instructionMessageMap = mapOf(
0 to "Khuôn mặt hợp lệ",
7 to "Không tìm thấy khuôn mặt",
10 to "Giữ yên khuôn mặt",
14 to "Phát hiện nhiều khuôn mặt"
)
)

val noteConfig = FaceMatchNoteConfig(
textColor = "#1F2937",
buttonTextColor = "#FFFFFF",
buttonBackgroundColor = "#00A7FF",
titleText = "Lưu ý",
messageText = "Vui lòng giữ điện thoại ngang tầm mắt để khuôn mặt nằm trọn trong khung hình.",
environmentTitleText = "Môi trường",
environmentDescriptionText = "Đủ ánh sáng",
sunglassesTitleText = "Không",
sunglassesDescriptionText = "Đeo kính râm",
maskTitleText = "Không",
maskDescriptionText = "Đeo khẩu trang",
buttonTitleText = "Đã hiểu"
)

Truyền các config này vào LivenessRequest qua faceMatchMaskConfig, faceMatchNoteConfigfaceMatchInstructionTopInset nếu cần chỉnh vị trí text hướng dẫn.

8. Thực hiện live check

8.1 Mở bằng Activity

Phù hợp khi muốn SDK tự mở màn hình FaceMatchActivity.

LiveNessSDK.startLiveNess(
context = this@MainActivity,
mLivenessRequest = livenessRequest,
livenessListener = object : CallbackLivenessListener {
override fun onStart() {
// SDK bắt đầu camera/session liveness.
}

override fun onResultsLiveness(action: String?) {
// Action/hướng dẫn trung gian trong quá trình liveness.
}

override fun onCallbackLiveness(data: LivenessModel?) {
handleLivenessResult(data)
}
}
)

Không dùng applicationContext cho flow này vì SDK cần Activity để mở UI và xử lý back stack.

8.2 Nhúng bằng Fragment

LiveNessSDK.startLiveNess(
context = this,
mLivenessRequest = livenessRequest,
supportFragmentManager = supportFragmentManager,
container = R.id.fragment_container,
livenessListener = listener
)

8.3 Nhúng bằng LivenessFrameLayout

Phù hợp khi app muốn chủ động quản lý pause(), resume(), stop()release().

private var livenessView: LivenessFrameLayout? = null

private fun openLiveness() {
livenessView = LivenessFrameLayout(this).apply {
attachAndStart(
activity = this@MainActivity,
container = findViewById(R.id.frame_view_main),
mLivenessRequest = livenessRequest,
livenessListener = listener
)
}
}

override fun onPause() {
livenessView?.pause()
super.onPause()
}

override fun onResume() {
super.onResume()
livenessView?.resume()
}

override fun onDestroy() {
livenessView?.release()
livenessView = null
super.onDestroy()
}

Nếu tự xử lý nút back trong Activity nhúng view, forward back event vào SDK:

onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
if (livenessView?.handleBackPressed() == true) return
finish()
}
})

Khi back được xử lý bởi SDK, callback trả về status = LivenessFrameLayout.STATUS_BACK_PRESSED.

9. Xử lý callback

Nên ưu tiên đọc callback theo thứ tự:

FieldÝ nghĩa
sdkErrorCodeMã lỗi nội bộ ổn định để app xử lý logic
statusHTTP status hoặc trạng thái flow
messageThông điệp hiển thị/log

Ví dụ:

private fun handleLivenessResult(data: LivenessModel?) {
when (data?.sdkErrorCode) {
null -> {
// Không có lỗi SDK nội bộ, kiểm tra status/success theo payload backend.
}
"BACK_PRESSED" -> {
// Người dùng bấm back.
}
"PERMISSION_DENIED" -> {
// Thiếu quyền camera.
}
else -> {
// Log và hiển thị thông báo phù hợp.
}
}
}

Một số sdkErrorCode thường gặp:

  • COMPROMISED_ENVIRONMENT
  • SDK_NOT_INITIALIZED
  • INVALID_INPUT
  • EMPTY_RESPONSE
  • TOTP_ERROR
  • PERMISSION_DENIED
  • DATA_CONFIG_FAIL
  • VERIFY_FAILED
  • BACK_PRESSED

10. Register face

Nếu flow cần đăng ký khuôn mặt:

LiveNessSDK.registerFace(
context = this,
mLivenessRequest = livenessRequest,
livenessListener = listener
)

11. Tiện ích

HàmMục đích
LiveNessSDK.checkVersion()Trả về version SDK hiện tại
LiveNessSDK.isRegisterFace(context)Kiểm tra thiết bị/người dùng đã đăng ký mặt chưa
LiveNessSDK.getDeviceId(context)Lấy device ID SDK đang dùng
LiveNessSDK.clearAllData(context)Xóa cache/config SDK

12. Checklist trước production

  • Tắt isDebug hoặc giảm log level.
  • Kiểm tra credential GitHub Packages không nằm trong source public.
  • Kiểm thử permission denied, back pressed, network timeout, verify failed.
  • Kiểm thử trên nhiều thiết bị thật, đặc biệt thiết bị camera yếu hoặc ánh sáng thấp.