Grain Kotlin SDK
Kotlin Multiplatform analytics client for Grain.
Works on Android, iOS, and JVM.
Installation
Gradle (Kotlin DSL)
dependencies {
implementation("com.grainql:grain-sdk:0.0.1")
}
Version Catalog
[libraries]
grain-sdk = { module = "com.grainql:grain-sdk", version = "0.0.1" }
Quick Start
Android
com.grainql.sdk.GrainAnalytics
com.grainql.sdk.GrainConfig
com.grainql.sdk.platform.AndroidKeyValueStore
com.grainql.sdk.platform.AndroidFileStore
GrainAnalytics.initialize(
config = GrainConfig(tenantAlias = ),
kvStore = AndroidKeyValueStore(applicationContext),
fileStore = AndroidFileStore(applicationContext),
)
GrainAnalytics.track(, mapOf(
to ,
to ,
))
GrainAnalytics.identify()
GrainAnalytics.track(, mapOf(
to ,
to ,
to ,
))
iOS (from Swift via KMP framework)
let kvStore = IosKeyValueStore()
let fileStore = IosFileStore()
GrainAnalytics.shared.initialize(
config: GrainConfig(tenantAlias: "your-tenant"),
kvStore: kvStore,
fileStore: fileStore
)
GrainAnalytics.shared.track(eventName: "screen_viewed", properties: ["screen": "settings"])
JVM
import com.grainql.sdk.platform.JvmKeyValueStore
import com.grainql.sdk.platform.JvmFileStore
GrainAnalytics.initialize(
config = GrainConfig(tenantAlias = "your-tenant"),
kvStore = JvmKeyValueStore(),
fileStore = JvmFileStore(),
)
Configuration
GrainConfig(
tenantAlias = "your-tenant",
apiUrl = ,
secret = ,
debug = ,
flushIntervalMs = ,
flushThreshold = ,
maxBatchSize = ,
maxQueueSize = ,
maxRetries = ,
enablePersistence = ,
)
API Reference
Event Tracking
GrainAnalytics.track(eventName, properties)
GrainAnalytics.track(eventName, userId, properties)
Identity
GrainAnalytics.identify(userId)
GrainAnalytics.resetIdentity()
GrainAnalytics.getDeviceId()
GrainAnalytics.getSessionId()
User Properties
GrainAnalytics.setUserProperties(mapOf("plan" to "pro", "source" to "organic"))
GrainAnalytics.setUserProperties(userId, properties)
Lifecycle
GrainAnalytics.onForeground()
GrainAnalytics.onBackground()
GrainAnalytics.onNetworkConnected()
GrainAnalytics.onNetworkDisconnected()
GrainAnalytics.flush()
GrainAnalytics.shutdown()
How It Works
Events flow through a simple pipeline:
track() synchronously submits events into an unbounded channel — it never blocks.
- Before every flush, pending events are drained into an in-memory queue.
- The dispatcher batches events and POSTs them to the Grain API.
- Failed batches are retried with exponential backoff. Events exceeding
maxRetries are dropped.
- When persistence is enabled, events are written to a local JSONL file and removed after successful delivery.
The SDK automatically attaches session_id, device_id, client_version, platform, and timestamp to every event. These match the conventions used by the Grain web SDK so all events participate in the same analytics pipeline.
Building from Source
./gradlew :library:jvmTest
./gradlew :library:compileAndroidMain
./gradlew :library:compileKotlinIosArm64
Contributing
See CONTRIBUTING.md.
License
MIT