Skip to content

Android SDK

Persistent device identification, registration, and real-time fraud detection for Android.

Installation

SDK Access

The Android SDK is provided during onboarding. Follow the installation instructions in your welcome documentation, or contact your Honeypot representative.

Requirements: Android API 21+, Kotlin 1.8+

Permissions:

xml
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Initialization

Initialize once in your Application class:

kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()

        Honeypot.init(this) {
            apiKey = BuildConfig.HONEYPOT_KEY
            endpoint = "https://your-honeypot.honeypot.run"
        }
    }
}

Device ID

Get the persistent device identifier. Survives app reinstalls, cannot be spoofed:

kotlin
val deviceId: String = Honeypot.deviceId

Device Registration

Register devices to users. Honeypot maintains the registry — you don't need to build one.

Register a Device

kotlin
// Register this device to a user
val result = Honeypot.registerDevice(userId = "agent-12345") {
    set("role", "bank_agent")
    set("branch", "lagos-central")
    set("registered_by", "admin@bank.com")
}

result.onSuccess { registration ->
    // Device is now registered
    println("Registered: ${registration.deviceId}")
    println("User: ${registration.userId}")
    println("Registered at: ${registration.registeredAt}")
}

Check Registration Status

kotlin
// Check if current device is registered
val status = Honeypot.device.registration

when {
    !status.isRegistered -> {
        // Device not registered - show registration flow
    }
    status.userId != currentUserId -> {
        // Device registered to different user - security alert
    }
    !status.isActive -> {
        // Device was deactivated - block access
    }
    else -> {
        // Device is registered and trusted
    }
}

Registration in Event Response

Every event response includes registration status:

kotlin
val result = Honeypot.track("Login")

result.onSuccess { response ->
    // Registration info included automatically
    val isRegistered = response.device.isRegistered
    val registeredTo = response.device.registeredTo  // userId or null
    val registeredAt = response.device.registeredAt

    // Plus risk signals
    val riskScore = response.riskScore
    val tags = response.tags
}

Identify Users

Link events to a user identity:

kotlin
Honeypot.identify("user@example.com")

// Or with metadata
Honeypot.identify("agent-12345") {
    set("role", "bank_agent")
    set("branch", "lagos-central")
}

Event Tracking

Track events and get real-time risk signals:

kotlin
val result = Honeypot.track("P2P Transfer") {
    set("recipient_id", recipientId)
    set("amount", amount)
    set("currency", "NGN")
}

result.onSuccess { response ->
    // Device registration status
    val isRegistered = response.device.isRegistered
    val isTrusted = response.device.isTrusted

    // Risk assessment
    val riskScore = response.riskScore
    val tags = response.tags  // ["vpn", "emulator", etc.]

    // Behavioral data
    val txCount = response.behaviors["count_transactions_1h"]?.count ?: 0
}

Full Example: Agent Onboarding

kotlin
class AgentOnboardingViewModel : ViewModel() {

    fun onboardAgent(agentId: String, branchCode: String) = viewModelScope.launch {
        // Step 1: Check for device risks before registration
        val checkResult = Honeypot.track("Agent Onboarding Started") {
            set("agent_id", agentId)
            set("branch_code", branchCode)
        }

        checkResult.onSuccess { response ->
            when {
                // Block compromised devices
                response.tags.containsAny("emulator", "rooted", "hooked") -> {
                    _state.value = OnboardingState.Rejected("Device not supported")
                    return@onSuccess
                }

                // Check if device already registered to someone else
                response.device.isRegistered && response.device.registeredTo != agentId -> {
                    _state.value = OnboardingState.Rejected(
                        "Device already registered to another agent"
                    )
                    return@onSuccess
                }

                // Flag high-risk for manual review
                response.riskScore > 0.5 -> {
                    _state.value = OnboardingState.PendingReview
                    return@onSuccess
                }
            }

            // Step 2: Register the device
            registerDevice(agentId, branchCode)
        }
    }

    private suspend fun registerDevice(agentId: String, branchCode: String) {
        val result = Honeypot.registerDevice(userId = agentId) {
            set("role", "bank_agent")
            set("branch", branchCode)
            set("registered_at", Clock.System.now().toString())
        }

        result.onSuccess { registration ->
            Honeypot.identify(agentId) {
                set("type", "agent")
                set("branch", branchCode)
            }
            _state.value = OnboardingState.Success(registration.deviceId)
        }

        result.onFailure { error ->
            _state.value = OnboardingState.Error(error.message)
        }
    }
}

