Kotlin / Android SDK
Native Android analytics — app lifecycle, screen tracking, deep links, crash capture, push notifications, and A/B experiments.
The Kotlin SDK integrates directly with the Android Activity and Application lifecycle. Initialize it once from your Application class and it handles everything automatically — no manual screen calls needed for Activity-based screens.
Prerequisites
Installation
Add the dependency
dependencies {
implementation("app.flashanalytics:flashanalytics-kotlin:1.1.5")
}Sync your Gradle project after adding the dependency.
Initialize in Application.onCreate()
Initialize exactly once from your Application class so the SDK is ready before any Activity starts.
import android.app.Application
import app.flashanalytics.sdk.CaptureVariantsOptions
import app.flashanalytics.sdk.FlashAnalyticsOptions
import app.flashanalytics.sdk.android.FlashAnalyticsAndroid
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
FlashAnalyticsAndroid.init(
application = this,
options = FlashAnalyticsOptions(
appId = BuildConfig.FLASH_APP_ID, // UUID from your dashboard
captureAppLifecycle = true,
captureScreenViews = true,
captureDeepLinks = true,
captureInstallAttribution = true,
captureSessionOnInit = true,
captureNativeCrashes = true,
captureVariants = CaptureVariantsOptions(),
batchEnable = true,
batchSize = 10,
batchTimeoutMs = 5_000L,
)
)
}
}Register in AndroidManifest.xml
android:name=".MyApp" in the <application> tag.Identify users and track events
val analytics = FlashAnalyticsAndroid.getInstance()
// After login
analytics.identify(
IdentifyPayload(
profileId = "user_123",
email = "user@example.com",
)
)
// Track a product event
analytics.track("purchase_completed", mapOf(
"orderId" to "order_123",
"amount" to 49.99,
))Auto-capture flags
captureAppLifecycleapp_opened, app_foregrounded, app_backgrounded
captureSessionOnInitsdk_initialized session warm-up before lifecycle events
captureScreenViewsscreen_view on every Activity resume
captureDeepLinksdeep_link_opened for intent URLs
captureInstallAttributionInstall / update attribution
captureNativeCrashesnative_crash report on next launch
captureViewTagsAndroid View tag auto-tracking helpers
capturePushLifecyclePush notification lifecycle helpers
captureVariantsA/B experiment auto-assignment
Error tracking
try {
riskyOperation()
} catch (e: Exception) {
FlashAnalyticsAndroid.getInstance().trackError(
throwable = e,
eventName = "payment_failed",
properties = mapOf("orderId" to orderId),
)
}Dashboard collection controls and timeout
The Kotlin SDK automatically mirrors dashboard-managed collection settings locally. It can drop blocked events, remove blocked properties, apply batching settings, and cache the effective session timeout for heartbeat and local session expiry.
FlashAnalyticsAndroid.init(
application = this,
options = FlashAnalyticsOptions(
appId = BuildConfig.FLASH_APP_ID,
collectionConfig = true,
maxSessionTimeoutInMin = 15,
)
)Startup and heartbeat system events bypass user collection filters. The Android auto-capture pipeline waits for the initial session response before sending install, update, app-open, and screen events that should share the startup session.
Allow events:
app_opened
screen_view
app_installed
app_updated
notification_*
Block events:
debug.*
internal_android_test
For screen_view, allow only:
screenName
path
source
Client-level override for android-prod:
block property androidAdId
session timeout: 15 minutes
batching: 10 events or 5 secondsSDK-side allow and block rules
FlashAnalyticsAndroid.init(
application = this,
options = FlashAnalyticsOptions(
appId = BuildConfig.FLASH_APP_ID,
allowEvents = listOf(
LocalSdkEventRule(
name = "screen_view",
allowProperties = listOf("screenName", "path"),
),
LocalSdkEventRule(
name = "purchase_completed",
allowProperties = listOf("orderId", "amount", "currency"),
),
),
blockEvents = listOf("debug.*", "internal_android_test"),
blockProperties = listOf("androidAdId", "authToken", "rawPushPayload"),
shouldTrack = { payload ->
payload !is TrackHandlerPayload.Track ||
!payload.payload.name.startsWith("dev.")
},
)
)Deep links (warm start)
For warm-start deep links, forward the new intent from your main activity.
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent)
FlashAnalyticsAndroid.getInstance().onNewIntent(intent)
}Experiments
val analytics = FlashAnalyticsAndroid.getInstance()
// All cached assignments — no API call
val all = analytics.getAllExperiments()
// Cache first, API fallback (suspend)
CoroutineScope(Dispatchers.Main).launch {
val assignment = analytics.getExperimentById("checkout-cta")
println(assignment?.variantName)
}
// Callback wrapper for non-coroutine code
analytics.getExperimentByIdAsync("checkout-cta") { result ->
println(result?.variantName)
}Global properties
analytics.setGlobalProperties(mapOf(
"appVersion" to "1.2.0",
"plan" to "pro",
))Session updates
The Android SDK sends sdk_initialized on startup by default so the backend can return a session before install, update, and lifecycle events. Use onSessionUpdatedwhen native code needs the current session ID immediately after it is received or restored.
FlashAnalyticsAndroid.init(
application = this,
options = FlashAnalyticsOptions(
appId = BuildConfig.FLASH_APP_ID,
captureSessionOnInit = true,
onSessionUpdated = { session ->
Log.d("FlashAnalytics", session.id)
Log.d("FlashAnalytics", session.estimatedExpiresAt.toString())
Log.d("FlashAnalytics", session.estimatedTtlMs.toString())
},
)
)Push notifications
analytics.trackNotificationEvent(
event = FlashNotificationEvent.OPENED,
intent = intent,
source = "android_intent",
appState = "terminated",
coldStart = true,
)The SDK supports notification_delivered, notification_opened, notification_dismissed, notification_action_clicked, and notification_expired. Android expiry is inferred from an expiresAt payload value or an optional fallback TTL configured by your app.
notificationId, messageId, campaignId, provider.Manual batch flush
// Call when the app goes to background if you manage lifecycle manually
FlashAnalyticsAndroid.getInstance().flushBatch()When batching is enabled, events are queued and flushed by size or timeout. Android lifecycle capture also flushes when the app moves to the background.