Orange textured background

Getting Started

Android SDK — Quick Start

Native device identification for Android. The same hardwareFingerprint a browser produces, plus mobile-native integrity — installable from Maven Central.

Reviewed

Install

The Android SDK is published to Maven Central. Add it to your app module — the published POM carries its transitive dependencies, so they resolve automatically. Requires minSdk 24.

kotlin
repositories {
    mavenCentral()
}
dependencies {
    implementation("io.github.miri-san-so:doorman-benny:0.1.0")
}

app/build.gradle.kts

Two entry points

The SDK exposes two suspend functions, mirroring the web library. getDeviceId collects only the hardware-bound signals and returns the cross-surface hardware id — the same value the same physical device produces in a browser. getFingerprint runs the full pipeline and additionally returns the per-install composite fingerprint, the risk buckets, and the persistent device id.

Both are suspend functions and never throw — call them from a coroutine. On any uncaught error they return a well-formed result with the error attached.

kotlin
import com.bennythedoorman.sdk.DoormanBenny
import kotlinx.coroutines.launch

lifecycleScope.launch {
    // Cross-surface DEVICE id — hardware only, fast. Matches the web SDK on this device.
    val device = DoormanBenny.getDeviceId(context)
    println(device.id)

    // Full result: composite fingerprint + risk + persistent id.
    val fp = DoormanBenny.getFingerprint(context)
    println(fp.fingerprint)                       // per-install composite
    println(fp.hardwareFingerprint)               // == device.id (cross-surface)
    println(fp.persistentId?.id)                  // reinstall-persistent correlator
    println(fp.automation.automationLikelihood)   // low | medium | high
    println(fp.consistency.spoofLikelihood)       // low | medium | high
}

Call from an Activity / Fragment coroutine scope.

What you get

hardwareFingerprint is the cross-surface device hash — use it to recognise the same physical device across a browser visit and your native app, with no manual identity stitching. fingerprint is the per-install composite. persistentId is a reinstall-stable correlator (seeded from the platform device identifier and cached in Keystore-encrypted storage) — a hint to accelerate matching, not an authoritative identity. The consistency and automation blocks carry the mobile risk signals, including tamper and emulator detection, surfaced as low / medium / high likelihoods.

Which signals the Android SDK collects

The native SDK runs the hardware-bound collectors plus the mobile-only sensor signal. The browser-engine signals (canvas, audio, WebGL, and the rest — they depend on browser APIs that don't exist in a native app) return absent on Android and contribute the absent sentinel to the composite fingerprint. The six hardware signals are what build the cross-surface hardwareFingerprint; sensor_calibration adds mobile-only entropy to the per-install composite only.

Per-signal coverage on Android

SignalBindingAndroid
webgl_gpu_identityhardwarecollected
platformhardwarecollected
timezonehardwarecollected
fontshardwarecollected
media_deviceshardwarecollected
architecturehardwarecollected
sensor_calibrationhardware (mobile-only)collected
audioengineabsent
canvasengineabsent
webgl_paramsengineabsent
screenengineabsent
mathengineabsent
css_probeengineabsent
webgl_gpu_traceengineabsent
webgpuengineabsent
speech_voicesengineabsent
storage_quotaengineabsent
apple_payengineabsent
audio_base_latencyengineabsent
screen_frameengineabsent
js_heap_size_limitengineabsent
font_preferencesengineabsent
webgl_pixel_readbackengineabsent
user_agent_dataengineabsent
error_stack_engineengineabsent
permissionsengineabsent
webrtc_sdpengineabsent

Hardware attestation (opt-in)

For tamper-resistant trust the SDK can produce hardware-backed attestation — Google Play Integrity plus an Android Keystore StrongBox key attestation. It is OFF by default and obtained through a dedicated call, never inside getFingerprint, because it is a slow, rate-limited operation and its inputs must come from your server to be replay-safe.

The returned payloads are opaque and are never part of any fingerprint hash — forward them to your backend for verification (Play Integrity token redemption and certificate-chain validation). Play Integrity additionally needs your Google Cloud project number.

kotlin
import com.bennythedoorman.sdk.core.AttestationConfig

val attestation = DoormanBenny.getAttestation(
    context,
    nonce = serverNonce,
    challenge = serverChallenge,
    config = AttestationConfig(enabled = true, cloudProjectNumber = yourGcpProjectNumber),
)
// Send attestation.playIntegrity / attestation.strongBox to your backend to verify.

Attestation is opt-in; nonce and challenge come from your server.

Where to go next

Read the Overview for how the two hashes differ and the three risk tracks. Read Fusion & cross-browser to understand how the cross-surface hardwareFingerprint is built. The iOS SDK is in preview — reach out for early access.

Last reviewed 2026-06-18