# Android SDK

Official Android client SDK - Kotlin, minSdk 21, zero third-party runtime dependencies. The API mirrors the Mixpanel Android SDK, so migrating is mostly a find-and-replace of MixpanelAPI to Cohorly.

## Install

Distributed via JitPack from the public `cohorly-io/cohorly-android`
repository:

```kotlin
// settings.gradle.kts
dependencyResolutionManagement {
    repositories {
        google(); mavenCentral()
        maven("https://jitpack.io")
    }
}

// app/build.gradle.kts
dependencies {
    implementation("com.github.cohorly-io.cohorly-android:cohorly-android:v0.1.0")
}
```

The host app must declare the `INTERNET` permission.

## Initialize

Call `Cohorly.getInstance` once, e.g. in `Application.onCreate()`. One
instance per project token.

```kotlin
import com.cohorly.android.Cohorly

val cohorly = Cohorly.getInstance(context, "YOUR_PROJECT_TOKEN")

cohorly.track("Plan Selected", mapOf("plan" to "pro"))

cohorly.identify("user-123")           // links the anonymous id via /alias
cohorly.people.set("plan", "pro")      // profile update via /engage

cohorly.registerSuperProperties(mapOf("ab_test" to "variant_b"))

cohorly.flush() // also auto-flushes every 5s / 20 events
```

## API

| Member                                                                           | Notes                                                                                                                |
| -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| `Cohorly.getInstance(context, token, apiHost[, config])`                         | Singleton per token. `CohorlyConfig` accepts `flushIntervalMs`, `batchSize`, `maxQueueSize`, `trackAutomaticEvents`. |
| `track(name[, JSONObject \| Map])`                                               | Queue an event (persisted to SharedPreferences).                                                                     |
| `identify(id)` / `reset()`                                                       | Set the distinct id (sends /alias while anonymous) / new anonymous id on logout.                                     |
| `registerSuperProperties[Once] / unregisterSuperProperty / clearSuperProperties` | Super properties merged into every event.                                                                            |
| `people.set / setOnce / increment / unset / deleteUser`                          | Profile updates sent to /engage.                                                                                     |
| `optOutTracking() / optInTracking()`                                             | GDPR opt-out; drops queued events while opted out.                                                                   |
| `flush()`                                                                        | Send now, bypassing any retry backoff window.                                                                        |

## Auto-captured properties

Every event includes `$lib` = `"android"`, `$lib_version`, `$os`,
`$os_version`, `$manufacturer`, `$brand`, `$model`, `$screen_dpi`,
`$screen_height`, `$screen_width`, `$app_version_string`,
`$app_build_number`, `$carrier`, `$has_nfc`, `$has_telephone`,
`$bluetooth_version` and `$google_play_services`. `$wifi` and
`$bluetooth_enabled` are only collected when the app holds the
corresponding permission. Geo properties are derived server-side from the
client IP.

## Automatic events

Opt-in via `trackAutomaticEvents = true` (default off, matching the iOS
and React Native SDKs): `$ae_first_open` (once ever), `$ae_updated` (on
version change) and `$ae_session` with `$ae_session_length` when the app
backgrounds after a session of 10s or more.

The offline queue survives process death (SharedPreferences, capped at
1000 events, oldest dropped) and follows the shared Cohorly retry
contract: exponential backoff on 429/5xx/network errors honoring
`Retry-After`, batch halving on 413, permanent drop on 400.
