Android reference
Every public type in the FacePing Android SDK: setup, enrolment, verification, the camera view and results.
Package: ai.faceping:faceping-android (Maven Central, preview). Starter app: faceping/android-starter. Android 7 (API 24) or later, on 64-bit phones (arm64-v8a) and x86_64 emulators.
android {
defaultConfig {
ndk { abiFilters += listOf("arm64-v8a", "x86_64") } // the ABIs FacePing's native core is built for
}
}
dependencies {
implementation("ai.faceping:faceping-android:1.0.0-preview.1") // from mavenCentral()
}Everything is in the package ai.faceping. The calls are suspend functions: call them from a coroutine, for example lifecycleScope.launch { … }. They do their work off the main thread.
Setup#
// Once, for example in Application.onCreate. Returns at once and loads the models in the background.
val faceping = FacePing.init(context, sandboxKey = "fp_test_…") // sandbox: faces enrolled on the device
// val faceping = FacePing.init(context, deviceToken = "fpd_…") // production: faces synced from your list
FacePing.current returns the same instance anywhere in the app, and throws IllegalStateException until init has been called. Calling init again with the same options returns the same instance; with different options it throws (call close() on the old one first).
FacePingOptions#
For every option, pass FacePing.init(context, FacePingOptions(...)).
| Property | Type | Default | Notes |
|---|---|---|---|
sandboxKey |
String? |
null |
A fp_test_ key from Developers → Sandbox keys. |
deviceToken |
String? |
null |
Production. A fpd_ token for one check-in list. Set this or sandboxKey, not both. |
region |
FacePingRegion |
EU |
Your account's region (sets the API address). |
apiBaseUrl |
String? |
null |
Overrides the region's address, for example for the UK or US region. |
passiveLiveness |
Boolean |
true |
Passive liveness on every check. Turn it off only if your app runs its own liveness check first. |
autoSyncInterval |
Duration? |
5 minutes | Production only. null turns automatic sync off; call sync() yourself. |
gatePolicy |
GatePolicy |
GatePolicy.DEFAULT |
How strict verification is. Change only if you know why. |
Setting neither sandboxKey nor deviceToken, or both, or a sandbox key that doesn't start with fp_test_, throws FacePingSetupException from init.
FacePing#
class FacePing : Closeable {
companion object {
fun init(context: Context, sandboxKey: String? = null, deviceToken: String? = null,
region: FacePingRegion = FacePingRegion.EU): FacePing
fun init(context: Context, options: FacePingOptions): FacePing
val current: FacePing
val SDK_VERSION: String
}
val options: FacePingOptions
val isSandbox: Boolean
val enrolledIds: Set<String>
val synced: SharedFlow<SyncResult> // every sync, automatic or not
suspend fun enrol(id: String, photo: FaceImage): EnrolResult // also Bitmap or ByteArray
suspend fun verifyLive(id: String, camera: FaceCameraView): VerifyResult
suspend fun verify(id: String, photo: FaceImage): VerifyResult // also Bitmap or ByteArray
suspend fun forget(id: String): Boolean
suspend fun forgetAll()
suspend fun sync(): SyncResult
override fun close()
}
| Method | Notes |
|---|---|
enrol |
Sandbox only. Production enrolment happens with consent on your server or through the FacePing widget. Replaces any face already stored under id. |
verifyLive |
Runs a live attempt on the camera's frames: match, head turn, match again. Shows prompts in the FaceCameraView and sets its guide. Times out after 10 seconds with NO_FACE or the last failure; cancel the coroutine to stop early. |
verify |
One photo, passive liveness only. |
forget |
Sandbox: deletes the face stored under id from the device straight away, and returns false if there was none. Production: throws IllegalStateException; remove a person through your server instead, and every device drops them at its next sync. |
forgetAll |
Deletes every face on the device straight away. In production the next sync brings back the people still enrolled. |
enrolledIds |
Who can be verified on this device, as of the last enrol, forget or sync. |
sync |
Production: downloads the latest faces for the device's list; a revoked device wipes its faces. Sandbox: activates the key, or renews its licence when due. |
close |
Stops automatic sync and frees the engine. FacePing.current is cleared; call init again to start over. |
FaceImage#
What you can pass as a photo.
| From | Example |
|---|---|
Bitmap |
faceping.enrol("me", bitmap) |
ByteArray (JPEG or PNG) |
faceping.enrol("me", bytes) |
A content:// or file:// Uri (for example from the photo picker) |
faceping.enrol("me", FaceImage.fromUri(context, uri)) |
FaceCameraView capture |
faceping.enrol("me", camera.capture()) |
FaceImage.fromBytes, fromBitmap and fromUri build one yourself. Photos are turned upright from their EXIF orientation and scaled down to 1280 pixels on the device before anything else happens.
FaceCameraView#
A front-camera view with a face guide and the liveness prompts ("Turn your head left", "Look back at the camera"). The SDK runs the camera (CameraX), so you don't need another camera library.
<ai.faceping.FaceCameraView
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="420dp" />
| Member | Notes |
|---|---|
suspend fun capture(): FaceImage |
Takes a still from the live view: upright, as the camera sees it (the preview is mirrored, the picture isn't). Throws IllegalStateException if the camera doesn't deliver a picture within 5 seconds. |
showGuide: Boolean |
The face outline. Default true. |
prompt: String? |
Set by verifyLive while a live check runs. |
guideState: FaceGuideState |
How the guide looks: READY (dashed), WORKING (a scan line), MATCH (green) or NO_MATCH (red). verifyLive sets it; set it yourself for other steps, for example WORKING while enrolling. Main thread only. |
cameraFailedListener |
Called on the main thread when the camera can't start: permission refused or no front camera. The message says which. |
fun startCamera() |
Starts (or restarts) the camera. Called for you when the view is attached; call it if your app gets camera permission another way. |
The camera starts when the view is attached to a window inside an AndroidX activity or fragment, and stops with its lifecycle. In Jetpack Compose, wrap it with AndroidView(factory = { FaceCameraView(it) }).
The prompts are the string resources faceping_prompt_look_at_camera, faceping_prompt_turn_left, faceping_prompt_turn_right and faceping_prompt_look_back: define them in your app to translate or reword them.
Permissions#
The library's manifest declares android.permission.CAMERA (for the camera view) and android.permission.INTERNET (to activate a sandbox key and to sync in production; face checks never use the network). Android merges both into your app, so you don't add them yourself.
FaceCameraView asks for the camera the first time it appears, if your app hasn't asked already. To ask earlier, use CameraPermission.isGranted(context) and CameraPermission.request(activity), then call startCamera() on the view once it's granted.
Backups#
The face store's encryption keys are kept in this device's Android Keystore, which can't be restored on another device. Exclude FacePing's files from Auto Backup (or turn backup off, as the starter app does): files/faceping and the shared preferences faceping.keys.
Results#
data class EnrolResult(val outcome: EnrolOutcome, val id: String) {
val isEnrolled: Boolean // outcome == ENROLLED
}
enum class EnrolOutcome { ENROLLED, NO_FACE, MULTIPLE_FACES, FACE_TOO_SMALL, NOT_LIVE, LIMIT_REACHED }
data class VerifyResult(
val outcome: VerifyOutcome,
val similarity: Double,
val livenessScore: Double?,
val elapsed: Duration,
val isSandbox: Boolean,
) {
val isMatch: Boolean // outcome == MATCH
}
enum class VerifyOutcome {
MATCH, NO_MATCH, NOT_ENROLLED, NO_FACE, LIVENESS_FAILED, CHALLENGE_FAILED, EXPIRED, LEASE_EXPIRED
}
data class SyncResult(
val status: PackDownloadStatus, // OK, GONE, REVOKED or UNAVAILABLE
val enrolled: Int,
val leaseUntilMillis: Long?, // production: verifies offline until then
val deleteAfterMillis: Long?,
)
LIMIT_REACHED means the sandbox already holds 25 faces on this device: forget one first. LEASE_EXPIRED (production) means the device hasn't synced for longer than its lease, 24 hours by default; it needs a connection before it verifies again.
Exceptions#
| Exception | When |
|---|---|
FacePingSetupException |
The key or token is missing, invalid or revoked, or the sandbox key couldn't be activated (no connection on first run). The message says which. |
FacePingModelException |
The face models couldn't load on this device. Send people to your normal entry. |
IllegalArgumentException |
A bad argument, for example an empty id or bytes that aren't a JPEG or PNG. |
IllegalStateException |
Not allowed in this mode or state: enrolling or forgetting one person in production, a closed FacePing, or a camera that didn't deliver a picture. |
IOException |
The device's storage failed. |
Everything else is a result, not an exception: a face check never throws because someone looked away.