Setting up Umami Kotlin on Android applications
This guide walks you through installing umami-kotlin in a pure Android (single-platform) project, configuring the client, and tracking your first event.
Already using Kotlin Multiplatform?
See the KMP Get Started guide instead. This page focuses on a standard Android-only module.
1. Add the Dependency
The library is published on Maven Central:
Add the dependency to your Android app module build.gradle.kts (or build.gradle). Replace LATEST_VERSION with the version shown in the badge above.
Using a Version Catalog (Recommended)
If you manage dependencies with a libs.versions.toml catalog:
[versions]
umami = "LATEST_VERSION" # Replace with the latest version
[libraries]
umami = { group = "dev.appoutlet", name = "umami", version.ref = "umami" }
Then in your module build file:
This keeps upgrades centralized—just bump the umami version in the catalog.
2. Ensure Internet Permission
Most apps already have this, but confirm your AndroidManifest.xml includes:
3. Get Your Website ID
From your Umami dashboard:
- Open the website you want to track.
- Copy its Website ID (a UUID).
- If you self‑host Umami, note your base domain (e.g.
https://analytics.mycompany.com). If you use Umami Cloud you can omitbaseUrl(it defaults internally).
4. Create a Singleton Umami Client
Create the client once and reuse it. A convenient place is a custom Application class or your DI container.
Simple Application-level Singleton
class MyApp : Application() {
lateinit var umami: Umami
private set
override fun onCreate() {
super.onCreate()
umami = Umami("YOUR-WEBSITE-UUID") {
// baseUrl("https://your-self-hosted-instance") // Only if self-hosting
}
}
}
AndroidManifest.xml:
Access it anywhere:
Using Hilt (Optional)
@Module
@InstallIn(SingletonComponent::class)
object AnalyticsModule {
@Provides
@Singleton
fun provideUmami(): Umami = Umami("YOUR-WEBSITE-UUID") {
// baseUrl("https://your-self-hosted-instance")
}
}
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
@Inject lateinit var umami: Umami
...
}
5. Track Your First Event
The tracking APIs (event() and identify()) are regular (non-suspend) functions. They enqueue work asynchronously, so it's safe to call them directly on the main thread—no coroutine or background dispatch required.
Track a Screen View (Page View Analogy)
class MainActivity : ComponentActivity() {
@Inject lateinit var umami: Umami
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { /* UI */ }
// Non-blocking call
umami.event(url = "/main", title = "Main Screen")
}
}
Track a Custom Event
Identify a User / Session Enrichment
Info
The calls return immediately; events are placed into an internal queue and processed off the main thread. See detailed parameter explanations on the Event Tracking page.
6. Optional Configuration
All optional parameters can be set inside the Umami constructor lambda. For a more detailed explanation of each parameter, see The Umami object documentation.
Example with common parameters:
import android.content.res.Resources
import java.util.Locale
val umami = Umami("YOUR-WEBSITE-UUID") {
baseUrl("https://analytics.example.com") // Only for self-hosted
language(Locale.getDefault().toLanguageTag())
screenSize("${Resources.getSystem().displayMetrics.widthPixels}x${Resources.getSystem().displayMetrics.heightPixels}")
eventQueueCapacity = 50
}
Type-safe constructor
If you already have domain objects (e.g., Uuid, Hostname), you can use the primary constructor for type safety. This is useful if you validate these values elsewhere.
import dev.appoutlet.umami.Umami
import dev.appoutlet.umami.domain.Hostname
import dev.appoutlet.umami.domain.Language
import dev.appoutlet.umami.domain.ScreenSize
import kotlin.uuid.Uuid
val umamiTypeSafe = Umami(Uuid.parse("YOUR-WEBSITE-UUID")) {
hostname = Hostname("example.com")
language = Language("en-US")
screenSize = ScreenSize(1080, 2400)
eventQueueCapacity = 50
}
7. Threading & Performance
Events are queued internally (Kotlin Channel) and processed off the main thread using Ktor. Your UI stays responsive, and you can fire events freely—even during transitions.
8. Next Steps
- Dive deeper into Event Tracking
- Explore the generated API docs in the Reference section.
You're all set—start capturing meaningful insights from your Android app!