Skip to main content
The Truemetrics SDK provides advanced sensor data collection and analytics capabilities for Android applications. This guide covers all aspects of integrating and using the SDK effectively.

Table of Contents


Installation

Add the Truemetrics SDK to your app’s build.gradle file:
dependencies {
    implementation 'io.truemetrics:truemetricssdk:1.4.0'
}

Quick Start

1. Initialize the SDK in your Application class

class MyApplication : Application() {
    override fun onCreate() {
        super.onCreate()

        val config = SdkConfiguration.Builder("YOUR_API_KEY").build()
        TruemetricsSdk.init(this, config)
    }
}

2. Start and stop recordings

val sdk = TruemetricsSdk.getInstance()

// Start recording sensor data
sdk.startRecording()

// Stop recording
sdk.stopRecording()

// Check recording status
if (sdk.isRecordingInProgress()) {
    // Recording is active
}

Configuration

The SDK is configured using the SdkConfiguration.Builder class.

Basic Configuration

val config = SdkConfiguration.Builder("YOUR_API_KEY").build()

Custom Foreground Notification

Customize the notification shown when the SDK is running as a foreground service using the SDK’s notification channel:
class CustomNotificationFactory : ForegroundNotificationFactory {
    override fun createNotification(context: Context): Notification {
        // Use SDK's notification channel ID
        return NotificationCompat.Builder(context, "FOREGROUND_SERVICE")
            .setContentTitle("Truemetrics SDK Running")
            .setContentText("Collecting sensor data...")
            .setSmallIcon(R.drawable.ic_sensors)
            .setOngoing(true)
            .build()
    }
}

val config = SdkConfiguration.Builder("YOUR_API_KEY")
    .foregroundNotificationFactory(CustomNotificationFactory())
    .build()

Core Features

Recording Management

val sdk = TruemetricsSdk.getInstance()

// Start recording
sdk.startRecording()

// Stop recording
sdk.stopRecording()

// Check recording status
val isRecording = sdk.isRecordingInProgress()
val isStopped = sdk.isRecordingStopped()

// Get recording start time
val startTime = sdk.getRecordingStartTime() // Returns timestamp in milliseconds

Device ID

Get the unique device identifier (available after initialization):
val deviceId = sdk.getDeviceId()

// Or get from Status
sdk.observeSdkStatus().collect { status ->
    when (status) {
        is Status.Initialized -> println("Device ID: ${status.deviceId}")
        is Status.RecordingInProgress -> println("Device ID: ${status.deviceId}")
        else -> {}
    }
}

Metadata Logging

Attach custom metadata to your recordings:
sdk.logMetadata(mapOf(
    "userId" to "user123",
    "sessionId" to "session_abc",
    "appVersion" to "1.2.3"
))
For advanced metadata with templates and tags, see Metadata Guide.

Sensor Management

// Enable/disable all sensors
sdk.setAllSensorsEnabled(true)

// Check if sensors are enabled
val enabled = sdk.getAllSensorsEnabled()

// Observe available sensors
sdk.sensorInfo.collect { sensors ->
    sensors.forEach { sensor ->
        println("Sensor: ${sensor.sensorName}, Status: ${sensor.sensorStatus}")
        println("Frequency: ${sensor.frequency} Hz")
        if (sensor.missingPermissions.isNotEmpty()) {
            println("Missing permissions: ${sensor.missingPermissions}")
        }
    }
}

Complete Cleanup

sdk.deinitialize()
Warning: After calling deinitialize(), the SDK instance becomes unusable. You must call init() again to use the SDK.

SDK Status

Monitor the SDK state using observeSdkStatus():
sdk.observeSdkStatus().collect { status ->
    when (status) {
        is Status.Uninitialized -> {
            // SDK not yet initialized
        }
        is Status.Initialized -> {
            // SDK initialized, deviceId available
            val deviceId = status.deviceId
        }
        is Status.RecordingInProgress -> {
            // Recording is active
            val deviceId = status.deviceId
        }
        is Status.RecordingStopped -> {
            // Recording has stopped
        }
        is Status.DelayedStart -> {
            // Waiting for auto-start delay
            val deviceId = status.deviceId
            val delayMs = status.delayMs
        }
        is Status.TrafficLimitReached -> {
            // Traffic limit reached
        }
        is Status.ReadingsDatabaseFull -> {
            // Device storage full
        }
        is Status.Error -> {
            // SDK encountered an error
            val errorCode = status.errorCode
            val message = status.message
        }
        is Status.AskForPermissions -> {
            // SDK requesting permissions
            val permissions = status.permissions
        }
    }
}

