# Android (Kotlin)

`io.splithub:splithub` runs experiments and collects analytics in native Android apps. A visitor gets the same variant here as on your website, because assignment is the same hash as the web SDK. Read [Apps](/docs/apps) first for what differs from the web.

The Android SDK is new. Min SDK 21; its only dependency is `androidx.lifecycle:lifecycle-process`, and it brings its own `INTERNET` permission.

## Install

```kotlin
// app/build.gradle.kts
dependencies {
    implementation("io.splithub:splithub:0.5.0")
    // Optional: Jetpack Compose helpers
    implementation("io.splithub:splithub-compose:0.5.0")
}
```

`npx splithub init` in a Gradle project prints these lines and a quick start. Native apps have no `splithub.config.ts`: experiments come from SplitHub Cloud.

## Start

Once, in your `Application`:

```kotlin
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        SplitHub.start(this, "pk_live_...", property = "sh-x1h78w")
    }
}
```

The key is your project's public key. The property is the analytics property for screens and events; leave it out to run experiments only.

## Variants and events

```kotlin
val cta = SplitHub.variant("hero-cta")            // "control", "bold", ...
val price = SplitHub.value("price") as? Map<*, *>  // payload of a value experiment
SplitHub.screen("Settings")                        // a page view of /Settings
SplitHub.track("Video Played", mapOf("id" to 7))   // any event; a goal when marked as one
SplitHub.identify("user-42", mapOf("plan" to "pro"))
SplitHub.reset()                                   // on log out
```

`variant()` and `value()` record an exposure once per variant per session. `valueJson()` gives the payload as JSON text for Gson, Moshi or kotlinx.serialization.

## Compose

```kotlin
@Composable
fun Home() {
    TrackScreen("Home")

    Experiment("hero-cta") { variant ->
        when (variant) {
            "bold" -> Button(onClick = { SplitHub.track("signup") }) { Text("Start free") }
            else -> Button(onClick = { SplitHub.track("signup") }) { Text("Sign up") }
        }
    }

    val price = rememberValue("price")
}
```

`Experiment` records the exposure when the variant is shown and recomposes when variants change.

## Good to know

- **First launch.** The app waits up to 400 ms for the experiments and shows the control meanwhile. Compose helpers update by themselves; in plain views, read variants in `SplitHub.whenReady { }`. Later launches decide at once from the cached copy.
- **Changes** in the dashboard reach the app on its next session, never in the middle of one.
- **Offline.** Events go out every 2 seconds and when the app goes to the background; offline, they wait on the device (up to 1,000).
- **Sessions.** The visitor id stays until `reset()`. A new session starts after 30 minutes in the background.
- **Targeting.** Flows can use `platform` (`android`), `app_version` (at least / below), language, device (`mobile` or `tablet`) and country. See [Targeting flows](/docs/targeting).

## QA

Force a variant on your own device. It's shown but never counted:

```kotlin
SplitHub.start(this, "pk_live_...", options = SplitHubOptions(forcedVariants = mapOf("hero-cta" to "bold"), debug = true))
```

`debug = true` logs every decision under the Logcat tag `SplitHub`.
