# Veg Sahayyak SDK Full Documentation This file contains the complete, concatenated documentation for the Veg Sahayyak SDK. --- START OF FILE: api-reference/index.md --- # API Reference & KDoc Complete Kotlin API specifications for public interfaces, builders, and data models in the **Veg Sahayyak SDK**. --- ## ๐Ÿš€ `SpeedAssistant` Singleton Builder `package com.vegsahayyak.speedcore.api` The primary entry point to the telematics engine. ### Builder & Lifecycle Methods #### `companion object.with(context: Context): SpeedAssistant` Retrieves or instantiates the singleton instance of `SpeedAssistant`. Automatically initializes core dependencies. #### `setWarningSpeedThreshold(limitInUserUnit: Float): SpeedAssistant` Sets the maximum speed ceiling. Converts user units to SI meters/second and updates `TelematicsEngine`. #### `setMinWarningSpeedThreshold(limitInUserUnit: Float): SpeedAssistant` Sets the minimum speed corridor limit. #### `setDrivingProfile(profile: DrivingProfile): SpeedAssistant` Applies a pre-configured or dynamic `DrivingProfile` and automatically resolves the ideal max and min speed limits according to the user's active unit. #### `setWarningPendingIntent(intent: PendingIntent): SpeedAssistant` Configures the `PendingIntent` fired when the driver breaks the speed threshold. #### `setColorScheme(colorScheme: SpeedColorScheme): SpeedAssistant` Configures custom brand colors for system notifications and alerts across the SDK. #### `useRepository(repository: ISpeedRepository): SpeedAssistant` Overrides the internal default `SpeedRepositoryImpl` with a custom implementation or test double (e.g. `FakeSpeedRepository`). #### `usePreferenceRepository(repository: IPreferenceRepository): SpeedAssistant` Overrides the internal persistent preferences repository with a custom implementation. #### `val tracker: ISpeedRepository` Direct accessor to the active speed repository instance. #### `val preferences: IPreferenceRepository` Direct accessor to the active persistent preferences repository instance. #### `start()` Starts the `SpeedometerService` foreground service and begins Fused Location Provider polling. #### `startIfEnabled(): Boolean` Checks user preferences and restarts the tracking service only if it was previously active. Returns `true` if started. #### `stop()` Halts the foreground service, removes location updates, and resets the `TelematicsEngine`. #### `companion object.observeFlow(): Flow` Returns a Kotlin Coroutines `Flow` of real-time telematics updates. --- ## ๐ŸŽจ `SpeedColorScheme` & `SpeedUiColorScheme` Color Models `package com.vegsahayyak.speedcore.api` / `package com.vegsahayyak.speedui.components` Data classes for branding SDK alerts and UI components. ```kotlin data class SpeedColorScheme( @ColorInt val safeColor: Int = 0xFF00E676.toInt(), @ColorInt val warningApproachColor: Int = 0xFFFF9100.toInt(), @ColorInt val overSpeedColor: Int = 0xFFFF1744.toInt(), @ColorInt val underSpeedColor: Int = 0xFF00E5FF.toInt(), @ColorInt val warningGlowColor: Int = 0x88FF1744.toInt(), @ColorInt val needleColor: Int = 0xFF2979FF.toInt() ) data class SpeedUiColorScheme( val safeColor: Color = Color(0xFF00E676), val warningApproachColor: Color = Color(0xFFFF9100), val overSpeedColor: Color = Color(0xFFFF1744), val underSpeedColor: Color = Color(0xFF00E5FF), val warningGlowColor: Color = Color(0x88FF1744), val needleColor: Color = Color(0xFF2979FF) ) ``` --- ## ๐Ÿ“ก `SpeedData` (Sealed Hierarchy) Data Sealed Interface `package com.vegsahayyak.speedcore.data.location` ```kotlin sealed interface SpeedData { data class SpeedChanged( val speedMps: Float, val isOverLimit: Boolean, val isUnderLimit: Boolean = false, val accuracyMeters: Float ) : SpeedData data class LowAccuracy( val reason: String ) : SpeedData object GPSDisabled : SpeedData object SpeedUnavailable : SpeedData object Disabled : SpeedData } ``` --- ## ๐Ÿ“ `SpeedUnit` Enum `package com.vegsahayyak.speedcore.units` | Enum Constant | Label | MPS Conversion Factor | Gauge Max Scale | Major Step | | :--- | :--- | :--- | :--- | :--- | | `KILOMETERS_PER_HOUR` | `km/h` | 3.6 ร— mps | 180 | 20 | | `METERS_PER_SECOND` | `m/s` | 1.0 ร— mps | 50 | 10 | | `MILES_PER_HOUR` | `mph` | 2.23694 ร— mps | 120 | 20 | | `FEET_PER_SECOND` | `ft/s` | 3.28084 ร— mps | 160 | 20 | ### Methods * `convertSpeed(metersPerSecond: Float): Float`: Converts SI meters per second to the target unit. * `convertToMetersPerSecond(speedInUnit: Float): Float`: Converts user-unit speed to SI m/s. --- ## โš™๏ธ `TelematicsEngine` Internal Domain `package com.vegsahayyak.speedcore.domain` Performs mathematical signal smoothing and state machine transitions. ```kotlin data class TelematicsResult( val smoothedSpeedMps: Float, val isOverLimit: Boolean, val isUnderLimit: Boolean, val accuracyMeters: Float ) ``` * `processLocation(rawSpeedMps: Float, accuracyMeters: Float): TelematicsResult?`: Passes data to the C++ Native Vault which applies proprietary accuracy confidence gating, Exponential Moving Average smoothing, and Schmitt Trigger Hysteresis. Returns `null` if precision is insufficient. * `reset()`: Flushes historical momentum states. --- ## ๐Ÿ—„๏ธ `ISpeedRepository` & `IPreferenceRepository` Interface Abstraction `package com.vegsahayyak.speedcore.api` Repository abstractions allowing custom mock implementations for unit testing or integration testing. ```kotlin interface ISpeedRepository { fun observeSpeed(): Flow fun isEnable(): Boolean fun isLocationAvailable(): Boolean fun toggle(boolean: Boolean) fun enable() fun disable() } interface IPreferenceRepository { fun isRunning(): Boolean fun setRunning(value: Boolean) fun getUnit(): SpeedUnit fun setUnit(unit: SpeedUnit) fun isFirstRun(): Boolean fun setFirstRun(value: Boolean) fun getUpdateWhileScreenOff(): Boolean fun setUpdateWhileScreenOff(value: Boolean) fun getWarningSpeedThreshold(): Float fun setWarningSpeedThreshold(value: Float) fun getMinWarningSpeedThreshold(): Float fun setMinWarningSpeedThreshold(value: Float) fun setLocationPermissionRequested(value: Boolean) fun getLocationPermissionRequested(): Boolean } ``` --- ## ๐ŸชŸ `PipWidget` & `PipWidgetConfig` Composable / Model `package com.vegsahayyak.speedoverlay` A floating, compact Picture-in-Picture (PiP) style speedometer designed to render over other apps (such as navigation or delivery apps) using `SYSTEM_ALERT_WINDOW`. ```kotlin @Composable fun PipWidget( speed: Float, unitLabel: String, isOverLimit: Boolean, modifier: Modifier = Modifier, isUnderLimit: Boolean = false, config: PipWidgetConfig = PipWidgetConfig() ) ``` ```kotlin data class PipWidgetConfig( val size: Dp = 100.dp, val safeColor: Color = Color(0xFF1FC95E), val warningColor: Color = Color(0xFFE31D23), val underSpeedColor: Color = Color(0xFF29B6F6), val backgroundColor: Color = Color(0x66000000), // Translucent dark glass val speedTextSize: TextUnit = 36.sp, val unitTextSize: TextUnit = 14.sp, val textColor: Color = Color.White ) ``` --- ## ๐Ÿš— `AutoStartManager` Plugin Utility `package com.vegsahayyak.speedautostart` Manager object providing zero-friction background trip detection using Google Play Services Activity Recognition API. ```kotlin object AutoStartManager { fun enable( context: Context, onPermissionRequired: () -> Unit, onSuccess: () -> Unit, onError: (Exception) -> Unit ) } ``` --- ## ๐Ÿš— `DrivingProfile` Sealed Class `package com.vegsahayyak.speedcore.api` Pre-configured speed limit profiles for various vehicle classes and environments. ```kotlin sealed class DrivingProfile { abstract val maxKmh: Float abstract val minKmh: Float abstract val maxMph: Float abstract val minMph: Float fun getMaxLimit(unit: SpeedUnit): Float fun getMinLimit(unit: SpeedUnit): Float object CarHighway : DrivingProfile() // Max 120 km/h / 75 mph, Min 60 km/h / 40 mph object CarCity : DrivingProfile() // Max 50 km/h / 30 mph, Min 0 object Motorcycle : DrivingProfile() // Max 120 km/h / 75 mph, Min 0 object TruckHighway : DrivingProfile() // Max 90 km/h / 60 mph, Min 50 km/h / 30 mph object BusCoach : DrivingProfile() // Max 100 km/h / 65 mph, Min 50 km/h / 30 mph object TractorAgricultural : DrivingProfile() // Max 40 km/h / 25 mph, Min 0 object EScooter : DrivingProfile() // Max 20 km/h / 12.5 mph, Min 0 object Bicycle : DrivingProfile() // Max 25 km/h / 15 mph, Min 0 object Walking : DrivingProfile() // Max 8 km/h / 5 mph, Min 0 object SchoolZone : DrivingProfile() // Max 30 km/h / 20 mph, Min 0 data class CustomProfile( val maxLimit: Float, val minLimit: Float, val unit: SpeedUnit ) : DrivingProfile() } ``` --- ## ๐ŸŽ๏ธ `SpeedGauge` & UI Models Composable / Models `package com.vegsahayyak.speedui.components` / `package com.vegsahayyak.speedui.models` Stateless hardware-accelerated speedometer gauge rendering with dynamic color schemes, theme presets, and screen reader accessibility. ```kotlin enum class ThemeMode { SYSTEM, // Follows system light/dark theme DARK_GRAY, // Deep charcoal slate OLED_BLACK, // Pure #000000 true black for OLED battery conservation HIGH_CONTRAST, // High-visibility bright yellow/white for direct sunlight HUD_MIRRORED // Vertically inverted reflection mode } enum class UiSpeedUnit(val label: String) { KMH("km/h"), MPH("mph"), MPS("m/s"), FPS("ft/s") } @Composable fun SpeedGauge( speed: Float, warningSpeed: Float, isTrackingActive: Boolean, isOverLimit: Boolean = false, modifier: Modifier = Modifier, minSpeedLimit: Float = 0f, maxSpeed: Float = SpeedGaugeTokens.DefaultMaxSpeed, unitLabel: String = "km/h", unitOptions: List = UiSpeedUnit.entries, labelStep: Int = 20, onUnitSelected: ((Int) -> Unit)? = null, themeMode: ThemeMode = ThemeMode.SYSTEM, colorScheme: SpeedUiColorScheme? = null, showGpsAccuracy: Boolean = true, gpsAccuracyMeters: Float = -1f, isHudMirrored: Boolean = false ) ``` --- ## ๐ŸŒ™ `HudDisplay` & `Modifier.hudMirror` Composable / Modifier `package com.vegsahayyak.speedui.components` Dedicated nighttime windshield projection component and transformation modifiers. ```kotlin enum class HudMirrorAxis { VERTICAL, HORIZONTAL, BOTH } fun Modifier.hudMirror( isMirrored: Boolean = true, axis: HudMirrorAxis = HudMirrorAxis.VERTICAL ): Modifier @Composable fun HudDisplay( speed: Float, warningSpeed: Float, isTrackingActive: Boolean, modifier: Modifier = Modifier, minSpeedLimit: Float = 0f, isOverLimit: Boolean = false, unitLabel: String = "km/h", unitOptions: List = UiSpeedUnit.entries, onUnitSelected: ((Int) -> Unit)? = null, isMirrored: Boolean = true, onToggleMirror: (() -> Unit)? = null, mirrorAxis: HudMirrorAxis = HudMirrorAxis.VERTICAL, colorScheme: SpeedUiColorScheme? = null, showGpsAccuracy: Boolean = true, gpsAccuracyMeters: Float = -1f ) ``` --- ## ๐ŸŽ™๏ธ `VoiceCommandButton` & `VoiceCommandParser` Composable / Parser `package com.vegsahayyak.speedui.components` / `package com.vegsahayyak.speedui.api` Hands-free STT transcription button and speech-intent parser interfaces. ```kotlin sealed class VoiceAction { data class SetProfile(val profile: DrivingProfile) : VoiceAction() data class ChangeUnit(val unitName: String) : VoiceAction() object Unknown : VoiceAction() } interface VoiceCommandParser { suspend fun parse(text: String): VoiceAction? companion object { fun parse(text: String): VoiceAction } } @Composable fun VoiceCommandButton( parser: VoiceCommandParser? = null, onCommandParsed: (VoiceAction) -> Unit, modifier: Modifier = Modifier ) ``` --- END OF FILE: api-reference/index.md --- --- START OF FILE: architecture/index.md --- # Architecture Overview The **Veg Sahayyak SDK** is engineered around a clean, decoupled, and framework-agnostic architecture. This ensures high-accuracy telematics processing in background environments without imposing dependency injection frameworks (like Hilt or Koin) onto host applications. --- ## ๐Ÿ›๏ธ Modular Design The SDK is strictly modularized into 5 components to enforce separation of concerns and enable flexible, lightweight B2B integration: ### Module Responsibilities | Module | Namespace | Role | | :--- | :--- | :--- | | **`speed-core`** | `com.vegsahayyak.speedcore` | **Headless Engine**: Location tracking, `TelematicsEngine` signal processing, Foreground Service, `SpeedColorScheme`, persistent preferences, and repository contracts. **Crucially, this module is entirely headless and contains zero Jetpack Compose or UI dependencies.** | | **`speed-ui`** | `com.vegsahayyak.speedui` | **Jetpack Compose UI**: Production-ready, animated `SpeedGauge` canvas component, `HudDisplay` night windshield projection, and `SpeedUiColorScheme`. All UI rendering is fully delegated here. | | **`speed-overlay`** | `com.vegsahayyak.speedoverlay` | **Floating PiP Overlay**: Lightweight floating Picture-in-Picture window for persistent speed display over third-party navigation apps. | | **`speed-autostart`** | `com.vegsahayyak.speedautostart` | **Zero-Touch Autostart**: Seamless background trip detection via Google Play Activity Recognition (`IN_VEHICLE` transitions). | | **`speed-bom`** | `com.vegsahayyak.speedbom` | **Bill of Materials**: Aligns module versioning (v2.2.0) so clients never encounter runtime ABI mismatches. | --- ## ๐Ÿ›ก๏ธ Native Security & Binary Hardening (`libveg_vault.so`) In **v2.2.0**, critical signal processing algorithms and licensing verification are encapsulated within a compiled **Native C++ Library (`libveg_vault.so`)**. This provides defense-in-depth protection for commercial enterprise integrations: * **Anti-Tamper & Anti-Reversing**: Core telematics logic is protected against Dalvik/ART bytecode decompilation, dynamic hooking, and runtime memory tampering. * **Offline Cryptographic Integrity**: High-assurance license validation runs locally on-device, verifying cryptographic signatures without exposing raw mathematical constants or logic to the Java/Kotlin runtime layer. * **Minimal Binary Footprint**: Fully stripped to less than 300KB per ABI, preserving the SDK's lightweight footprint with zero impact on host application APK size. --- ## ๐Ÿ”‘ Commercial Enterprise Licensing The SDK operates exclusively on an offline-first **Commercial Enterprise License** model, eliminating runtime third-party authentication servers or tracking dependencies: 1. **Self-Contained Claims**: Your commercial license key is a signed JSON Web Token (JWT) that encodes authorized module entitlements (such as `:speed-ui`, `:speed-overlay`, `:speed-autostart`) and expiration bounds. 2. **100% Offline Execution**: All license verification runs locally on-device within the native vault. Fleets and logistics vehicles operate uninterrupted in remote, tunnel, or off-grid environments without periodic server ping requirements. --- ## ๐Ÿ“ Signal Processing & Telematics Engine GPS hardware sensors on mobile devices frequently produce velocity noise spikes, multipath signal reflections, and intermittent signal drift (especially in urban canyons or under bridges). The `TelematicsEngine` in `speed-core` applies a multi-stage mathematical pipeline before emitting speed updates. ### 1. Accuracy Confidence Gating Raw GPS fixes with an estimated horizontal accuracy greater than our **proprietary internal threshold** (or missing speed precision) are discarded: ::: info ๐ŸŽฏ Gating Rule ```text Accept GPS Fix IF: horizontalAccuracy <= CONFIDENCE_THRESHOLD (2ฯƒ confidence) ``` ::: When a reading is rejected, the engine emits `SpeedData.LowAccuracy`, preventing erratic spikes while preserving the last valid smoothed speed. --- ### 2. Exponential Moving Average (EMA) To eliminate abrupt needle shaking while retaining immediate responsiveness to actual vehicle acceleration, the engine applies an **Exponential Moving Average** using proprietary coefficients gated inside `libveg_vault.so`. ::: info ๐Ÿ“ Mathematical Smoothing Formula ```text SmoothedVelocity[t] = ฮฑ ยท RawVelocity[t] + (1 - ฮฑ) ยท SmoothedVelocity[t - 1] ``` * **`S_t`**: Smoothed speed at timestamp *t* (in meters/second). * **`Y_t`**: Raw velocity reading from the GPS provider. * **`S_{t-1}`**: Previous smoothed speed state. * **`ฮฑ`**: Calibrated weighting coefficient (executed securely inside `libveg_vault.so`). ::: --- ### 3. Dual Schmitt Trigger Hysteresis (Max & Min Limits) A major problem with standard telematics alerting is **alarm flutter** (e.g. at `80.1 km/h` the alarm fires, at `79.9 km/h` it shuts off, causing rapid flickering and annoying audio chatter). The SDK's `TelematicsEngine` implements a **Dual Schmitt Trigger Hysteresis** state machine covering both **Maximum Speed Limits** and **Minimum Speed Corridors**. These dynamic limits are no longer set manually; they are now **automatically fed by the selected `DrivingProfile`** (e.g. `CarHighway`, `EScooter`): #### A. Maximum Speed Ceiling Hysteresis * **Trigger Threshold**: Warning activates when speed exceeds the upper bound limit. * **Dismissal Threshold**: Warning deactivates when speed drops below the required hysteresis baseline. * **Result**: Sets `isOverLimit = true` in `SpeedData.SpeedChanged`. #### B. Minimum Speed Corridor Hysteresis * **Startup Safety Guard (`hasReachedSafeSpeed`)**: Prevents false under-speed alarms when the vehicle is stationary or starting from a parking stop until it first accelerates past a safe baseline. * **Trigger Threshold**: Warning activates when driving speed drops below the corridor floor. * **Dismissal Threshold**: Warning deactivates once speed recovers safely into the corridor. * **Result**: Sets `isUnderLimit = true` in `SpeedData.SpeedChanged`. --- ## ๐Ÿ”‹ Foreground Service & Battery Optimization Continuous GPS monitoring can drain mobile battery rapidly. The SDK provides advanced power-conservation strategies: 1. **`AutoStartManager` (`:speed-autostart`)**: This is the new recommended strategy for battery optimization. By utilizing Google Play Services `IN_VEHICLE` transitions, it detects when a trip starts or stops using the low-power sensor hub, bypassing OEM background killers without relying on continuous GPS polling. 2. **`ScreenStateWatcher`**: Dynamically observes display state. If the host application configures `updateWhileScreenOff = false`, the GPS hardware is immediately turned off when the screen sleeps, reducing power consumption by up to **68%**. 3. **Dynamic Status Bar Icons**: Speed is rendered directly into the system status bar as a vector numeric drawable, allowing drivers to monitor speed without keeping the screen active. --- ๐Ÿ‘‰ **Next Step:** Explore the [Core Integration Guide](/guide/) to initialize the SDK and collect live telematics streams. --- END OF FILE: architecture/index.md --- --- START OF FILE: changelog/index.md --- # Changelog & Version Matrix Track releases, breaking architectural migrations, and upcoming feature roadmap for the **Veg Sahayyak SDK**. --- ## ๐Ÿท๏ธ Version Matrix & Release History | Version | Status | Release Date | Target Android SDK | Highlights | | :--- | :--- | :--- | :--- | :--- | | **`v2.2.0`** | ๐ŸŸข **Current Stable** | October 2026 | API 23 - 37 | Native C++ Vault, JWT Commercial Licensing, Sample Monorepo. | | **`v2.1.0`** | ๐ŸŸก **Legacy Stable** | August 2026 | API 23 - 37 | Voice Commands, Driving Profiles, Decoupled UI, PiP, HUD, Auto-start, JaCoCo Quality Gates. | | **`v2.0.2`** | ๐ŸŸก Supported | August 2026 | API 23 - 37 | Exponential Moving Average ([REDACTED]), Schmitt Trigger Hysteresis, Compose UI `SpeedGauge` tokens. | | **`v2.0.0`** | ๐ŸŸก Supported | July 2026 | API 23 - 37 | Architectural Migration to modular SDK (`:speed-core`, `:speed-ui`, `:speed-bom`), GitHub Packages Maven distribution. | | **`v1.2.0`** | ๐Ÿ”ด Deprecated | March 2026 | API 21 - 34 | Legacy monolithic Android application architecture. | --- ## ๐Ÿš€ v2.2.0 (Latest Stable) ### ๐ŸŒŸ New Features & Enhancements * **Native C++ Telematics Vault**: * Core GPS verification, EMA algorithms, and JWT license parsing are now executed inside an obfuscated C++ `.so` vault (`libveg_vault.so`) to prevent Dalvik/ART hooking. * **Flexible Commercial Licensing**: * Completely replaced Firebase authentication with offline-first JWT (JSON Web Token) commercial license keys that encode module access and expiry dates directly in the payload. * **Sample Applications Monorepo**: * Released the `veg-sahayyak-samples` repository featuring 6 B2B integrations (Basic, Fleet, UBI, Background, Custom UI, OEM). --- ## ๐ŸŸก v2.1.0 (Legacy Stable) ### ๐ŸŒŸ New Features & Enhancements * **Voice Commands & Driving Profiles**: * Introduced `VoiceCommandButton` and `VoiceCommandParser` for hands-free mode switching. * Replaced manual limit configuration with legal `DrivingProfile` bounds (e.g. `CarHighway`, `SchoolZone`). * **Client Theme & Color Scheme Injection**: * Added `SpeedColorScheme` (`:speed-core`) and `SpeedUiColorScheme` (`:speed-ui`) allowing host apps to inject custom brand colors. * Propagates brand colors across `SpeedGauge`, `HudDisplay`, `PipWidget`, and foreground `NotificationProvider`. * **HUD Windshield Reflection Mode**: * Added `Modifier.hudMirror()` for vertical/horizontal axis transformations. * Added `HudDisplay` standalone composable with true OLED black (`#000000`) background and high-visibility 120sp typography. * Integrated HUD mirroring into `SpeedGauge` and `ThemeMode.HUD_MIRRORED`. * **Decoupled Architecture Modules**: * `:speed-overlay`: Standalone floating Picture-in-Picture speedometer widget (`PipWidget`). * `:speed-autostart`: Zero-touch background trip detection via Google Play Activity Recognition (`AutoStartManager`). ### ๐Ÿ› Bug Fixes * **False Minimum Speed Alarms**: Implemented 8 km/h Stationary Suppression in `TelematicsEngine`. The under-speed alarm is now aggressively silenced when the vehicle is in heavy traffic or navigating speed bumps. * **API 25 Crash Fix**: Resolved `VectorDrawable` inflation crashes on Android Nougat (API 25). * **AAPT2 String Errors**: Fixed missing localized string resources triggering AAPT2 compilation failures during `:app` assembly. * **CI/CD Quality Gates & Coverage**: * Aggregated multi-module JaCoCo coverage reporting (`jacoco.gradle.kts`). * Verified full ProGuard consumer rules and zero-warning Lint passes. --- ## ๐Ÿš€ v2.0.2 ### ๐ŸŒŸ New Features & Enhancements * **`TelematicsEngine` Signal Pipeline**: * Implemented Exponential Moving Average (EMA) with **[REDACTED]** smoothing to eliminate jitter from raw GPS sensor readings. * Added confidence gating to automatically discard GPS fixes exceeding **[C++ VAULT THRESHOLD]** inaccuracy. * Introduced Dual Schmitt Trigger Hysteresis (**+1.0 km/h** alert, **-3.0 km/h** dismissal) to prevent alarm fluttering. * **Jetpack Compose UI Gallery (`:speed-ui`)**: * Added hardware-accelerated `SpeedGauge` canvas component with smooth 60fps needle animations. * Added high-contrast and OLED dark theme presets. * Integrated real-time GPS accuracy pill badge (`Good`, `Fair`, `Weak`). * **Bill of Materials (`:speed-bom`)**: * Added Gradle platform BOM artifact for aligned SDK dependency resolution. --- ## ๐Ÿ”„ Migration Guide: v1.x โ†’ v2.0.x Version 2.0 represents a major architectural overhaul, splitting the codebase into modular SDK components: ### 1. Update Gradle Dependencies Replace legacy monolithic imports with the modular BOM: ```kotlin // Old (v1.x) implementation("com.vegsahayyak:speed-assistant:1.2.0") // New (v2.x Modular) implementation(platform("com.vegsahayyak:speed-bom:2.0.2")) implementation("com.vegsahayyak:speed-core") implementation("com.vegsahayyak:speed-ui") ``` ### 2. Update Initialization Pattern Replace static singleton access with the manual service locator builder: ```kotlin // Old (v1.x) SpeedAssistantManager.getInstance().start(context) // New (v2.x) SpeedAssistant.with(context, "YOUR_JWT_LICENSE") .setDrivingProfile(DrivingProfile.CarHighway) .start() ``` --- ## ๐Ÿ”ฎ Upcoming: v2.3.0 Roadmap Teaser The upcoming `v2.3.0` release will introduce further enterprise telematics and driver safety capabilities: * **Trip Reports & Export (PDF/CSV)**: Comprehensive driving logs, trip summaries, and compliance reports for parents and fleet managers. * **Emergency SOS on Sudden Deceleration**: Life-saving automated first-responder triggers on severe decelerations. * **Lock Settings While Monitoring**: Vibration-proof dashboard lock preventing accidental setting modifications during active monitoring. * **Intent-Based Telematics**: On-device LLM / Gemini Nano integration for conversational driving profile switching. --- END OF FILE: changelog/index.md --- --- START OF FILE: getting-started/index.md --- # Getting Started Welcome to the **Veg Sahayyak SDK** integration guide. This document guides you through configuring your Android build, authenticating with GitHub Packages, declaring dependencies, and executing your first background telematics tracking session. --- ## ๐Ÿ“‹ Minimum Requirements Before integrating the SDK, ensure your project environment meets the following specifications: | Requirement | Minimum Supported | Recommended Target | | :--- | :--- | :--- | | **Android Minimum SDK (`minSdk`)** | API 23 (Android 6.0) | API 26 (Android 8.0+) | | **Android Target SDK (`targetSdk`)** | API 34 | API 35 / API 37 | | **Kotlin Version** | 1.9.20+ | 2.0.0+ / 2.2.0 | | **JDK Version** | Java 17 | Java 21 | | **Jetpack Compose** | 2024.04.00 (BOM) | Latest Stable Compose BOM | --- ## ๐Ÿ”‘ 1. Authentication with GitHub Packages Veg Sahayyak SDK artifacts are distributed privately via **GitHub Packages Maven Registry**. To resolve dependencies, you must supply a GitHub Personal Access Token (PAT) with `read:packages` scope. ### Step A: Configure Authentication Credentials We strongly recommend storing your credentials securely in your `local.properties` file or environment variables to avoid checking secrets into version control: ```properties [local.properties] # In your project's local.properties (git-ignored) gpr.user=YOUR_GITHUB_USERNAME gpr.key=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ``` ### Step B: Add Repository to Gradle Add the registry to your `settings.gradle.kts` (or root `build.gradle.kts`): ::: code-group ```kotlin [settings.gradle.kts (Kotlin DSL)] import java.util.Properties dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() // Veg Sahayyak SDK Private Registry maven { name = "VegSahayyakSDK" url = uri("https://maven.pkg.github.com/VegSahayyak/veg-sahayyak-sdk") credentials { val localProps = Properties().apply { val file = rootProject.file("local.properties") if (file.exists()) file.inputStream().use { load(it) } } username = System.getenv("GITHUB_ACTOR") ?: localProps.getProperty("gpr.user") ?: (project.findProperty("gpr.user") as String?) password = System.getenv("GITHUB_TOKEN") ?: localProps.getProperty("gpr.key") ?: (project.findProperty("gpr.key") as String?) } } } } ``` ```groovy [settings.gradle (Groovy DSL)] dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { name = "VegSahayyakSDK" url = uri("https://maven.pkg.github.com/VegSahayyak/veg-sahayyak-sdk") credentials { username = System.getenv("GITHUB_ACTOR") ?: project.findProperty("gpr.user") password = System.getenv("GITHUB_TOKEN") ?: project.findProperty("gpr.key") } } } } ``` ::: --- ## ๐Ÿ“ฆ 2. Dependency Declaration The SDK is divided into modular artifacts. Using the **Bill of Materials (BOM)** is the recommended approach to guarantee version alignment. ::: code-group ```kotlin [app/build.gradle.kts (Recommended with BOM)] dependencies { // 1. Import the Veg Sahayyak BOM implementation(platform("com.vegsahayyak:speed-bom:2.2.0")) // 2. Core headless tracking, FusedLocation & TelematicsEngine implementation("com.vegsahayyak:speed-core") // 3. Optional Compose UI components (SpeedGauge, HudDisplay, Themes) implementation("com.vegsahayyak:speed-ui") // 4. Optional PiP floating speedometer overlay widget implementation("com.vegsahayyak:speed-overlay") // 5. Optional automatic zero-touch trip start via Activity Recognition implementation("com.vegsahayyak:speed-autostart") } ``` ```kotlin [app/build.gradle.kts (Pure Headless / XML View-Only)] dependencies { // For non-Compose projects: import only the core telematics engine implementation(platform("com.vegsahayyak:speed-bom:2.2.0")) implementation("com.vegsahayyak:speed-core") // Zero Compose dependencies added to your project! } ``` ::: > [!TIP] > **XML Layouts & ViewBinding Support**: If your application is built with traditional XML layouts rather than Jetpack Compose, you have two options: > 1. **Headless XML Binding:** Import only `:speed-core` and bind `SpeedAssistant.observeFlow()` to standard `TextView` and `ProgressBar` widgets. > 2. **ComposeView Interop:** Import `:speed-ui` and embed `` directly inside your XML layout file. See the [XML Integration Guide](/guide/#traditional-xml-viewbinding-integration). --- ## ๐Ÿ›ก๏ธ 3. Android Manifest Permissions The SDK requires standard Android Location and Foreground Service permissions. Add the following to your `app/src/main/AndroidManifest.xml`: ```xml [AndroidManifest.xml] ``` > [!NOTE] > The SDK's `speed-core` module includes the `SpeedometerService` pre-configured in its internal Android Manifest with `android:foregroundServiceType="location"`. You do not need to redeclare the service in your app manifest. --- ## ๐Ÿ”’ 4. ProGuard & R8 Optimization Rules If your application enables code obfuscation (`minifyEnabled = true`), the SDK includes consumer Proguard rules automatically. If needed, you can explicitly verify these rules: ```properties [proguard-rules.pro] # Veg Sahayyak SDK Model & Data Retention -keep class com.vegsahayyak.speedcore.data.location.SpeedData** { *; } -keep class com.vegsahayyak.speedcore.domain.TelematicsResult { *; } -keep class com.vegsahayyak.speedcore.units.SpeedUnit { *; } -keep class com.vegsahayyak.speedcore.api.DrivingProfile** { *; } -keep class com.vegsahayyak.speedui.api.VoiceAction** { *; } -keep interface com.vegsahayyak.speedcore.api.** { *; } ``` --- ## ๐Ÿ”‘ 5. Commercial JWT Licensing The Veg Sahayyak SDK requires an offline-first **JSON Web Token (JWT)** to initialize. This token encodes your organization's permitted module access and expiry dates securely using the Native C++ `libveg_vault.so` library. You will receive this JWT from your Veg Sahayyak account manager. --- ## โšก 6. Verify Installation In your `MainActivity.kt`, verify that the SDK compiles and initializes with your JWT: ```kotlin import com.vegsahayyak.speedcore.api.SpeedAssistant import com.vegsahayyak.speedcore.api.DrivingProfile class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val enterpriseJwt = "eyJhbGciOi..." // Your actual JWT here // Initialize the SDK with your License and apply a driving profile val assistant = SpeedAssistant.with(this, enterpriseJwt) assistant.setDrivingProfile(DrivingProfile.CarHighway) android.util.Log.d("SpeedAssistant", "SDK initialized with Highway Profile!") } } ``` ๐Ÿ‘‰ **Next Up:** Learn about the [SDK Architecture Overview](/architecture/) and how the signal processing algorithms work under the hood. --- END OF FILE: getting-started/index.md --- --- START OF FILE: guide/auto-start.md --- # ๐Ÿš— In-Vehicle Auto-Start (Activity Recognition) The `:speed-autostart` module provides zero-touch background trip detection using **Google Play Services Activity Recognition API**. It eliminates user friction by automatically starting speed tracking when the driver enters a vehicle and halting it upon exit to preserve battery. --- ## ๐ŸŽฏ Why Activity Recognition Over Background GPS? Continuous background GPS polling drains the device battery rapidly and triggers severe Google Play Store rejection risks under background location policies. By using **Activity Recognition (`DetectedActivity.IN_VEHICLE`)**: * **Hardware Co-Processor Power:** Runs on low-power sensor hubs without waking the main CPU. * **Zero Location Polling When Idle:** The GPS radio remains powered off until the vehicle begins moving. * **Automatic Teardown:** When the driver parks and walks away (`ACTIVITY_TRANSITION_EXIT`), the SDK shuts down the foreground service automatically. ```mermaid graph LR A["Phone Sensors / Accelerometer"] --> B["Google Play Activity Recognition"] B -->|IN_VEHICLE ENTER| C["AutoStartReceiver"] C -->|start| D["Speedometer Foreground Service"] B -->|IN_VEHICLE EXIT| C C -->|stop| E["Halt Service & Save Battery"] ``` --- ## ๐Ÿ“ฆ Gradle Dependency Add `:speed-autostart` to your `build.gradle.kts`: ```kotlin dependencies { implementation(platform("com.vegsahayyak:speed-bom:2.2.0")) implementation("com.vegsahayyak:speed-core") implementation("com.vegsahayyak:speed-autostart") } ``` --- ## ๐Ÿ’ป Registering Auto-Start (`AutoStartManager`) Enable auto-start with runtime permission handling: ```kotlin import com.vegsahayyak.speedautostart.AutoStartManager AutoStartManager.enable( context = context, onPermissionRequired = { // Android 10+ (API 29+) requires Manifest.permission.ACTIVITY_RECOGNITION ActivityCompat.requestPermissions( activity, arrayOf(android.Manifest.permission.ACTIVITY_RECOGNITION), REQUEST_CODE_ACTIVITY_RECOGNITION ) }, onSuccess = { // Successfully registered with Google Play Services! // SpeedAssistant will now auto-start when vehicle motion is detected. }, onError = { exception -> Log.e("Telematics", "Activity Recognition registration failed", exception) } ) ``` --- ## ๐Ÿ“ก How the Receiver Operates (`AutoStartReceiver`) The SDK bundles `AutoStartReceiver` in its internal manifest. When Google Play Services fires an activity transition event: ```kotlin // Automatically handled by :speed-autostart when (event.activityType) { DetectedActivity.IN_VEHICLE -> { when (event.transitionType) { ActivityTransition.ACTIVITY_TRANSITION_ENTER -> { SpeedAssistant.with(context, "YOUR_JWT_LICENSE").start() } ActivityTransition.ACTIVITY_TRANSITION_EXIT -> { SpeedAssistant.with(context, "YOUR_JWT_LICENSE").stop() } } } } ``` --- ## ๐Ÿ›ก๏ธ Android Manifest Requirements Ensure the activity recognition permission is declared in your `AndroidManifest.xml`: ```xml ``` > [!TIP] > **Passenger Mode:** If a user is riding as a passenger (e.g. on a bus or train), your app can provide a "Passenger Mode" pause toggle that calls `SpeedAssistant.with(context, "YOUR_JWT_LICENSE").stop()`, overriding auto-start until the next journey. --- END OF FILE: guide/auto-start.md --- --- START OF FILE: guide/cicd-and-quality.md --- # Quality & Testing Resources Looking for testing guidelines or CI/CD documentation? This topic is split into dedicated sections depending on your role: --- ## ๐Ÿ“ฑ For Client App Developers Integrating the SDK If you are integrating the SDK into your Android application and want to write unit tests, UI tests, or mock telematics streams: ๐Ÿ‘‰ **[Go to the Client Testing & QA Guide](/guide/testing)** * Unit testing ViewModels with `ISpeedRepository` & MockK * Simulating synthetic speeds with `FakeSpeedRepository` * Jetpack Compose & Espresso UI test recipes * Enterprise reliability & stability SLA guarantees --- ## ๐Ÿ› ๏ธ For SDK Maintainers & Contributors If you are contributing to the SDK codebase, running linters, or publishing releases: ๐Ÿ‘‰ **[Go to CI/CD & Release Pipeline](/standards/05_CICD_AND_RELEASE_PIPELINE)** * GitHub Actions quality gate workflows * Running `ktlint`, `detekt`, and Android Lint * Internal test execution & JaCoCo coverage metrics * Automated Maven AAR publishing to GitHub Packages --- END OF FILE: guide/cicd-and-quality.md --- --- START OF FILE: guide/driving-profiles.md --- # ๐Ÿš— Driving Profiles & Speed Corridors The **Veg Sahayyak SDK** includes a legally compliant, globally localized **Driving Profiles** system (`DrivingProfile.kt`) designed to configure speed warning corridors in a single function call. --- ## ๐ŸŽฏ Why Driving Profiles? Traditional speed limit apps perform naive floating-point conversions (e.g. converting `120 km/h` gives `74.5645 mph`), leading to awkward numbers on driver dashboards. `DrivingProfile` provides **explicitly rounded, legally localized speed limits** for each vehicle type and speed unit (`120 km/h` for Europe vs `75 mph` for US interstate highways). ```mermaid graph LR A["Vehicle Type Selected"] --> B{"Active SpeedUnit"} B -->|km/h| C["Clean Metric Ceiling: 120 km/h"] B -->|mph| D["Clean Imperial Ceiling: 75 mph"] C --> E["TelematicsEngine Corridor"] D --> E ``` --- ## ๐Ÿ“ฆ Applying a Driving Profile Apply any predefined profile to `SpeedAssistant`: ```kotlin import com.vegsahayyak.speedcore.api.SpeedAssistant import com.vegsahayyak.speedcore.api.DrivingProfile // Apply standard Highway Profile with 1 line of code SpeedAssistant.with(context, "YOUR_JWT_LICENSE") .setDrivingProfile(DrivingProfile.CarHighway) .start() ``` --- ## ๐ŸŽ๏ธ Built-In Vehicle Profiles Matrix | Vehicle Category | Profile Object | Max Limit (`km/h`) | Min Limit (`km/h`) | Max Limit (`mph`) | Min Limit (`mph`) | Target Domain | | :--- | :--- | :--- | :--- | :--- | :--- | :--- | | **Passenger Cars** | `DrivingProfile.CarHighway` | **120** | **60** | **75** | **40** | Interstates, Motorways, Expressways | | **Passenger Cars** | `DrivingProfile.CarCity` | **50** | **0** | **30** | **0** | Urban and suburban commuting | | **Motorcycles** | `DrivingProfile.Motorcycle` | **120** | **0** | **75** | **0** | Unrestricted motorcycle riding | | **Logistics / Freight** | `DrivingProfile.TruckHighway` | **90** | **50** | **60** | **30** | EU/US governed Heavy Goods Vehicles (HGV) | | **Public Transit** | `DrivingProfile.BusCoach` | **100** | **50** | **65** | **30** | Intercity passenger buses | | **Agriculture / Heavy** | `DrivingProfile.TractorAgricultural` | **40** | **0** | **25** | **0** | Farm and construction machinery | | **Micro-Mobility** | `DrivingProfile.EScooter` | **20** | **0** | **12.5** | **0** | Shared e-scooters & micromobility | | **Micro-Mobility** | `DrivingProfile.Bicycle` | **25** | **0** | **15** | **0** | Pedelecs, e-bikes, and city bicycles | | **Pedestrian** | `DrivingProfile.Walking` | **8** | **0** | **5** | **0** | Jogging, fitness, walking pace | | **Special Zones** | `DrivingProfile.SchoolZone` | **30** | **0** | **20** | **0** | School zones and residential quiet zones | --- ## ๐Ÿ› ๏ธ Dynamic Cloud Limits (`CustomProfile`) If your fleet application integrates with the **Google Roads API**, **HERE Maps**, or **OpenStreetMap** to ingest real-time geofenced legal speed limits, use `DrivingProfile.CustomProfile`: ```kotlin import com.vegsahayyak.speedcore.api.DrivingProfile import com.vegsahayyak.speedcore.units.SpeedUnit // Dynamically received 65 mph limit from cloud GPS corridor val dynamicLimitFromMap = 65f val minimumCorridorLimit = 40f val roadProfile = DrivingProfile.CustomProfile( maxLimit = dynamicLimitFromMap, minLimit = minimumCorridorLimit, unit = SpeedUnit.MILES_PER_HOUR ) // Ingest into SpeedAssistant SpeedAssistant.with(context, "YOUR_JWT_LICENSE").setDrivingProfile(roadProfile) ``` The SDK automatically converts custom bounds to SI units (m/s) internally while maintaining display accuracy for any user-selected gauge unit. --- ## ๐Ÿงช Unit Testing Driving Profiles `DrivingProfile` is designed to be easily testable without requiring Android context or mock hardware: ```kotlin @Test fun verifyHighwayLimitsMetricAndImperial() { val highway = DrivingProfile.CarHighway // Metric validation assertEquals(120f, highway.getMaxLimit(SpeedUnit.KILOMETERS_PER_HOUR)) assertEquals(60f, highway.getMinLimit(SpeedUnit.KILOMETERS_PER_HOUR)) // Imperial validation assertEquals(75f, highway.getMaxLimit(SpeedUnit.MILES_PER_HOUR)) assertEquals(40f, highway.getMinLimit(SpeedUnit.MILES_PER_HOUR)) } ``` --- END OF FILE: guide/driving-profiles.md --- --- START OF FILE: guide/floating-overlay.md --- # ๐ŸชŸ Floating Overlay (Picture-in-Picture) Widget The `:speed-overlay` module provides a lightweight, circular **Floating Speedometer Widget (`PipWidget`)** designed to hover above third-party navigation apps (such as Google Maps, Waze, or delivery driver apps) using Android's `SYSTEM_ALERT_WINDOW`. --- ## ๐ŸŽฏ Key Capabilities * **Floating Screen Overlay:** Stays pinned on top of any navigation or dispatch app. * **Dynamic Ring Warnings:** Animates border colors between **Safe (Green)**, **Over-Speed (Red)**, and **Under-Speed (Cyan)**. * **Translucent Glassmorphism:** Semi-transparent dark background (`0x66000000`) prevents obscuring navigation map turns. * **Decoupled Architecture:** Pure Jetpack Compose widget with zero Activity lifecycle dependencies. ```mermaid graph TD A["Speedometer Foreground Service"] -->|Real-Time Velocity| B["PipWidget Compose View"] B -->|Overlay Window| C["Navigation Apps (Google Maps / Waze)"] B -->|Exceeds Limit| D["Animated Red Alert Ring"] ``` --- ## ๐Ÿ“ฆ Gradle Dependency Add `:speed-overlay` to your `build.gradle.kts`: ```kotlin dependencies { implementation(platform("com.vegsahayyak:speed-bom:2.2.0")) implementation("com.vegsahayyak:speed-core") implementation("com.vegsahayyak:speed-overlay") } ``` --- ## ๐Ÿ’ป Basic Usage (`PipWidget`) ```kotlin import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import com.vegsahayyak.speedoverlay.PipWidget import com.vegsahayyak.speedoverlay.PipWidgetConfig @Composable fun FloatingSpeedometer( currentSpeed: Float, isOverLimit: Boolean, isUnderLimit: Boolean = false ) { PipWidget( speed = currentSpeed, unitLabel = "km/h", isOverLimit = isOverLimit, isUnderLimit = isUnderLimit ) } ``` --- ## ๐ŸŽจ Customizing Brand Colors (`PipWidgetConfig`) You can fully customize size, typography, and alert colors via `PipWidgetConfig`: ```kotlin import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.vegsahayyak.speedoverlay.PipWidgetConfig val customFleetOverlayConfig = PipWidgetConfig( size = 110.dp, safeColor = Color(0xFF00E676), // Neon Green warningColor = Color(0xFFFF1744), // Bright Crimson Red underSpeedColor = Color(0xFF00E5FF), // Electric Cyan backgroundColor = Color(0x99000000), // Dark Glass speedTextSize = 40.sp, unitTextSize = 13.sp, textColor = Color.White ) PipWidget( speed = currentSpeed, unitLabel = "mph", isOverLimit = isOverLimit, config = customFleetOverlayConfig ) ``` --- ## ๐Ÿ› ๏ธ Displaying via Android `WindowManager` To render `PipWidget` as a system overlay above other applications: ### 1. Declare Permission in `AndroidManifest.xml` ```xml ``` ### 2. Request Permission at Runtime ```kotlin if (!Settings.canDrawOverlays(context)) { val intent = Intent( Settings.ACTION_MANAGE_OVERLAY_PERMISSION, Uri.parse("package:${context.packageName}") ) context.startActivity(intent) } ``` ### 3. Attach Compose View to WindowManager ```kotlin val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager val layoutParams = WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY else WindowManager.LayoutParams.TYPE_PHONE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE or WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, PixelFormat.TRANSLUCENT ).apply { gravity = Gravity.TOP or Gravity.START x = 100 y = 200 } val composeView = ComposeView(context).apply { setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnDetachedFromWindow) setContent { PipWidget( speed = currentSpeedKmh, unitLabel = "km/h", isOverLimit = currentSpeedKmh > 80f ) } } windowManager.addView(composeView, layoutParams) ``` --- END OF FILE: guide/floating-overlay.md --- --- START OF FILE: guide/index.md --- # Core Integration Guide This guide details the complete developer workflow for initializing the **Veg Sahayyak SDK**, configuring speed thresholds, starting foreground tracking, and consuming the real-time telematics `StateFlow`. --- ## โšก 1. SDK Initialization Initialize the SDK by calling `SpeedAssistant.with(context, "YOUR_JWT_LICENSE")`. The SDK employs a lightweight manual service locator pattern internally, so you can call `with(context)` from any Android `Activity`, `Fragment`, or `Application` class without setting up Hilt or Dagger. ```kotlin import com.vegsahayyak.speedcore.api.SpeedAssistant import com.vegsahayyak.speedcore.units.SpeedUnit class App : Application() { override fun onCreate() { super.onCreate() // Initialize the SDK with a predefined or custom driving profile SpeedAssistant.with(this, "YOUR_JWT_LICENSE") .setDrivingProfile(DrivingProfile.CarHighway) } } ``` > [!TIP] > **Dynamic Limits:** The `DrivingProfile` automatically handles maximum and minimum speed limits based on vehicle type and road legalities. You can also build a `DrivingProfile.CustomProfile` if you need manual limits. --- ## ๐Ÿš— 2. Starting & Stopping Tracking ### Starting the Background Service Calling `.start()` initiates the `SpeedometerService` foreground service and registers the Fused Location Provider client: ```kotlin val assistant = SpeedAssistant.with(context, "YOUR_JWT_LICENSE") // Set the driving profile and launch background tracking assistant .setDrivingProfile(DrivingProfile.CarHighway) .start() ``` ### Auto-Resuming on Boot / App Restart To restart tracking only if the driver previously had tracking enabled: ```kotlin class App : Application() { override fun onCreate() { super.onCreate() // Auto-starts service only if preference state is enabled val wasRunning = SpeedAssistant.with(this, "YOUR_JWT_LICENSE").startIfEnabled() } } ``` ### Stopping Tracking To stop background tracking and release GPS hardware immediately: ```kotlin SpeedAssistant.with(context, "YOUR_JWT_LICENSE").stop() ``` --- ## ๐Ÿ“ก 3. Observing Real-Time Telematics The SDK exposes a Kotlin Coroutines `StateFlow`. You can collect this stream in Jetpack Compose or traditional ViewModels. ### Sealed Interface: `SpeedData` The state stream emits instances of the `SpeedData` sealed interface: | Subtype | Description | Key Fields | | :--- | :--- | :--- | | `SpeedChanged` | Active valid speed reading | `speedMps: Float`, `isOverLimit: Boolean`, `isUnderLimit: Boolean`, `accuracyMeters: Float` | | `LowAccuracy` | GPS fix rejected by precision filter | `reason: String` | | `GPSDisabled` | Device location provider is turned off | N/A | | `SpeedUnavailable` | Tracking active, waiting for satellite fix | N/A | | `Disabled` | Tracking is stopped | N/A | ### Jetpack Compose Example ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import com.vegsahayyak.speedcore.api.SpeedAssistant import com.vegsahayyak.speedcore.data.location.SpeedData import com.vegsahayyak.speedui.components.SpeedGauge @Composable fun DriverDashboardScreen() { // Collect SDK flow as Compose state val speedState by SpeedAssistant.observeFlow().collectAsState(initial = SpeedData.SpeedUnavailable) when (val state = speedState) { is SpeedData.SpeedChanged -> { SpeedGauge( speed = state.speedMps * 3.6f, // Convert m/s to km/h warningSpeed = 80f, // Maximum speed limit minSpeedLimit = 40f, // Minimum highway corridor isTrackingActive = true, isOverLimit = state.isOverLimit, gpsAccuracyMeters = state.accuracyMeters ) // Contextual alert banners based on dual corridor bounds if (state.isOverLimit) { Text("โš ๏ธ Slow Down: Maximum speed limit exceeded (80 km/h)!") } else if (state.isUnderLimit) { Text("๐Ÿข Speed Up: Maintain minimum expressway corridor speed (40 km/h)!") } } is SpeedData.LowAccuracy -> { Text("GPS Signal Weak (ยฑ${state.reason}) - Searching satellites...") } is SpeedData.GPSDisabled -> { Text("Please enable device GPS in settings.") } is SpeedData.SpeedUnavailable, is SpeedData.Disabled -> { SpeedGauge( speed = 0f, warningSpeed = 80f, minSpeedLimit = 40f, isTrackingActive = false ) } } } ``` ### ViewModel Example (Coroutines) ```kotlin import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.stateIn class TelematicsViewModel : ViewModel() { val speedState = SpeedAssistant.observeFlow() .stateIn( scope = viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = SpeedData.SpeedUnavailable ) } ``` ### Traditional XML & ViewBinding Integration If your application uses traditional Android XML layouts and ViewBinding (instead of full Jetpack Compose), the SDK supports both approaches: #### Approach A: Embedding `SpeedGauge` in XML with `ComposeView` You can embed the modern `SpeedGauge` component directly into any XML layout file using `ComposeView`: ::: code-group ```xml [res/layout/activity_driver_dashboard.xml]