Android SDK
Capture events from Android apps — identity, sessions, persistence, feature flags and surveys under the shared SDK spec.
azfive-android brings AZ-Five product analytics to Android: events, identity, sessions, persistence, feature flags & experiments, and surveys, under the shared behavioral spec. minSdk 21.
Install
The package resolves through JitPack:
repositories {
maven("https://jitpack.io")
}
dependencies {
implementation("com.github.az-five:azfive-android:v0.1.0")
}
Honest packaging note: the published coordinate currently carries the core module only — the full analytics client (events, identity, sessions, flags, exposure dedup) as a pure-Kotlin JAR. The Android bindings layer — the AzFive.init(context, …) singleton, SharedPreferencesStore persistence, lifecycle flush-on-background, optional az.screen_view autocapture, and the SurveyBottomSheet renderer — lives in the SDK’s :android module, which isn’t separately installable from JitPack yet. Until it is, build that module from github.com/az-five/azfive-android; the core artifact alone works, but persistence defaults to in-memory (identity won’t survive restarts until you plug a Store into the config).
Initialize
Create a public ingest token with “Mobile app token” enabled (Settings → API Keys → Public Ingest Tokens) — native requests carry no browser Origin, and tokens without that flag fail closed.
With the :android bindings, initialize once in Application.onCreate():
val azfive = AzFive.init(this, "azfive_pub_…", host = "https://app.az-five.com")
AzFive.init wires SharedPreferencesStore, platform properties, and lifecycle flush automatically; AzFive.shared() returns the singleton anywhere. Core-only, construct the client directly:
val azfive = AzFiveClient(
AzFiveConfig(
token = "azfive_pub_…",
host = "https://app.az-five.com",
// store = <your Store implementation> — defaults to InMemoryStore
)
)
Capture events
azfive.capture("signed_up", mapOf("plan" to "pro"))
azfive.screen("Checkout") // az.screen_view + survey eligibility re-check
// Super properties — merged into every event
azfive.register(mapOf("deployment" to "eu-1"))
With the bindings, AzFive.init(…, autocaptureScreens = true) emits az.screen_view automatically from activity lifecycle callbacks.
Identify & person properties
azfive.identify("ava@example.com", mapOf("plan" to "pro"))
azfive.alias("legacy-77")
azfive.peopleSet(mapOf("favorite_color" to "teal"))
azfive.peopleSetOnce(mapOf("signup_date" to "2026-08-01"))
// on logout:
azfive.reset() // new anonymous id; reset(resetDeviceId = true) also rotates the device id
identify merges the anonymous session into the person (az.identify with $anonymous_id) and refetches flags. Opt-out controls — optIn() / optOut() / hasOptedOut() — drop events at capture time, persist, and survive reset().
Feature flags
Flags load from /v1/decide on init, persist for stale-while-revalidate startup, and refresh on identify() / reset():
azfive.onFlags {
val variant = azfive.getFlag("exp-checkout") // "control" | "test" | false | null
if (azfive.isFlagEnabled("new-billing")) {
val payload = azfive.getFlagPayload("new-billing") // no exposure event
}
}
azfive.reloadFlags() // force a refetch
getFlag and isFlagEnabled capture an az.flag_called exposure automatically, deduped per session:flag:value. getFlagPayload never does.
Surveys
Decide-delivered surveys are driven by azfive.surveys (a SurveyCoordinator in core: selection on screen() changes, per-survey suppression, question branching, and the az.survey_shown / az.survey_dismissed / az.survey_sent events). With the :android bindings, render them with the Material bottom sheet:
// in your single-activity host (detach in onDestroy)
val detach = SurveyBottomSheet.attach(this, azfive.surveys)
Or build your own UI on azfive.surveys.addListener(...) + advance(questionId, response) / dismiss().
Flush & shutdown
Delivery is automatic (10 events / 5 s); with the bindings, the queue also flushes when the last activity stops. flush() forces delivery; the client is AutoCloseable — close() flushes and stops the worker.
Reference
AzFiveConfig (core)
| Parameter | Default | Notes |
|---|---|---|
token | required | Public token (azfive_pub_…) with “Mobile app token” enabled |
host | required | AZ-Five deployment base URL |
project | "default" | Target project slug |
batchSize | 10 | Queue length that triggers a flush |
flushIntervalMs | 5000 | Background flush period |
maxQueueSize | 1000 | Queue bound; oldest events dropped on overflow |
gzip | false | Content-Encoding: gzip on event POSTs |
optOut | false | Start opted out (persisted opt-out wins) |
disableDecide | false | Skip flags/surveys/recording bootstrap |
sessionIdleTimeoutMs | 30 min | Session rotation on inactivity |
store | InMemoryStore() | Persistence backend; the bindings supply SharedPreferencesStore |
enableSessionRecording | false | Session replay opt-in; recording still requires the server to enable it |
AzFive.init (bindings)
AzFive.init(context, token, host, project = "default", autocaptureScreens = false, configure = { it }) — the configure lambda receives the assembled AzFiveConfig for overrides.
Behavior notes
- Sessions rotate after 30 minutes idle or 24 hours total;
$session_idis stamped on every event. - Failed batches —
429included — re-queue at the front and retry next flush; the public API never throws for delivery or flag problems. - Custom event names: anything except the reserved
az.prefix, ≤ 200 characters; properties ≤ 64 KiB serialized.