Android SDK
Kixo Android SDK podržava Kotlin 2.0+ i Java, zahteva minSdk 24 (Android 7.0) i kompajliran je uz compileSdk 35. Vaša host aplikacija i dalje sama brine o svom targetSdk. Jedan poziv Kixo.configure u vašem Application.onCreate automatski prati ekrane, dodire, sesije, padove aplikacije i događaje životnog ciklusa. Za praćenje push poruka potreban je FCM most opisan ispod. Automatsko praćenje mrežnih zahteva nije deo trenutnog Android izdanja. SDK podržava i session replay, identitet i ciljeve.
Brzi početak
Tri fajla. Dodajte Maven repozitorijum, dodajte zavisnost, pa ubacite dve linije u svoju podklasu Application.
Zahtevi za build: compileSdk 35, minSdk 24, Kotlin 2.0+ ili Java i Java 17 bytecode.
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
}
}
}Napomena
To je cela analytics integracija. Standardni auto-tracker-i su podrazumevano uključeni; za push je i dalje potreban FCM most ispod. Pojedinačne flag-ove menjajte preko KixoConfiguration.Builder(...) samo kada je potrebno.
Dodajte u aplikaciju
Kixo Maven repozitorijum hostuje se na GitHub Pages. Dodajte ga uz google() i mavenCentral() u settings.gradle.kts:
// settings.gradle.kts
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
}
}
}Zatim dodajte zavisnost u modul aplikacije:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Savet
android.permission.INTERNET i android.permission.ACCESS_NETWORK_STATE su uključeni u manifest SDK-a. Dozvole za notifikacije i dalje kontroliše vaša aplikacija i prijavljuju se kada uključite push funkcije.
Projekti sa više modula
Gradle konfiguracija implementation je nije tranzitivno: ako u bibliotečkom modulu (npr. :core_domain) deklarišete implementation("io.kixo:kixo-android-sdk:0.1.20"), to NE čini Kixo vidljivim za :app niti za bilo kog drugog potrošača. Postoje dva ispravna obrasca — izaberite jedan.
Obrazac A — svaki modul koji poziva Kixo deklariše ga sam (preporučeno). Održava classpath svakog modula malim i sprečava kaskadne rebuild-ove. Koristite version catalog (libs.kixo.sdk) da verziju menjate na jednom mestu.
// :core_domain/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20") // local use only
}
// :app/build.gradle.kts
dependencies {
implementation(project(":core_domain"))
implementation("io.kixo:kixo-android-sdk:0.1.20") // declared again — fine
}Obrazac B — reeksport preko api(...). Jedna deklaracija, ali javni ABI bibliotečkog modula tada uključuje Kixo tipove — svaka promena verzije pokreće rebuild svih downstream modula. Koristite ovo samo kada biblioteka koristi Kixo tipove i u svojim javnim potpisima, na primer kada funkcija vraća KixoDiagnostics.
// :core_domain/build.gradle.kts
dependencies {
api("io.kixo:kixo-android-sdk:0.1.20") // re-exposed
}
// :app/build.gradle.kts
dependencies {
implementation(project(":core_domain")) // gets Kixo for free
}Upozorenje
Ako pri kompilaciji u nekom modulu vidite Unresolved reference: Kixo, tom modulu nedostaje sopstvena zavisnost od SDK-a — dodajte implementation red iznad ili koristite obrazac B.
Inicijalizacija
Podesite Kixo iz svoje podklase Application — onCreate se izvršava pre bilo koje activity, pa se svaki prikaz ekrana, dodir i događaj životnog ciklusa beleži od prvog kadra. Registrujte Application u manifestu pomoću android:name=".MyApp".
import android.app.Application
import io.kixo.sdk.Kixo
class MyApp : Application() {
override fun onCreate() {
super.onCreate()
Kixo.configure(
context = this,
projectId = "kx_proj_YOUR_PROJECT_ID",
apiKey = "kx_key_YOUR_API_KEY",
)
}
}Za detaljna podešavanja (flagove za automatsko praćenje, učestalost flush-a, replay sampling, prilagođeni API host) eksplicitno napravite KixoConfiguration:
import io.kixo.sdk.Kixo
import io.kixo.sdk.KixoConfiguration
val config = KixoConfiguration.Builder(
projectId = "kx_proj_YOUR_PROJECT_ID",
apiKey = "kx_key_YOUR_API_KEY",
)
.autoTrackScreens(true)
.autoTrackTaps(true)
.autoTrackNetwork(false) // reserved; no-op in the current Android release
.autoTrackCrashes(true)
.autoTrackSessions(true)
.autoTrackPush(true)
.flushIntervalMillis(30_000)
.flushAt(20)
.maxBufferSize(200)
.build(applicationContext)
Kixo.configure(this, config)Napomena
Idempotentno. Drugi poziv configure iz istog procesa samo se zabeleži kao WARN i ne radi ništa — SDK zadržava prvu konfiguraciju. Događaji koje vaš auth singleton stavi u red pre nego što pre stigne do configure čuvaju se u baferu (do 50) i reprodukuju kada se SDK poveže, pa Kixo.identify(...) možete da pozovete iz globalnog konteksta i pre nego što se Application.onCreate završi.
Pratite događaje
Tri osnove nose najveći deo vaše instrumentacije: track za događaje, markGoal za signale konverzije i addBreadcrumb za kontekst van događaja.
import io.kixo.sdk.Kixo
Kixo.track("video_played", mapOf(
"video_id" to "vid_42",
"duration_ms" to 18_500,
"autoplay" to false,
))
// markGoal(name, value?, currency?, properties?) — pass extra context
// through the named 'properties' argument (a Map can't be the 2nd
// positional arg; that slot is the Double 'value').
Kixo.markGoal("activated", properties = mapOf(
"step" to "onboarding_completed",
))
// Revenue goals use the typed value + currency parameters:
Kixo.markGoal("purchase_completed", value = 49.99, currency = "USD")
Kixo.addBreadcrumb(
message = "user toggled dark mode",
category = "ui",
level = "info",
)Savet
Ciljevi se ocenjuju. Označeni ciljevi ulaze u Kixo levke aktivacije i dnevni cron za detekciju promena — cilj čiji obim padne 70% u odnosu na prethodnu nedelju pojaviće se u dashboardu sa oznakom Potrebna provera. Koristite markGoal za nekoliko ključnih trenutaka, a track za sve ostalo.
Standardni događaji
Tanki sloj preko Kixo.track za događaje koje Kixo prepoznaje po nazivu — doslovne string ključeve koje backend detektor standardnih događaja prepoznaje. Dobijate proveru oblika svojstava u vreme kompajliranja i jedno mesto istine za imenovanje.
import io.kixo.sdk.Kixo
import io.kixo.sdk.SubscriptionInterval
Kixo.trackPurchase(
amount = 49.99,
currency = "USD",
productId = "pro_yearly",
)
Kixo.trackSubscriptionStart(
plan = "pro",
amount = 9.99,
currency = "USD",
interval = SubscriptionInterval.MONTH,
)
Kixo.trackSignup(method = "google")
Kixo.trackTrialStart(plan = "pro", days = 14)
Kixo.trackCancel(plan = "pro", reason = "too_expensive")
Kixo.trackUpgrade(fromPlan = "free", toPlan = "pro")
Kixo.trackActivation(event = "first_post_published")
Kixo.trackShare(channel = "twitter", contentId = "post_123")
Kixo.trackInvite(channel = "email", recipientCount = 5)Identifikujte korisnike
Povežite naredne događaje sa stabilnim ID-jem korisnika i skupom trait-ova. Spajanje anonimnog i poznatog identiteta radi Kixo — događaji zabeleženi pre identify naknadno se pripisuju istom korisniku.
import io.kixo.sdk.Kixo
// Reserved standard property keys carry a $-prefix (Mixpanel
// convention) so they namespace away from your own custom traits
// and promote to the dashboard's profile columns. See
// io.kixo.sdk.StandardProperty for the typed catalogue, or the
// "Standard property catalog" section below for the full 37-key list.
Kixo.identify("user_123", mapOf(
"$email" to "jane@example.com", // identity
"$name" to "Jane Doe", // identity
"$plan" to "pro", // subscription pack
"$lifetime_orders" to 12, // e-commerce pack
"signup_source" to "twitter_ad", // custom trait
))
// Logout: clear identity, super-properties, and the persisted queue.
Kixo.reset()⚠️ Zamka sa znakom dolara u Kotlinu. Standardni identitetski ključevi imaju prefiks $ ($email, $name, $first_name) — a u Kotlin string literalu mora znak dolara morate da escape-ujete kao "\$email". Ako napišete "$email", interpolira se promenljiva email, pa vrednost neprimetno završi kao trait prilagođeno i nikada ne popuni kolone za email / ime u Audience. Najjednostavnije rešenje je typed overload (SDK 0.1.13+), koji praktično ne može da se pogreši: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Označite korisnika za segmentaciju
Koristite setUserProperty sa vrednošću tipa logička vrednost da korisniku dodelite jednostavnu da/ne oznaku. Oznaka ostaje sačuvana između pokretanja aplikacije i koristi se za segmente, email kampanje i upite u chatu — bez dodatnog podešavanja osim SDK poziva.
// Tag a user as subscribed — segments + campaigns can target this
Kixo.setUserProperty("subscribe", true)
// VIP membership
Kixo.setUserProperty("vip", true)
// String + numeric values work too
Kixo.setUserProperty("plan_tier", "enterprise")
Kixo.setUserProperty("lifetime_orders", 42)
// Bulk-set
Kixo.setUserProperties(mapOf(
"subscribe" to true,
"plan_tier" to "enterprise",
))Svojstva se čuvaju preko SharedPreferences između pokretanja aplikacije i automatski dodaju svakom odlaznom događaju. U chatu možete da kažete nešto poput "pošalji imejl dobrodošlice korisnicima gde je subscribe true" — Kixo će za vas napraviti segment i pripremiti šablon. Brišu se pri Kixo.reset().
Standardni katalog svojstava
Rezervisani ključevi svojstava nose prefiks $ kako bi bili odvojeni od vaših prilagođenih osobina. Kixo katalog obuhvata 37 ključeva u 3 univerzalna paketa (identitet, geo, životni ciklus) i 5 B2B vertikalnih paketa (pretplata, e-trgovina, mediji, tržište, program lojalnosti). Podesite samo ono što je relevantno za vaš proizvod — dashboard se prilagođava i prikazuje samo pakete koje popunite.
Identitet
Uvek relevantno. Podešava kolone zaglavlja profila.
| Ključ | Tip | Opis |
|---|---|---|
$email | niska | Primarna imejl adresa, često glavni ključ za povezivanje identiteta. |
$phone | niska | Broj telefona u formatu E.164. |
$name | niska | Puno ime za prikaz. |
$first_name | niska | Ime. |
$last_name | niska | Prezime. |
$avatar_url | niska | Pun URL do korisnikove avatar slike. |
Geo
Geografski kontekst.
| Ključ | Tip | Opis |
|---|---|---|
$country | niska | ISO 3166 kod države. |
$city | niska | Naziv grada. |
$region | niska | Država ili pokrajina. |
$timezone | niska | IANA zona, na primer America/Los_Angeles. |
$language | niska | IETF oznaka, na primer en ili ru-RU. |
$locale | niska | Puni identifikator lokalizacije. |
Životni ciklus
Kada smo ga videli.
| Ključ | Tip | Opis |
|---|---|---|
$created | ISO8601 | Vreme registracije ili otvaranja naloga. |
$last_seen | ISO8601 | Vreme poslednje interakcije. |
Pretplata
Podesite ako vaš proizvod ima planove.
| Ključ | Tip | Opis |
|---|---|---|
$plan | niska | Slug nivoa — free, pro, enterprise. |
$subscription_status | niska | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | Kada ističe trenutni probni period. |
$mrr | broj | Mesečni ponavljajući prihod u valuti naloga. |
$subscription_started | ISO8601 | Kada je počela trenutna pretplata. |
E-trgovina
Podesite ako prodajete proizvode.
| Ključ | Tip | Opis |
|---|---|---|
$lifetime_orders | broj | Broj završenih porudžbina. |
$lifetime_revenue | broj | Ukupna potrošnja. |
$aov | broj | Prosečna vrednost porudžbine. |
$last_purchase | ISO8601 | Najnovija uspešna kupovina. |
$first_purchase | ISO8601 | Prva uspešna kupovina. |
$cart_abandoned_count | broj | Ukupan broj napuštanja korpe. |
Mediji
Podesite ako objavljujete sadržaj.
| Ključ | Tip | Opis |
|---|---|---|
$content_tier | niska | free / premium / paid. |
$subscribed_categories | CSV string ili niz | Kategorije koje korisnik prati. |
$watch_time_total | broj | Ukupno vreme gledanja u sekundama. |
$last_played | ISO8601 | Najnovije pokretanje reprodukcije. |
Tržište
Podesite ako ste platforma sa dve strane.
| Ključ | Tip | Opis |
|---|---|---|
$seller_tier | niska | Slug nivoa na strani prodavca. |
$buyer_tier | niska | Slug paketa na strani kupca. |
$listings_count | broj | Aktivni oglasi koje korisnik poseduje. |
$reviews_count | broj | Recenzije koje je korisnik dobio. |
$verified | logička vrednost | KYC status. |
Program lojalnosti
Podesite ako koristite programe angažovanja i nagrađivanja.
| Ključ | Tip | Opis |
|---|---|---|
$loyalty_points | broj | Trenutni raspoloživi saldo poena. |
$vip_level | niska | Slug VIP nivoa. |
$referral_count | broj | Uspešne preporuke pripisane ovom korisniku. |
Savet
Ne vidite svoj obrazac? Za prilagođene trait-ove koristite obične ključeve. Prikazuju se u panelu Custom Traits na dashboardu, bez zagušenja kolona profila. Pet vertikalnih paketa iznad su promišljene pretpostavke o najčešćim B2B modelima — terminologija specifična za korisnika (npr. shipping_plan) ostaje bez prefiksa.
Super-svojstva
Parovi ključ/vrednost na nivou sesije koji se automatski dodaju svakom odlaznom događaju. Za razliku od identify trait-ova, koji opisuju identitet, super-properties opisuju kontekst sesije — aktivnu A/B varijantu, build flavor i uključene feature flag-ove. Ostaju sačuvani između pokretanja aplikacije; brišu se pri reset(). Ako dođe do preklapanja, prednost uvek imaju properties zadati po događaju na track.
import io.kixo.sdk.Kixo
Kixo.setSuperProperty("build_flavor", "beta")
Kixo.setSuperProperties(mapOf(
"ab_variant" to "B",
"referrer_campaign" to "autumn-launch",
))
// Sugar for A/B tracking — stored as 'experiment_<id>'.
Kixo.setExperimentVariant("checkout_v2", "variant_a")
Kixo.unsetSuperProperty("build_flavor")
Kixo.clearSuperProperties()Push obaveštenja
Postoje dva puta integracije. Izaberite A ako koristite FCM i želite najkraće funkcionalno podešavanje; izaberite B ako već imate prilagođeni FirebaseMessagingService koji ne možete da restrukturirate ili želite eksplicitnu kontrolu nad tim koje FCM isporuke Kixo vidi.
Opcija A — nasledite KixoFirebaseMessagingService (automatsko praćenje)
Nasledite KixoFirebaseMessagingService i iz svog override-a pozovite super.onMessageReceived(...) — Kixo automatski emituje push_received (vidljiv payload) ili push_silent (samo podaci). Bazna klasa obrađuje i registraciju za onNewToken ako je sami ne override-ujete. Registracija za AndroidManifest.xml ostaje ista kao kod običnog FCM servisa.
import com.google.firebase.messaging.RemoteMessage
import io.kixo.sdk.KixoFirebaseMessagingService
class MyMessagingService : KixoFirebaseMessagingService() {
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage) // Kixo auto-tracks push_received
// … your own routing / notification display
}
}Napomena
Kixo kompajlira ovu opcionu klasu uz Firebase Messaging, ali ne dodaje Firebase tranzitivno vašoj aplikaciji. SDK deklariše Firebase kao compileOnly; aplikacija koja koristi ovu opciju već mora da zavisi od firebase-messaging, kao i svaki FCM receiver.
Opcija B — pozovite ručni API iz svog FCM servisa
Registrujte FCM token u Kixo preko FirebaseMessagingService.onNewToken, a zatim eksplicitno beležite svaku isporuku. Ovaj pristup koristite kada želite da Kixo vidi samo deo FCM isporuka. Android isporuka trenutno podržava samo FCM.
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import io.kixo.sdk.Kixo
import io.kixo.sdk.PushProvider
class MyMessagingService : FirebaseMessagingService() {
override fun onNewToken(token: String) {
Kixo.setPushToken(token, PushProvider.FCM)
}
override fun onMessageReceived(message: RemoteMessage) {
// Convert the FCM payload to a Map<String, Any?> and log it —
// Kixo correlates this with the open / dismiss it sees later.
Kixo.logPushReceived(message.data.toMap(), appState = "background")
}
}Android ne izlaže univerzalni lifecycle hook za otvaranje notifikacija, odbacivanje niti dugmad za akcije. Prosledite te signale iz notification intent-a ili receiver-a koje vaša aplikacija kreira:
import io.kixo.sdk.Kixo
Kixo.logPushOpened(payload = pushPayload) // open
Kixo.logPushOpened(payload = pushPayload, actionId = "reply") // action-button tap
Kixo.logPushDismissed(payload = pushPayload) // swipe-awaySnimak sesije
Replay daje stvarnu vizuelnu rekonstrukciju onoga što je korisnik video. Pri svakom snimanju SDK enkoduje kompresovani kadar ekrana (JPEG sliku) zajedno sa strukturnim snimkom hijerarhije prikaza i otprema oba, tako da plejer u dashboardu može da prikaže piksel-preciznu reprodukciju uz vremensku liniju interakcija. Replay za projekat podesite u Kontrolna tabla → Podešavanja → Snimanje sesije. SDK tu politiku projekta automatski učitava i osvežava, uključujući maskiranje, režime snimanja i dozvolu za otpremanje preko mobilne mreže.
import io.kixo.sdk.Kixo
import io.kixo.sdk.KixoConfiguration
val config = KixoConfiguration.Builder(
projectId = "kx_proj_YOUR_PROJECT_ID",
apiKey = "kx_key_YOUR_API_KEY",
)
.build(applicationContext)
Kixo.configure(this, config)Kada je otpremanje preko mobilne mreže isključeno, replay na čekanju ostaje dok se ne pojavi dozvoljena mreža.
Savet
Maskirajte pre otpremanja. Kixo snima piksele, pa se maskiranje primenjuje pre nego što bilo šta napusti uređaj. Polja za lozinku i e-adresu prepoznaju se automatski i rediguju; tekst u strukturnim snimcima prolazi kroz PII filter; a svaki view koji označite sa setKixoMask(true) rasterizuje se kao neprovidan pravougaonik u kadru pre nego što se JPEG enkoduje — njegovi pikseli nikada ne napuštaju uređaj. Ekrani u Jetpack Compose su podrazumevano u celosti maskirani (pozovite setKixoMask(false) na spoljašnjem ComposeView da uključite ekran koji ste proverili). Operateri u dashboardu pregledaju replay plejer zajedno sa vremenskom linijom događaja.
Prikupljanje podataka
SDK beleži podatke koji su uključeni u projektu, kao i događaje i svojstva koje vaša aplikacija šalje.
Otklanjanje problema
Kixo.diagnostics() vraća pregled stanja SDK-a samo za čitanje — korisno na skrivenom debug ekranu ili u smoke testu. Odgovara na pitanje „zašto mi događaji ne prolaze?“ bez debugger-a.
import io.kixo.sdk.Kixo
val diag = Kixo.diagnostics()
Log.d("Kixo", "queued=${diag.queue.bufferedEventCount}")
Log.d("Kixo", "paused=${diag.paused}") // collection paused state
Log.d("Kixo", "lifecycleState=${diag.lifecycleState}") // SDK lifecycle statePrinudno pokrenite flush iz test harness-a — blokira do timeoutMs tokom jednog mrežnog round-trip-a:
import io.kixo.sdk.Kixo
// Async fire-and-forget — returns immediately.
Kixo.flush()
// Blocking variant for instrumentation tests. Never call on the main thread.
val landed: Boolean = Kixo.flushBlocking(timeoutMs = 5_000L)
assertTrue(landed)Compose Navigation
Rute Activity / Fragment odmah proizvode screen_view događaje i strukturirane screen_visit zapise sa metapodacima o zadržavanju i toku, bez dodatnog podešavanja. Za Jetpack Compose Navigation pozovite Kixo.screen iz LaunchedEffect vezanog za rutu — SDK tada vidi jedan događaj po odredištu, bez obzira na broj rekompozicija.
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import io.kixo.sdk.Kixo
@Composable
fun AppNavHost(nav: NavHostController) {
NavHost(navController = nav, startDestination = "home") {
composable("home") {
LaunchedEffect("home") { Kixo.screen("HomeScreen") }
HomeScreen()
}
composable("settings") {
LaunchedEffect("settings") { Kixo.screen("SettingsScreen") }
SettingsScreen()
}
}
}AI agenti za kodiranje
Javna površina SDK-a je mala i prilagođena code completion-u — svaka metoda je na singletonu Kixo, svaki Kotlin primer u ovom vodiču počinje sa import io.kixo.sdk.Kixo, a naš README sadrži blok „AI agent quick reference“ koji alati kao što su Claude Code, Cursor i Codex mogu direktno da ubace u svoj kontekst. Ako vam se agent zaglavi, evo kanonske početne tačke:
// Tell your AI coding agent:
// "Integrate the Kixo Android SDK using io.kixo:kixo-android-sdk
// from https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo.
// Call Kixo.configure(this, projectId, apiKey) in Application.onCreate.
// Then use Kixo.track / Kixo.identify / Kixo.markGoal as needed."Napomena
Svaki odeljak iznad napisan je za taj tok rada — importi su uvek eksplicitni, tipovi su uvek imenovani, a SDK singleton nikada nema alias. Prosledite ovu stranicu svom agentu i pustite ga da vodi.