Android Integration
Prebuilt AAR distribution of the VeryAILiveness palm-liveness SDK for Android. A liveness check opens a single-shot palm scan that confirms a live human palm — no enrollment, no verification, no signed token.
Distribution repository and releases: veroslabs/very-ai-liveness-android.
1. Install the SDK
Gradle (recommended)
org.very:liveness is published to Maven Central. Add the dependency in your app's build.gradle:
dependencies {
implementation 'org.very:liveness:1.0.55'
} Manual AAR
Two AARs ship at the root of every tagged release:
| File | Purpose |
|---|---|
liveness-1.0.55.aar | Main SDK — org.very:liveness |
sdk-native-bundle-1.0.55.aar | Optional bundled .so companion (see Asset loading below) |
Drop them in your app's libs/ directory and add a fileTree dependency:
dependencies {
implementation fileTree(dir: 'libs', include: ['liveness-1.0.55.aar'])
// Optional — opt into bundled mode (see Asset loading)
implementation fileTree(dir: 'libs', include: ['sdk-native-bundle-1.0.55.aar'])
// VeryAILiveness depends on AndroidX + CameraX at runtime; the
// released POM declares them, but fileTree skips POM resolution
// so they have to be added manually:
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.11.0'
def camerax_version = "1.4.1"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-view:${camerax_version}"
} Prefer the Maven Central path unless you have a specific reason — fileTree skips POM resolution so transitive deps have to be added by hand and won't auto-bump between releases.
2. Configure your app
| Setting | Value |
|---|---|
minSdk | 23 |
compileSdk | 34+ |
| Java / Kotlin target | 11 |
| Manifest permissions | android.permission.CAMERA, android.permission.INTERNET |
Liveness uses the device camera and the on-device PalmID native library. Both work on real ARM devices only (no emulator support for the .so).
3. Run a liveness check
import org.very.liveness.VeryAILiveness
import org.very.liveness.VeryLivenessConfig
val config = VeryLivenessConfig(
sdkKey = "your-sdk-key", // required — issued by Very
themeMode = "dark", // "light" or "dark"
language = "en", // optional — ISO 639-1, defaults to system locale
)
VeryAILiveness.check(context = this, config = config) { result ->
runOnUiThread {
when {
result.isSuccess -> { /* liveness passed */ }
result.code == "cancelled" -> { /* user dismissed the page */ }
else -> {
// result.error / result.errorMessage carry the failure detail
}
}
}
} VeryLivenessConfig is a slim subset of the full SDK's VeryConfig — no userId, since liveness binds no user identity, but sdkKey is required to authenticate the backend session calls. On Android the liveness check always uses touch mode.
Success & error pages
By default the SDK shows a brief "Thanks for verifying" success page (~1.5 s) before your callback fires, and returns terminal errors straight to your callback. Both are configurable by property assignment after construction:
val config = VeryLivenessConfig(sdkKey = "your-sdk-key")
// Return to your callback the instant capture succeeds — skips the
// "Thanks for verifying" success page (shown ~1.5 s by default).
config.showSuccess = false
// Route terminal errors to an in-SDK page with Retry / Close buttons
// instead of returning straight to your callback.
config.showError = true showSuccess— defaulttrue; setfalseto return the instant capture succeeds.showError— defaultfalse; settrueto route terminal errors to an in-SDK Retry / Close page.
Privacy disclosure
Show a partner disclosure below the native scan instruction with privacyMessage. The SDK renders it verbatim, so your app owns localization — pass the already-localized string. Basic HTML is honoured: wrap a substring in <a href="https://…">…</a> to make it an inline link the SDK opens on tap. A link with no valid HTTP(S) URL — and tag-free copy — renders as plain text with no tap handling. Tune appearance with privacyMessageFontSize and privacyMessageColor.
val config = VeryLivenessConfig(sdkKey = "your-sdk-key")
config.privacyMessage = "We use your hand motion only for anti-bot verification. " +
"<a href=\"https://example.com/privacy\">Learn more</a>"
config.privacyMessageFontSize = 12f // sp; 0 uses the SDK default
config.privacyMessageColor = Color.WHITE // null uses the SDK's muted on-scrim colour VeryResult
VeryResult.code is one of "success", "cancelled", or "error". On non-success, result.error carries an SDK error code and result.errorMessage carries a localized human-readable message.
Asset loading
The native palm-recognition library (libPalmAPISaas.so, ~18 MB per ABI) ships in slim mode by default — org.very:liveness does not include the .so. The SDK downloads it from CDN on first scan and caches it under app-private storage; subsequent launches use the cache. Plan for a loading state on the first scan (5–15 s on typical networks).
To bundle the .so inside your APK (instant first scan, +18 MB per ABI), add the companion sdk-native-bundle artifact alongside:
dependencies {
implementation 'org.very:liveness:1.0.55'
implementation 'org.very:sdk-native-bundle:1.0.55'
} Don't combine sdk-native-bundle with org.very:sdk — the full Palm Verification SDK already bundles the same .so, and adding both produces a jniLibs merge conflict at AGP packaging time.
Network endpoints
If your network restricts egress, allowlist the following:
| Purpose | URL |
|---|---|
| Liveness session create | https://api.very.org/v1/sdk/liveness-sessions |
| Liveness result POST | https://api.very.org/v1/sdk/liveness-sessions/{id}/result |
| Model download (primary) | https://assets.very.org/sdk/v3/<abi>/libPalmAPISaas.so |
| Model download (backup) | https://r2.assets.very.org/sdk/v3/<abi>/libPalmAPISaas.so |
The result POST is fire-and-forget — it doesn't block the host callback. The model download path is unused in bundled mode after the first install.