{"id":50833203,"url":"https://github.com/synheart-ai/synheart-behavior-kotlin","last_synced_at":"2026-06-14T01:30:39.319Z","repository":{"id":339322803,"uuid":"1095754265","full_name":"synheart-ai/synheart-behavior-kotlin","owner":"synheart-ai","description":"Android SDK for behavioral signals — typing, gestures, motion, attention, notifications.","archived":false,"fork":false,"pushed_at":"2026-05-22T07:02:51.000Z","size":99682,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T15:22:26.233Z","etag":null,"topics":["android","attention","behavioral-analytics","kotlin","motion","sdk","typing"],"latest_commit_sha":null,"homepage":"https://central.sonatype.com/artifact/ai.synheart/synheart-behavior","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/synheart-ai.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-11-13T13:28:54.000Z","updated_at":"2026-05-22T07:02:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/synheart-ai/synheart-behavior-kotlin","commit_stats":null,"previous_names":["synheart-ai/synheart-behavior-kotlin"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/synheart-ai/synheart-behavior-kotlin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-kotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-kotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-kotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-kotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/synheart-ai","download_url":"https://codeload.github.com/synheart-ai/synheart-behavior-kotlin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/synheart-ai%2Fsynheart-behavior-kotlin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34306772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-13T02:00:06.617Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","attention","behavioral-analytics","kotlin","motion","sdk","typing"],"created_at":"2026-06-14T01:30:38.565Z","updated_at":"2026-06-14T01:30:39.311Z","avatar_url":"https://github.com/synheart-ai.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Synheart Behavioral SDK for Android\n\n[![CI](https://github.com/synheart-ai/synheart-behavior-kotlin/actions/workflows/ci.yml/badge.svg)](https://github.com/synheart-ai/synheart-behavior-kotlin/actions/workflows/ci.yml)\n[![Maven Central](https://img.shields.io/maven-central/v/ai.synheart/synheart-behavior.svg)](https://central.sonatype.com/artifact/ai.synheart/synheart-behavior)\n[![Platform](https://img.shields.io/badge/platform-Android%20API%2021%2B-brightgreen)](https://developer.android.com)\n[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)\n\n\u003e **Source-available.** This repository is open for reading, auditing, and\n\u003e filing issues. We do **not** accept pull requests — see\n\u003e [CONTRIBUTING.md](CONTRIBUTING.md) for the rationale and how to contribute\n\u003e via issues. Security reports go through [SECURITY.md](SECURITY.md).\n\nA privacy-preserving mobile SDK that collects digital behavioral signals from smartphones. The SDK models how users interact with digital systems — timing, rhythm, switching, and fragmentation — without ever accessing content, text, or personal data. Downstream consumers turn these raw signals into per-session aggregates and higher-level inferences.\n\n## Features\n\n- **Privacy-First**: No text, content, or personally identifiable information (PII) collected—only timing-based signals\n- **Real-Time Streaming**: Event streams for scroll, tap, swipe, notification, call, and typing interactions\n- **Session Tracking**: Built-in session management with comprehensive summaries\n- **On-Demand Metrics**: Calculate behavioral metrics for custom time ranges within sessions\n- **Motion State Prediction**: Activity recognition (LAYING, MOVING, SITTING, STANDING) using ML model inference\n- **Kotlin-First**: Modern Kotlin API with coroutines and Flow support\n- **Zero Permissions**: No special permissions required for basic functionality\n- **Platform Support**: Android API 21+ (Android 5.0+)\n\n## Installation\n\n### Gradle\n\nAdd to your `build.gradle`:\n\n```gradle\ndependencies {\n    implementation 'ai.synheart:synheart-behavior:0.5.0'\n}\n```\n\n### Maven\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eai.synheart\u003c/groupId\u003e\n    \u003cartifactId\u003esynheart-behavior\u003c/artifactId\u003e\n    \u003cversion\u003e0.4.1\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n### Native dependencies\n\nThis SDK is **self-contained** and does **not** require bundling any native `.so` libraries.\n\n- Motion inference uses ONNX Runtime via the `onnxruntime-android` Gradle dependency.\n- No other native binaries are bundled or vendored.\n\n## Quick Start\n\nHere's a complete example to get you started:\n\n```kotlin\nimport ai.synheart.behavior.*\nimport android.app.Application\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompatActivity\n\nclass MyApplication : Application() {\n    lateinit var behavior: SynheartBehavior\n        private set\n\n    override fun onCreate() {\n        super.onCreate()\n\n        val config = BehaviorConfig(\n            enableInputSignals = true,\n            enableAttentionSignals = true,\n            enableMotionLite = false\n        )\n\n        behavior = SynheartBehavior.create(this, config)\n        behavior.initialize()\n    }\n}\n\nclass MainActivity : AppCompatActivity() {\n    private val behavior by lazy { (application as MyApplication).behavior }\n    private var currentSession: BehaviorSession? = null\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        // Set up event handler (callback approach)\n        behavior.setEventHandler { event -\u003e\n            android.util.Log.d(\"Behavior\", \"Event: ${event.eventType} at ${event.timestamp}\")\n            android.util.Log.d(\"Behavior\", \"Metrics: ${event.metrics}\")\n        }\n\n        // Or use Flow for reactive event streaming\n        lifecycleScope.launch {\n            behavior.onEvent.collect { event -\u003e\n                android.util.Log.d(\"Behavior\", \"Event: ${event.eventType}\")\n            }\n        }\n\n        // Start a session\n        startSession()\n    }\n\n    private fun startSession() {\n        try {\n            currentSession = behavior.startSession()\n            android.util.Log.d(\"Behavior\", \"Session started: ${currentSession?.sessionId}\")\n        } catch (e: Exception) {\n            android.util.Log.e(\"Behavior\", \"Failed to start session: $e\")\n        }\n    }\n\n    private fun endSession() {\n        currentSession?.let { session -\u003e\n            try {\n                val summary = behavior.endSession(session.sessionId)\n                android.util.Log.d(\"Behavior\", \"Session ended: ${summary.durationMs}ms\")\n                android.util.Log.d(\"Behavior\", \"Total events: ${summary.activitySummary.totalEvents}\")\n                android.util.Log.d(\"Behavior\", \"Focus hint: ${summary.behavioralMetrics.focusHint}\")\n                currentSession = null\n            } catch (e: Exception) {\n                android.util.Log.e(\"Behavior\", \"Failed to end session: $e\")\n            }\n        }\n    }\n\n    override fun onDestroy() {\n        super.onDestroy()\n        behavior.dispose()\n    }\n}\n```\n\n### Key Steps\n\n1. **Initialize the SDK** - Create and initialize `SynheartBehavior` in your `Application` class\n2. **Attach to Views** - Use `attachToView()` to enable gesture tracking on views\n3. **Listen to Events** - Set an event handler or use Flow to receive real-time behavioral signals\n4. **Track Sessions** - Start and end sessions to get behavioral summaries\n5. **Clean Up** - Call `dispose()` when done to free resources\n\n## Real-Time Event Tracking\n\nThe SDK streams behavioral events in real-time as they occur. This is the primary way to track user behavior:\n\n### Using Callback Handler\n\n```kotlin\nbehavior.setEventHandler { event -\u003e\n    android.util.Log.d(\"Behavior\", \"Event: ${event.eventType} at ${event.timestamp}\")\n    android.util.Log.d(\"Behavior\", \"Metrics: ${event.metrics}\")\n\n    // Handle different event types\n    when (event.eventType) {\n        BehaviorEventType.SCROLL -\u003e {\n            val velocity = event.metrics[\"velocity\"] as? Double\n            android.util.Log.d(\"Behavior\", \"Scroll velocity: $velocity px/s\")\n        }\n        BehaviorEventType.TAP -\u003e {\n            val duration = event.metrics[\"tap_duration_ms\"] as? Int\n            val longPress = event.metrics[\"long_press\"] as? Boolean\n            android.util.Log.d(\"Behavior\", \"Tap duration: $duration ms, long press: $longPress\")\n        }\n        BehaviorEventType.SWIPE -\u003e {\n            val direction = event.metrics[\"direction\"] as? String\n            val velocity = event.metrics[\"velocity\"] as? Double\n            android.util.Log.d(\"Behavior\", \"Swipe direction: $direction, velocity: $velocity px/s\")\n        }\n        BehaviorEventType.TYPING -\u003e {\n            val tapCount = event.metrics[\"typing_tap_count\"] as? Int\n            val speed = event.metrics[\"typing_speed\"] as? Double\n            val deepTyping = event.metrics[\"deep_typing\"] as? Boolean\n            android.util.Log.d(\"Behavior\", \"Typing: $tapCount taps, speed: $speed, deep: $deepTyping\")\n        }\n        // ... handle other event types\n        else -\u003e {}\n    }\n}\n```\n\n### Using Flow (Reactive Approach)\n\n```kotlin\nimport kotlinx.coroutines.flow.collect\nimport androidx.lifecycle.lifecycleScope\n\nlifecycleScope.launch {\n    behavior.onEvent.collect { event -\u003e\n        when (event.eventType) {\n            BehaviorEventType.SCROLL -\u003e {\n                // Handle scroll event\n            }\n            BehaviorEventType.TYPING -\u003e {\n                // Handle typing event\n            }\n            // ... handle other event types\n            else -\u003e {}\n        }\n    }\n}\n```\n\n## Event Types\n\nThe SDK collects six types of behavioral events:\n\n- **Scroll**: Velocity, acceleration, direction, direction reversals\n- **Tap**: Duration, long-press detection\n- **Swipe**: Direction, distance, velocity, acceleration\n- **Notification**: Received, opened, ignored (requires permission)\n- **Call**: Answered, ignored, dismissed (requires permission)\n- **Typing**: Comprehensive typing session metrics including speed, cadence, burstiness, and deep typing detection. Clipboard activity rate and correction rate are derived downstream from per-typing-session counts on each event.\n\n**Note**: App switch events (`APP_SWITCH`) are tracked internally and emitted on the event stream for downstream task-switch calculations, but are not displayed as one of the six event types in UI lists. App switch count is available in session summaries via `activitySummary.appSwitchCount`.\n\nEach event includes:\n\n- `eventId`: Unique identifier\n- `sessionId`: Associated session ID\n- `timestamp`: ISO 8601 timestamp\n- `eventType`: Type of event (scroll, tap, swipe, etc.)\n- `metrics`: Event-specific metrics (velocity, duration, etc.)\n\n## Permissions\n\n**Note**: Basic functionality (scroll, tap, swipe) requires **no permissions**. The following permissions are optional and only needed for notification and call tracking.\n\n### Notification Permission\n\nRequired for tracking notification interactions (received, opened, ignored).\n\n**Android**: Requires enabling Notification Access in system settings\n\n```kotlin\n// Check if notification listener is enabled\nval isEnabled = behavior.checkNotificationListenerEnabled()\n\nif (!isEnabled) {\n    // Open system settings to enable notification access\n    behavior.requestNotificationListenerAccess()\n}\n\n// Check if notification permission is granted (Android 13+)\nval hasPermission = behavior.checkNotificationPermission()\n```\n\n### Call Permission\n\nRequired for tracking call interactions (answered, ignored, dismissed).\n\n**Android**: Requires `READ_PHONE_STATE` permission\n\n```kotlin\n// Check if permission is granted\nval hasPermission = behavior.checkCallPermission()\n\nif (!hasPermission) {\n    // Request permission using Activity.requestPermissions() or ActivityResultContracts\n    // After permission is granted, call:\n    behavior.reinitializePhoneStateListener()\n}\n```\n\n## Configuration\n\n### Initial Configuration\n\nConfigure the SDK during creation:\n\n```kotlin\nval config = BehaviorConfig(\n    // Enable/disable signal types\n    enableInputSignals = true,        // Scroll, tap, swipe gestures\n    enableAttentionSignals = true,    // App switching, idle gaps, session stability\n    enableMotionLite = false,         // Device motion + ML inference (optional, may impact battery)\n\n    // Session configuration\n    sessionIdPrefix = \"MYAPP\",        // Custom session ID prefix (default: \"SESS\")\n    eventBatchSize = 10,              // Events per batch for streaming (default: 10)\n\n    // Advanced settings\n    maxIdleGapSeconds = 10.0,         // Max idle time before task drop (default: 10.0)\n\n    // HSI payload fields (optional)\n    userId = \"anon_43a8cd\",           // Anonymous user ID (auto-generated if null)\n    deviceId = \"synheart_android_14\", // Device ID (auto-generated if null)\n    behaviorVersion = \"0.4.0\",       // SDK version for HSI payloads\n    consentBehavior = true            // Behavior tracking consent (default: true)\n)\n\nval behavior = SynheartBehavior.create(context, config)\nbehavior.initialize()\n```\n\n### Update Configuration at Runtime\n\nYou can update the configuration after initialization:\n\n```kotlin\n// Disable motion tracking to save battery\nbehavior.updateConfig(BehaviorConfig(\n    enableInputSignals = true,\n    enableAttentionSignals = true,\n    enableMotionLite = false,  // Disabled\n))\n```\n\n**Note**: Configuration can only be updated when no session is active.\n\n## Session Management\n\n### Starting a Session\n\n```kotlin\n// Start with auto-generated session ID\nval session = behavior.startSession()\n\n// Or provide a custom session ID\nval session = behavior.startSession(\"MYAPP-${System.currentTimeMillis()}\")\n```\n\n**Note**: 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.\n\n### Ending a Session\n\nWhen a session ends, you receive a comprehensive summary:\n\n```kotlin\nval summary = behavior.endSession(session.sessionId)\n\n// Session metadata\nandroid.util.Log.d(\"Behavior\", \"Session ID: ${summary.sessionId}\")\nandroid.util.Log.d(\"Behavior\", \"Started: ${summary.startAt}\")\nandroid.util.Log.d(\"Behavior\", \"Ended: ${summary.endAt}\")\nandroid.util.Log.d(\"Behavior\", \"Duration: ${summary.durationMs}ms\")\n\n// Behavioral metrics\nandroid.util.Log.d(\"Behavior\", \"Focus Hint: ${summary.behavioralMetrics.focusHint}\")\nandroid.util.Log.d(\"Behavior\", \"Distraction Score: ${summary.behavioralMetrics.behavioralDistractionScore}\")\nandroid.util.Log.d(\"Behavior\", \"Interaction Intensity: ${summary.behavioralMetrics.interactionIntensity}\")\nandroid.util.Log.d(\"Behavior\", \"Deep Focus Blocks: ${summary.behavioralMetrics.deepFocusBlocks.size}\")\n\n// Activity summary\nandroid.util.Log.d(\"Behavior\", \"Total Events: ${summary.activitySummary.totalEvents}\")\nandroid.util.Log.d(\"Behavior\", \"App Switches: ${summary.activitySummary.appSwitchCount}\")\n\n// Notification summary\nandroid.util.Log.d(\"Behavior\", \"Notifications: ${summary.notificationSummary.notificationCount}\")\nandroid.util.Log.d(\"Behavior\", \"Ignore Rate: ${summary.notificationSummary.notificationIgnoreRate}\")\n\n// Typing session summary (populated downstream from typing-event counts)\nsummary.typingSessionSummary?.let { typing -\u003e\n    android.util.Log.d(\"Behavior\", \"Typing Sessions: ${typing.typingSessionCount}\")\n    android.util.Log.d(\"Behavior\", \"Average Speed: ${typing.averageTypingSpeed} taps/sec\")\n    android.util.Log.d(\"Behavior\", \"Deep Typing Blocks: ${typing.deepTypingBlocks}\")\n    android.util.Log.d(\"Behavior\", \"Clipboard Activity Rate: ${typing.clipboardActivityRate}\")\n    android.util.Log.d(\"Behavior\", \"Correction Rate: ${typing.correctionRate}\")\n}\n\n// Motion state (if motion tracking enabled)\nsummary.motionState?.let { motion -\u003e\n    android.util.Log.d(\"Behavior\", \"Motion State: ${motion.majorState}\")\n    android.util.Log.d(\"Behavior\", \"Confidence: ${motion.confidence}\")\n}\n```\n\n### Motion State Inference\n\nWhen `enableMotionLite` is enabled, the SDK uses machine learning to predict user activity states from motion sensor data. The model classifies activity into four states: **LAYING**, **MOVING**, **SITTING**, and **STANDING**.\n\nMotion state inference is automatically performed when ending a session (if motion data is available).\n\n```kotlin\n// Motion state is included in session summaries\nval summary = behavior.endSession(session.sessionId)\nsummary.motionState?.let { motion -\u003e\n    android.util.Log.d(\"Behavior\", \"Predicted State: ${motion.majorState}\")\n    android.util.Log.d(\"Behavior\", \"State Distribution: ${motion.state}\")\n    android.util.Log.d(\"Behavior\", \"Major State Percentage: ${motion.majorStatePct * 100}%\")\n    android.util.Log.d(\"Behavior\", \"Confidence: ${motion.confidence}\")\n    android.util.Log.d(\"Behavior\", \"ML Model: ${motion.mlModel}\")\n}\n```\n\n**Note**: Motion state inference requires:\n\n- `enableMotionLite = true` in configuration\n- Motion data collected during the session\n- ONNX Runtime library (automatically included as a dependency)\n\n### Current Statistics\n\nGet real-time statistics without ending a session:\n\n```kotlin\nval stats = behavior.getCurrentStats()\nandroid.util.Log.d(\"Behavior\", \"Scroll velocity: ${stats.scrollVelocity}\")\nandroid.util.Log.d(\"Behavior\", \"Tap rate: ${stats.tapRate}\")\nandroid.util.Log.d(\"Behavior\", \"App switches per minute: ${stats.appSwitchesPerMinute}\")\n```\n\n### Session Status\n\n```kotlin\n// Check if SDK is initialized\nif (behavior.isInitialized) {\n    // Check current active session\n    val currentSessionId = behavior.currentSessionId\n    if (currentSessionId != null) {\n        android.util.Log.d(\"Behavior\", \"Active session: $currentSessionId\")\n    }\n}\n```\n\n## View Attachment\n\nTo track gestures on specific views, attach the SDK to them:\n\n```kotlin\n// Attach to a single view\nbehavior.attachToView(myScrollView)\n\n// Attach to a RecyclerView\nbehavior.attachToView(myRecyclerView)\n\n// Attach to an Activity's root view\nbehavior.attachToView(findViewById(android.R.id.content))\n```\n\n**Note**: The SDK automatically tracks gestures on attached views. Text field interactions are captured as tap events. Typing events are created separately when typing sessions are detected.\n\n### Manual Event Sending\n\nYou can manually send events to the SDK. Only predefined event types are supported (scroll, tap, swipe, notification, call, typing):\n\n```kotlin\nval event = BehaviorEvent.typing(\n    sessionId = behavior.currentSessionId ?: \"current\",\n    typingTapCount = 50,\n    typingSpeed = 5.2,\n    meanInterTapIntervalMs = 192.3,\n    typingCadenceVariability = 0.15,\n    typingCadenceStability = 0.85,\n    typingGapCount = 3,\n    typingGapRatio = 0.1,\n    typingBurstiness = 0.3,\n    typingActivityRatio = 0.9,\n    typingInteractionIntensity = 0.8,\n    durationSeconds = 10,\n    startAt = \"2023-01-01T10:00:00Z\",\n    endAt = \"2023-01-01T10:00:10Z\",\n    deepTyping = true\n)\n\nbehavior.sendEvent(event)\n```\n\n## Privacy \u0026 Compliance\n\n- ✅ **No PII collected**: Only timing-based signals, no personal information\n- ✅ **No text content**: Typing events only contain timing metrics (speed, cadence, etc.), not actual text\n- ✅ **No screen capture**: No screenshots or screen recording\n- ✅ **Motion data privacy**: Motion state inference runs locally using ONNX Runtime; no data sent to external servers\n- ✅ **No app content**: No access to app UI content or data\n- ✅ **Fully local processing**: All processing happens on-device\n- ✅ **No persistent storage**: Data stored only in memory\n- ✅ **No network transmission**: Zero network activity\n- ✅ **GDPR/CCPA-ready**: Compliant with privacy regulations\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────┐\n│                  Your Android App                     │\n│                                                       │\n│  ┌─────────────────────────────────────────────────┐  │\n│  │           SynheartBehavior SDK                   │  │\n│  │                                                  │  │\n│  │  BehaviorConfig ──► SynheartBehavior.create()    │  │\n│  │                           │                      │  │\n│  │       ┌───────────────────┼───────────────┐      │  │\n│  │       ▼                   ▼               ▼      │  │\n│  │  GestureCollector  AttentionSignal  MotionSignal  │  │\n│  │  (scroll, tap,     Collector        Collector     │  │\n│  │   swipe)           (app switch,     (accel/gyro,  │  │\n│  │       │             idle, notif)     ONNX ML)     │  │\n│  │       │                   │               │      │  │\n│  │       └─────────┬─────────┘───────────────┘      │  │\n│  │                 ▼                                 │  │\n│  │          SessionTracker                           │  │\n│  │          (events, stats, windowing)               │  │\n│  │                 │                                 │  │\n│  │                 ▼                                 │  │\n│  │     BehaviorSessionSummary                        │  │\n│  │     (metrics, typing summary, motion state)       │  │\n│  └─────────────────┼────────────────────────────────┘  │\n│                    ▼                                   │\n│       Flow\u003cBehaviorEvent\u003e / Callback                  │\n└──────────────────────────────────────────────────────┘\n         │\n         ▼ (passed to synheart-core for HSI ingestion)\n```\n\nSignals flow: **Collectors → SessionTracker → BehaviorSessionSummary**.\nThe SDK never generates HSI directly — it collects and normalizes behavioral signals.\n\n## Testing\n\n```bash\n./gradlew test\n./gradlew lint\n./gradlew assembleRelease\n```\n\n## Documentation\n\nFull reference docs live at **[docs.synheart.ai/synheart-behavior/kotlin](https://docs.synheart.ai/synheart-behavior/kotlin)** — metric definitions, model card, threat model, error reference, and the cross-platform overview.\n\n## Related Projects\n\n| Repository | Description |\n|---|---|\n| [synheart-behavior](https://github.com/synheart-ai/synheart-behavior) | Specification \u0026 docs (Source of Truth) |\n| [synheart-behavior-dart](https://github.com/synheart-ai/synheart-behavior-dart) | Flutter/Dart SDK |\n| [synheart-behavior-swift](https://github.com/synheart-ai/synheart-behavior-swift) | iOS/Swift SDK |\n| [synheart-behavior-chrome](https://github.com/synheart-ai/synheart-behavior-chrome) | Chrome extension |\n\n## Requirements\n\n- **Android SDK**: API 21+ (Android 5.0+)\n- **Kotlin**: 1.9.0+\n- **Gradle**: 8.0+\n\n## Troubleshooting\n\n### SDK Not Initializing\n\n**Problem**: `SynheartBehavior.initialize()` throws an exception.\n\n**Solutions**:\n\n- Ensure you're using `Application` context (use `context.applicationContext`)\n- Check that native platform code is properly integrated\n- Verify Android API level meets requirements (\u003e= 21)\n\n### No Events Being Collected\n\n**Problem**: Event handler is not receiving events.\n\n**Solutions**:\n\n- Ensure you've attached views using `attachToView()`\n- Verify a session is started with `startSession()`\n- Check that `enableInputSignals` or `enableAttentionSignals` is `true` in config\n- For notifications/calls, ensure permissions are granted\n\n### Permission Requests Not Working\n\n**Problem**: Permission requests don't show dialogs or open settings.\n\n**Solutions**:\n\n- **Android**: Notification access requires manual enablement in system settings\n- Check platform-specific permission requirements in your app's manifest\n- Ensure you're testing on a real device (emulator may have limitations)\n\n### Session End Fails\n\n**Problem**: `behavior.endSession()` throws an exception or times out.\n\n**Solutions**:\n\n- Ensure the session was properly started\n- Check that the SDK is still initialized\n- Verify the session ID matches the active session\n\n### Build Errors\n\n```bash\n./gradlew clean\n./gradlew build\n```\n\n## Example App\n\nA complete example app demonstrating all SDK features is available in the [`example/`](example/) directory.\n\nTo run the example:\n\n```bash\ncd example\n./gradlew installDebug\n```\n\nThe example app includes:\n\n- Real-time event visualization\n- Session management UI\n- Permission handling examples\n- Event type handling demonstrations\n\n## API Reference\n\n### SynheartBehavior\n\n```kotlin\nclass SynheartBehavior {\n    companion object {\n        fun create(context: Context, config: BehaviorConfig = BehaviorConfig()): SynheartBehavior\n    }\n\n    // Lifecycle\n    fun initialize()\n    fun dispose()\n    val isInitialized: Boolean\n\n    // Sessions\n    fun startSession(sessionId: String? = null): BehaviorSession\n    fun endSession(sessionId: String): BehaviorSessionSummary\n    val currentSessionId: String?\n\n    // Events \u0026 stats\n    fun setEventHandler(handler: (BehaviorEvent) -\u003e Unit)\n    val onEvent: Flow\u003cBehaviorEvent\u003e\n    fun sendEvent(event: BehaviorEvent)\n    fun getCurrentStats(): BehaviorStats\n\n    // View tracking\n    fun attachToView(view: View)\n\n    // Configuration\n    fun updateConfig(newConfig: BehaviorConfig)\n}\n```\n\n### Key Types\n\n| Type | Description |\n|---|---|\n| `BehaviorConfig` | SDK configuration (signals, batching, consent, motion) |\n| `BehaviorEvent` | Single behavioral event with factory methods (`.scroll()`, `.tap()`, `.swipe()`, `.typing()`, etc.) |\n| `BehaviorEventType` | `SCROLL`, `TAP`, `SWIPE`, `NOTIFICATION`, `CALL`, `TYPING`, `CLIPBOARD`, `APP_SWITCH` |\n| `BehaviorSession` | Active session handle |\n| `BehaviorSessionSummary` | Aggregated session metrics (activity, behavioral, typing, motion, notification) |\n| `BehaviorStats` | Real-time metrics snapshot |\n| `MotionState` | ML-inferred motion state (LAYING, MOVING, SITTING, STANDING) |\n| `TypingSessionSummary` | Typing metrics (cadence, burstiness, clipboard/correction rates) |\n\nFor full API docs, see the [Maven Central package page](https://central.sonatype.com/artifact/ai.synheart/synheart-behavior).\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n## License\n\nApache 2.0 License - see [LICENSE](LICENSE) file for details.\n\n## Author\n\nIsrael Goytom\n\n## Links\n\n- 📦 [Maven Central](https://central.sonatype.com/artifact/ai.synheart/synheart-behavior)\n- 🔗 [GitHub repository](https://github.com/synheart-ai/synheart-behavior-kotlin)\n\n## Patent Pending Notice\n\nThis project is provided under an open-source license. Certain underlying systems, methods, and architectures described or implemented herein may be covered by one or more pending patent applications.\n\nNothing in this repository grants any license, express or implied, to any patents or patent applications, except as provided by the applicable open-source license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynheart-ai%2Fsynheart-behavior-kotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsynheart-ai%2Fsynheart-behavior-kotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynheart-ai%2Fsynheart-behavior-kotlin/lists"}