Full Example: Transaction with Device Verification

kotlin
class TransferViewModel : ViewModel() {

    fun transfer(recipientId: String, amount: Double) = viewModelScope.launch {
        val result = Honeypot.track("P2P Transfer") {
            set("recipient_id", recipientId)
            set("amount", amount)
            set("currency", "NGN")
        }

        result.onSuccess { response ->
            // First: Is this a known, registered device?
            if (!response.device.isRegistered) {
                _state.value = TransferState.Blocked("Please register this device first")
                return@onSuccess
            }

            if (!response.device.isTrusted) {
                _state.value = TransferState.Blocked("Device has been flagged. Contact support.")
                return@onSuccess
            }

            // Second: Check for fraud signals
            if (response.tags.containsAny("vpn", "proxy", "tor")) {
                _state.value = TransferState.Blocked("Please disable VPN")
                return@onSuccess
            }

            // Third: Velocity limits
            val txCount = response.behaviors["count_transactions_1h"]?.count ?: 0
            if (txCount > 10) {
                _state.value = TransferState.Blocked("Too many transactions")
                return@onSuccess
            }

            // Fourth: Step-up auth for risky situations
            if (response.device.ageDays < 7 || response.riskScore > 0.3) {
                _state.value = TransferState.RequiresBiometric
                return@onSuccess
            }

            // Proceed with transfer
            _state.value = TransferState.Ready
        }
    }
}

Response Object

kotlin
data class HoneypotResponse(
    val deviceId: String,
    val device: DeviceInfo,
    val riskScore: Double,
    val tags: Set<String>,
    val behaviors: Map<String, Behavior>,
    val phoneIntel: PhoneIntel?,       // If phone number provided
    val emailIntel: EmailIntel?        // If email provided
)

data class DeviceInfo(
    // Registration status
    val isRegistered: Boolean,
    val isTrusted: Boolean,           // Registered AND not flagged
    val registeredTo: String?,        // userId this device is registered to
    val registeredAt: Instant?,
    val role: String?,                // "bank_agent", "customer", "driver", etc.
    val metadata: Map<String, Any>,   // Custom registration metadata

    // Device metadata
    val ageDays: Int,
    val isNew: Boolean,
    val model: String?,
    val osVersion: String?
)

data class DeviceRegistration(
    val deviceId: String,
    val userId: String,
    val role: String,
    val registeredAt: Instant,
    val metadata: Map<String, Any>
)

data class Behavior(
    val count: Int?,                  // For count operations
    val sum: Double?,                 // For sum operations
    val unique: Int?,                 // For unique operations
    val values: List<String>?         // Unique values (if requested)
)

Device Management API

kotlin
// Register device with role
Honeypot.registerDevice(userId = "agent-123") {
    set("role", "bank_agent")
    set("branch", "lagos-central")
}

// Check current registration
val registration = Honeypot.device.registration
if (registration.role == "bank_agent") {
    // Show agent UI
}

// Deactivate this device (lost/stolen)
Honeypot.deactivateDevice(reason = "reported_stolen")

Supervisor API (REST)

bash
# List all devices for a branch
GET /api/devices?role=bank_agent&branch=lagos-central

# Deactivate a specific device
POST /api/devices/{device_id}/deactivate
{ "reason": "agent_terminated", "by": "supervisor-001" }

# Transfer device to new agent
POST /api/devices/{device_id}/transfer
{ "new_user_id": "agent-456", "by": "supervisor-001" }

Risk Tags

TagSeverityDescription
emulatorCriticalRunning on emulator
rootedCriticalRoot access detected
hookedCriticalFrida/Xposed detected
vpnHighVPN connection
proxyHighProxy detected
torCriticalTor network
new_deviceMediumDevice < 24h old
unregisteredMediumDevice not registered
multi_userHighRegistered to multiple users

Offline Support

Critical for agent banking in areas with poor connectivity:

kotlin
// Events are queued automatically when offline
Honeypot.track("Agent Deposit") {
    set("amount", 50000)
    set("customer_id", customerId)
}
// Returns immediately with cached device info
// Syncs to server when connectivity returns

// Check sync status
val pending = Honeypot.pendingEvents
val lastSync = Honeypot.lastSyncTime

// Force sync when connectivity available
Honeypot.sync()

Offline behavior:

  • Events queued in local database (SQLite)
  • Device registration status cached locally
  • Risk decisions use cached data + local checks (emulator, root)
  • Auto-sync when connectivity returns
  • Conflict resolution: server wins for registration, merge for events

Next Steps