Error Codes

Error CodeDescription
AUTHENTICATION_ERRORAPI key is not valid, expired or revoked
UPLOAD_ERRORRecordings couldn’t be uploaded after exhausting all attempts
STORAGE_FULLDevice storage is full which prevents saving sensor readings
MISSING_NOTIFICATION_PERMISSIONNotification permission not granted, foreground service cannot start
CONFIG_ERRORConfiguration error
TRAFFIC_USED_UPAll allotted traffic has been used
SENSORS_NOT_WORKINGSome sensors are not working. Check if permissions are missing

Statistics API

Upload Statistics

Monitor upload health:
val uploadStats = sdk.getUploadStatistics()
if (uploadStats != null) {
    println("Successful uploads: ${uploadStats.successfulUploadsCount}")
    println("Last upload: ${uploadStats.lastSuccessfulUploadTimestamp}")
}

Sensor Statistics

Get detailed sensor data quality:
val sensorStats = sdk.getSensorStatistics()
sensorStats?.forEach { stat ->
    println("Sensor: ${stat.sensorName}")
    println("Configured: ${stat.configuredFrequencyHz} Hz")
    println("Actual: ${stat.actualFrequencyHz} Hz")
    println("Quality: ${stat.quality}")
}
Quality levels:
  • EXCELLENT: 95-100% of configured frequency
  • GOOD: 80-95%
  • POOR: 50-80%
  • BAD: less than 50%
  • UNKNOWN: no data or not recording

Best Practices

1. Initialization

  • Always initialize in your Application class
  • Use the application context, not activity context
  • Initialize once and reuse the singleton instance

2. Error Handling

sdk.observeSdkStatus().collect { status ->
    when (status) {
        is Status.Error -> {
            Log.e("SDK", "Error: ${status.errorCode} - ${status.message}")
        }
        is Status.ReadingsDatabaseFull -> {
            Log.w("SDK", "Storage full")
        }
        else -> {}
    }
}

3. Monitoring SDK Health

fun checkSdkHealth() {
    val uploadStats = sdk.getUploadStatistics()
    if (uploadStats != null && uploadStats.successfulUploadsCount == 0) {
        Log.w("SDK", "No successful uploads yet")
    }

    val sensorStats = sdk.getSensorStatistics()
    sensorStats?.filter { it.quality == SensorDataQuality.BAD }?.forEach {
        Log.w("SDK", "Bad quality for: ${it.sensorName}")
    }
}

API Reference

TruemetricsSdk

MethodReturn TypeDescription
init(context, config)TruemetricsSdkInitialize SDK (static)
getInstance()TruemetricsSdkGet singleton instance (static)
startRecording()UnitStart sensor recording
stopRecording()UnitStop sensor recording
isRecordingInProgress()BooleanCheck if recording active
isRecordingStopped()BooleanCheck if recording stopped
getRecordingStartTime()LongGet recording start timestamp
getDeviceId()String?Get unique device identifier
logMetadata(payload)UnitLog custom metadata
setAllSensorsEnabled(enabled)UnitEnable/disable all sensors
getAllSensorsEnabled()BooleanGet sensor enable status
getActiveConfig()Configuration?Get active backend configuration
getUploadStatistics()UploadStatistics?Get upload stats
getSensorStatistics()List<SensorStatistics>?Get sensor stats
deinitialize()UnitShutdown SDK completely

Observable Flows

Property/MethodTypeDescription
sensorInfoStateFlow<Iterable<SensorInfo>>Available sensors info
sdkStatusStateFlow<Status>SDK operational status
observeSdkStatus()Flow<Status>Observe SDK status changes
getActiveConfigFlow()Flow<Configuration>?Observe backend config changes

Data Classes

UploadStatistics

PropertyTypeDescription
successfulUploadsCountIntTotal successful uploads
lastSuccessfulUploadTimestampLong?Last upload timestamp

SensorStatistics

PropertyTypeDescription
sensorNameSensorNameSensor identifier
configuredFrequencyHzFloatConfigured frequency
actualFrequencyHzFloatActual measured frequency
qualitySensorDataQualityQuality assessment

SensorInfo

PropertyTypeDescription
sensorNameSensorNameSensor identifier
sensorStatusSensorStatusStatus: ON, OFF, or NA
frequencyFloatPolling frequency in Hz
missingPermissionsList<String>Required permissions not granted