▸Install the Kotlin (Android) SDK
// build.gradle.kts (app module)
dependencies {
implementation("com.respectlytics:respectlytics-kotlin:3.0.0")
}
Pure Kotlin coroutines implementation. No Java dependencies, no Google Play Services dependencies. ~300KB DEX overhead — compare to roughly 3.8MB for Firebase Analytics (a measurable cold-start improvement on lower-end devices).
▸Initialize Respectlytics in Kotlin (Android)
import com.respectlytics.android.Respectlytics
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
Respectlytics.configure(this, appKey = "<YOUR_APP_KEY>")
}
}
Initialize once in Application.onCreate. No additional permissions in the manifest — INTERNET is sufficient. The SDK does not request AD_ID, does not query AdvertisingIdClient, and does not declare ACCESS_NETWORK_STATE.
✦Privacy & implementation notes
The deliberate event-loss-on-force-quit posture is the most common point of friction in adoption: most product / data teams default to "events must be 100% delivered" without questioning the assumption. The follow-up question — "what decision changes if we lose 1%?" — usually produces no real answer for product analytics. Revenue and accounting data, where the answer matters, lives in your billing system, not your product analytics.
On Android, app force-quit via the recent-tasks switcher is more aggressive than on iOS — the OS doesn't deliver a onPause callback in many such cases. Practical mitigation: SDK flushes more aggressively when the app comes back to foreground, catching the previous session's tail events. The 1–2% loss figure is after that mitigation.
Many teams discover the com.google.android.gms.permission.AD_ID permission in their merged manifest only after Google Play flags them — usually because a transitive dependency dragged it in. Respectlytics's Kotlin SDK has no Google Play Services dependency at all, so it cannot contribute to that merge.
The SDK is implemented as pure Kotlin coroutines with no Java sources, no RxJava, and no platform channels. Events are queued in a Channel<Event> buffered to a small ring (RAM-only), drained by a coroutine that flushes every 30 seconds or on backgrounding. There is no SharedPreferences usage.
⇋How this compares to other analytics SDKs
| Event queue | Firebase Analytics | Mixpanel | Amplitude | Respectlytics |
|---|---|---|---|---|
| Backed by | SQLite on disk | SQLite on disk | SQLite on disk | In-memory ring buffer |
| Default flush cadence | ~1 hour | Configurable (30s default) | 30s | 30s |
| Flushes on backgrounding | Yes | Yes | Yes | Yes |
| Flushes on terminate | Yes (best-effort) | Yes (best-effort) | Yes | No (RAM only) |
| Queue survives crash | Yes | Yes | Yes | No |
| Maximum queued event count | 100k+ | 100k+ | Unbounded | ~5k (ring eviction) |
❓Frequently asked questions
What's the typical event-loss rate?
In our internal benchmarks against fixture apps, force-quit between event submission and the next flush loses approximately 0.5–2% of events — the lower end on iOS where backgrounding is more predictable, the higher end on Android where users force-quit more aggressively. For aggregate metrics this is invisible; for per-event reconciliation it would be a problem, but per-event reconciliation isn't a use case Respectlytics supports.
Can the queue size grow unboundedly?
No — the in-memory buffer is bounded (default ~5,000 events). When the buffer fills (which we've never observed in production: it would require a sustained outage of our network endpoint plus very high in-app event volume), the oldest event is evicted. The bound is intentional: an unbounded queue would invite memory pressure on low-RAM Android devices.
Does the flush cadence affect billing / quota counts?
No. Quota counts the number of events ingested at our API, not the number of flushes. A single flush carries a batch of events; the batch size is a performance optimisation, not a billable unit.
How does this affect testing analytics in CI / debug?
Identically to production. The 30s cadence applies in debug too, but the SDK exposes a flush() API for tests to force-flush at known points. Use this in integration tests against a staging app key.