Documentation Index
Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt
Use this file to discover all available pages before exploring further.
Overview
The Synheart Behavior Kotlin/Android SDK provides real-time behavioral signal inference from digital interactions for native Android applications.
Installation
Add to your build.gradle:
dependencies {
implementation 'ai.synheart:behavior:0.4.1'
}
Requirements
- Android API 21+ (Android 5.0+)
- Kotlin 1.9.0+
- Gradle 8.0+
Quick Start
Basic Usage
import ai.synheart.behavior.*
import android.app.Application
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
class MyApplication : Application() {
lateinit var behavior: SynheartBehavior
private set
override fun onCreate() {
super.onCreate()
val config = BehaviorConfig(
enableInputSignals = true,
enableAttentionSignals = true,
enableMotionLite = true, // Enable motion state inference (LAYING, MOVING, SITTING, STANDING)
)
behavior = SynheartBehavior.create(this, config)
behavior.initialize()
}
}
class MainActivity : AppCompatActivity() {
private val behavior by lazy { (application as MyApplication).behavior }
private var currentSession: BehaviorSession? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Attach to views for gesture tracking
behavior.attachToView(findViewById(android.R.id.content))
// Start a session
startSession()
}
private fun startSession() {
try {
currentSession = behavior.startSession()
android.util.Log.d("Behavior", "Session started: ${currentSession?.sessionId}")
} catch (e: Exception) {
android.util.Log.e("Behavior", "Failed to start session: $e")
}
}
}
Real-Time Event Tracking
// Using callback handler
behavior.setEventHandler { event ->
android.util.Log.d("Behavior", "Event: ${event.eventType} at ${event.timestamp}")
android.util.Log.d("Behavior", "Metrics: ${event.metrics}")
// Handle different event types
when (event.eventType) {
BehaviorEventType.SCROLL -> {
val velocity = event.metrics["velocity"] as? Double
android.util.Log.d("Behavior", "Scroll velocity: $velocity px/s")
}
BehaviorEventType.TAP -> {
val duration = event.metrics["tap_duration_ms"] as? Int
android.util.Log.d("Behavior", "Tap duration: $duration ms")
}
BehaviorEventType.SWIPE -> {
val direction = event.metrics["direction"] as? String
android.util.Log.d("Behavior", "Swipe direction: $direction")
}
BehaviorEventType.TYPING -> {
val speed = event.metrics["typing_speed"] as? Double
val tapCount = event.metrics["typing_tap_count"] as? Int
android.util.Log.d("Behavior", "Typing speed: $speed, tap count: $tapCount")
}
else -> {}
}
}
// Or using Kotlin Flow (reactive approach)
import kotlinx.coroutines.flow.collect
import androidx.lifecycle.lifecycleScope
lifecycleScope.launch {
behavior.onEvent.collect { event ->
when (event.eventType) {
BehaviorEventType.SCROLL -> {
// Handle scroll event
}
BehaviorEventType.TYPING -> {
// Handle typing event
}
// ... handle other event types
else -> {}
}
}
}
Session Management
// Start a session
val session = behavior.startSession()
android.util.Log.d("Behavior", "Session started: ${session.sessionId}")
// ... user interacts with app ...
// End session and get summary
val summary = behavior.endSession(session.sessionId)
android.util.Log.d("Behavior", "Session duration: ${summary.durationMs}ms")
android.util.Log.d("Behavior", "Total events: ${summary.activitySummary.totalEvents}")
android.util.Log.d("Behavior", "Focus hint: ${summary.behavioralMetrics.focusHint}")
android.util.Log.d("Behavior", "Distraction score: ${summary.behavioralMetrics.behavioralDistractionScore}")
On-Demand Metrics Calculation
Calculate behavioral metrics for a custom time range within a session:
// Calculate metrics for a specific time range
val metrics = behavior.calculateMetricsForTimeRange(
startTimestampSeconds = 1767688063, // Unix timestamp in seconds
endTimestampSeconds = 1767688130, // Unix timestamp in seconds
sessionId = "SESS-1767688063415" // Optional: uses current session if not provided
)
// Access the calculated metrics
val activitySummary = metrics["activity_summary"] as Map<*, *>
android.util.Log.d("Behavior", "Total events: ${activitySummary["total_events"]}")
android.util.Log.d("Behavior", "App switches: ${activitySummary["app_switch_count"]}")
val behavioralMetrics = metrics["behavioral_metrics"] as Map<*, *>
android.util.Log.d("Behavior", "Interaction intensity: ${behavioralMetrics["interaction_intensity"]}")
android.util.Log.d("Behavior", "Distraction score: ${behavioralMetrics["behavioral_distraction_score"]}")
android.util.Log.d("Behavior", "Focus hint: ${behavioralMetrics["focus_hint"]}")
// Motion state (if motion data is available)
(metrics["motion_state"] as? Map<*, *>)?.let { motionState ->
android.util.Log.d("Behavior", "Motion state: ${motionState["major_state"]}")
android.util.Log.d("Behavior", "Confidence: ${motionState["confidence"]}")
}
// Device context
val deviceContext = metrics["device_context"] as Map<*, *>
android.util.Log.d("Behavior", "Screen brightness: ${deviceContext["avg_screen_brightness"]}")
android.util.Log.d("Behavior", "Orientation: ${deviceContext["start_orientation"]}")
// System state
val systemState = metrics["system_state"] as Map<*, *>
android.util.Log.d("Behavior", "Internet: ${systemState["internet_state"]}")
android.util.Log.d("Behavior", "Do not disturb: ${systemState["do_not_disturb"]}")
Note: The time range must be within the session’s start and end times. The SDK automatically validates this and will throw an error if the range is out of bounds.
API Reference
SynheartBehavior
Main Methods:
| Method | Description | Returns |
|---|
create(context, config) | Create SDK instance | SynheartBehavior |
initialize() | Initialize SDK | void |
attachToView(view) | Attach to view for gesture tracking | void |
startSession({sessionId}) | Start a new session | BehaviorSession |
endSession(sessionId) | End session and get summary | BehaviorSessionSummary |
calculateMetricsForTimeRange(...) | Calculate metrics for custom time range | Map<String, Any> |
getCurrentStats() | Get current statistics | BehaviorStats |
setEventHandler(callback) | Set callback for events | void |
sendEvent(event) | Manually send an event | void |
dispose() | Clean up resources | void |
calculateMetricsForTimeRange()
Calculate behavioral metrics for a custom time range within a session.
Parameters:
| Parameter | Type | Required | Description |
|---|
startTimestampSeconds | Long | Yes | Start time as Unix timestamp in seconds |
endTimestampSeconds | Long | Yes | End time as Unix timestamp in seconds |
sessionId | String? | No | Session ID (uses current session if not provided) |
Returns: Map<String, Any> - Map containing all behavioral metrics for the specified time range
Throws: Exception if time range is out of session bounds or session not found
Example:
val now = System.currentTimeMillis() / 1000
val fiveMinutesAgo = now - 300
val metrics = behavior.calculateMetricsForTimeRange(
startTimestampSeconds = fiveMinutesAgo,
endTimestampSeconds = now
)
// Access metrics
val totalEvents = (metrics["activity_summary"] as Map<*, *>)["total_events"] as Int
val intensity = (metrics["behavioral_metrics"] as Map<*, *>)["interaction_intensity"] as Double
Properties:
| Property | Type | Description |
|---|
isInitialized | Boolean | Whether SDK is initialized |
currentSessionId | String? | Current active session ID |
onEvent | Flow<BehaviorEvent> | Flow of behavioral events |
BehaviorConfig
Parameters:
| Parameter | Type | Default | Description |
|---|
enableInputSignals | Boolean | true | Enable scroll, tap, swipe, typing tracking |
enableAttentionSignals | Boolean | true | Enable app switching, idle gaps |
enableMotionLite | Boolean | false | Enable motion state inference |
sessionIdPrefix | String? | null | Prefix for session IDs (null = auto-generated) |
userId | String? | null | Optional user identifier |
deviceId | String? | null | Optional device identifier |
eventBatchSize | Int | 10 | Events per batch |
maxIdleGapSeconds | Double | 10.0 | Max idle time before task drop |
behaviorVersion | String? | null | SDK version for HSI payloads |
consentBehavior | Boolean | true | Behavior tracking consent |
BehaviorEvent
Properties:
| Property | Type | Description |
|---|
eventId | String | Unique event identifier |
sessionId | String | Associated session ID |
timestamp | String | ISO 8601 timestamp |
eventType | BehaviorEventType | Type of event |
metrics | Map<String, Any> | Event-specific metrics |
Event Types:
BehaviorEventType.SCROLL - Scroll interactions
BehaviorEventType.TAP - Tap interactions
BehaviorEventType.SWIPE - Swipe interactions
BehaviorEventType.APP_SWITCH - Foreground / background app-switch events
BehaviorEventType.NOTIFICATION - Notification events
BehaviorEventType.CALL - Call events
BehaviorEventType.TYPING - Typing session events (timing only — never characters)
BehaviorEventType.CLIPBOARD - Clipboard activity (copy / paste / cut counts only — never content)
BehaviorSession
Properties:
| Property | Type | Description |
|---|
sessionId | String | Session identifier |
BehaviorSessionSummary
Properties:
| Property | Type | Description |
|---|
sessionId | String | Session identifier |
startAt | String | ISO 8601 session start time |
endAt | String | ISO 8601 session end time |
durationMs | Long | Session duration in milliseconds |
behavioralMetrics | BehavioralMetrics | Behavioral metrics |
activitySummary | ActivitySummary | Activity summary |
notificationSummary | NotificationSummary | Notification summary |
motionState | MotionState? | Motion state (if enabled) |
typingSessionSummary | TypingSessionSummary? | Typing session summary (if typing occurred) |
motionData | List<MotionDataPoint>? | Raw motion data points (if enabled) |
BehavioralMetrics
Properties:
| Property | Type | Description |
|---|
interactionIntensity | Double | Overall interaction rate (0-1) |
behavioralDistractionScore | Double | Distraction proxy (0-1) |
focusHint | Double | Focus quality proxy (0-1) |
deepFocusBlocks | List<DeepFocusBlock> | Sustained focus periods |
taskSwitchRate | Double | App switching frequency |
idleRatio | Double | Proportion of idle time |
fragmentedIdleRatio | Double | Fragmented vs continuous idle |
burstiness | Double | Temporal clustering of events |
notificationLoad | Double | Notification pressure |
scrollJitterRate | Double | Scroll pattern irregularity |
typingSpeed | Double | Average typing speed (taps per second) |
typingCadenceStability | Double | Consistency of typing rhythm (0-1) |
typingCadenceVariability | Double | Variability in timing between taps |
typingActivityRatio | Double | Fraction of session with active typing (0-1) |
typingGapRatio | Double | Proportion of intervals that are gaps (0-1) |
typingBurstiness | Double | Temporal clustering of typing events |
typingInteractionIntensity | Double | Overall typing engagement (0-1) |
clipboardActivityRate | Double | (copy+paste+cut)/(typing+clipboard) |
correctionRate | Double | (backspace+delete)/(typing+backspace+delete) |
Typing: clipboard and correction rates
The typing session summary includes clipboardActivityRate and correctionRate, derived from backspace/copy/paste/cut event counts on the SDK. Use BehaviorEditText (or wire copy/paste/cut callbacks) so copy/paste/cut are reported. Cut is not counted as backspace.
Permissions
Notification Permission
// Check if notification listener is enabled
val isEnabled = behavior.checkNotificationListenerEnabled()
if (!isEnabled) {
// Open system settings to enable notification access
behavior.requestNotificationListenerAccess()
}
// Check if notification permission is granted (Android 13+)
val hasPermission = behavior.checkNotificationPermission()
if (!hasPermission) {
// Request permission using Activity.requestPermissions() or ActivityResultContracts
// After permission is granted, call:
behavior.hotRestartCollectors()
}
Call Permission
// Check if permission is granted
val hasPermission = behavior.checkCallPermission()
if (!hasPermission) {
// Request permission using Activity.requestPermissions() or ActivityResultContracts
// After permission is granted, call:
behavior.reinitializePhoneStateListener()
}
Configuration
Update Configuration at Runtime
behavior.updateConfig(BehaviorConfig(
enableInputSignals = true,
enableAttentionSignals = true,
enableMotionLite = true,
))
Note: Configuration can only be updated when no session is active.
View Attachment
To track gestures on specific views, attach the SDK to them:
// Attach to a ScrollView
behavior.attachToView(scrollView)
// Attach to a RecyclerView
behavior.attachToView(recyclerView)
// Attach to an Activity's root view
behavior.attachToView(findViewById(android.R.id.content))
Automatic Session Ending
Sessions are automatically ended after 1 minute if the app stays in the background. This prevents sessions from running indefinitely when users switch away from your app.
Resources
For comprehensive documentation, see the full README on GitHub.