Android SDK
Kixo Android SDK podržava Kotlin 2.0+ i Javu, zahtijeva minSdk 24 (Android 7.0) i izgrađen je prema compileSdk 35. Vaša host aplikacija i dalje je sama odgovorna za svoj targetSdk. Jedan poziv Kixo.configure u vašem Application.onCreate automatski bilježi zaslone, dodire, sesije, rušenja i događaje životnog ciklusa. Za praćenje push obavijesti potreban je FCM most opisan niže. Automatsko praćenje mrežnih zahtjeva nije dio trenutačnog Android izdanja. SDK podržava i replay sesije, identitet i ciljeve.
Početak rada
Tri datoteke. Dodajte Maven repozitorij, dodajte ovisnost, pa ubacite dva retka u svoju podklasu Application.
Zahtjevi za build: compileSdk 35, minSdk 24, Kotlin 2.0+ ili Java te 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
Time je integracija analitike gotova. Standardni automatski trackeri uključeni su po zadanim postavkama; za push i dalje trebate FCM most opisan niže. Pojedine zastavice mijenjajte preko KixoConfiguration.Builder(...) samo kad je to potrebno.
Dodajte u aplikaciju
Kixo Maven repozitorij hostan je 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 deklarirajte ovisnost u modulu aplikacije:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Savjet
android.permission.INTERNET i android.permission.ACCESS_NETWORK_STATE uključeni su u manifest SDK-a. Dozvole za obavijesti i dalje ostaju pod kontrolom vaše aplikacije i deklarirate ih tek kad uključite push funkcije.
Višemodulski projekti
Gradleova konfiguracija implementation je nije tranzitivno: deklariranje implementation("io.kixo:kixo-android-sdk:0.1.20") u bibliotečnom modulu (npr. :core_domain) NE čini Kixo vidljivim modulu :app ni bilo kojem drugom potrošaču. Rade dva obrasca — odaberite jedan.
Obrazac A — svaki modul koji poziva Kixo deklarira ga zasebno (preporučeno). drži classpath svakog modula što manjim i izbjegava lančane rebuildove. Koristite version catalog (libs.kixo.sdk) kako biste verziju mijenjali na jednom mjestu.
// :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 — ponovno izvezite kroz api(...). Jedna deklaracija, ali javni ABI bibliotečnog modula tada uključuje Kixo tipove — svaka promjena verzije pokreće rebuild svih nizvodnih modula. Ovo koristite samo kad biblioteka Kixo tipove koristi i u vlastitim javnim potpisima, npr. vraća KixoDiagnostics iz funkcije.
// :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 vlastita ovisnost o SDK-u — dodajte gornji redak s implementation ili primijenite obrazac B.
Inicijalizacija
Konfigurirajte Kixo u svojoj podklasi Application — onCreate se izvršava prije bilo koje aktivnosti, pa se svaki prikaz zaslona, dodir i događaj životnog ciklusa bilježe od prvog kadra. Registrirajte Application u manifestu s 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 detaljnije postavke (zastavice automatskog praćenja, učestalost flusha, uzorkovanje replaya, prilagođeni API host) eksplicitno izgradite 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 evidentira se kao WARN i ne radi ništa — SDK zadržava prvu konfiguraciju. Događaji koje vaš auth singleton stavi u red prije nego što prije configure bude spreman međuspremuju se (do 50) i šalju nakon što se SDK inicijalizira, pa Kixo.identify(...) možete pozvati iz globalnog konteksta prije nego što Application.onCreate završi.
Bilježenje događaja
Tri osnovna mehanizma pokrivaju većinu instrumentacije: track za događaje, markGoal za signale konverzije i addBreadcrumb za kontekst koji nije vezan uz događaj.
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",
)Savjet
Ciljevi imaju razine. Označeni ciljevi ulaze u Kixo aktivacijske funnel-e i dnevni cron za otkrivanje promjena — cilj čiji volumen padne 70% u odnosu na prethodni tjedan pojavit će se na nadzornoj ploči s oznakom Treba pregledati. markGoal koristite za nekoliko ključnih trenutaka, a track za sve ostalo.
Standardni događaji
Tanak sloj iznad Kixo.track za događaje koje Kixo prepoznaje po nazivu — doslovne string ključeve koje backendov detektor standardnih događaja uparuje. Dobivate provjeru oblika svojstava pri kompilaciji i jedno mjesto 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)Identificirajte korisnike
Povežite sve sljedeće događaje sa stabilnim ID-jem korisnika i skupom atributa. Spajanje anonimnog i poznatog identiteta događa se u Kixo — događaji zabilježeni prije identify retroaktivno 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 ključevi identiteta imaju prefiks $ ($email, $name, $first_name) — a u Kotlin literalu znak dolara mora escapati kao "\$email". Ako napišete "$email", interpolirat ćete varijablu email, pa će vrijednost tiho završiti kao atribut prilagođeno i nikad neće popuniti stupce e-pošte / imena u Audienceu. Najjednostavnije rješenje je tipizirano preopterećenje (SDK 0.1.13+), koje ne možete pogrešno upotrijebiti: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Označite korisnika za segmentaciju
Upotrijebite setUserProperty s vrijednošću boolean da korisniku dodate jednostavnu da/ne oznaku. Oznaka ostaje sačuvana između pokretanja aplikacije i koristi se za segmente, e-mail kampanje i upite u chatu — bez ikakve dodatne postave izvan poziva SDK.
// 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 preko SharedPreferences čuvaju između pokretanja aplikacije i automatski dodaju svakom odlaznom događaju. U chatu možete reći, primjerice, "pošalji e-poruku dobrodošlice korisnicima kod kojih je subscribe true" — Kixo će za vas složiti segment i pripremiti predložak. Brišu se pri Kixo.reset().
Katalog standardnih svojstava
Rezervirani ključevi svojstava nose prefiks $ kako bi bili odvojeni od vaših prilagođenih atributa. Kixo katalog pokriva 37 ključeva u 3 univerzalna paketa (identitet, geo, životni ciklus) i 5 B2B vertikalnih paketa (pretplata, e-trgovina, mediji, marketplace, program vjernosti). Postavite samo ono što odgovara vašem proizvodu — nadzorna ploča prilagođava se i prikazuje samo pakete koje popunite.
Identitet
Uvijek relevantno. Postavlja stupce zaglavlja profila.
| Ključ | Vrsta | Opis |
|---|---|---|
$email | tekst | Primarna adresa e-pošte, često glavni ključ za spajanje identiteta. |
$phone | tekst | Telefonski broj u formatu E.164. |
$name | tekst | Puni prikazni naziv. |
$first_name | tekst | Ime. |
$last_name | tekst | Prezime. |
$avatar_url | tekst | Puni URL korisnikove avatar slike. |
Geo
Geografski kontekst.
| Ključ | Vrsta | Opis |
|---|---|---|
$country | tekst | ISO 3166 kod države. |
$city | tekst | Naziv grada. |
$region | tekst | Država, savezna država ili pokrajina. |
$timezone | tekst | IANA zona poput America/Los_Angeles. |
$language | tekst | IETF oznaka poput en ili ru-RU. |
$locale | tekst | Puni identifikator lokalizacije. |
Životni ciklus
Kad smo ih vidjeli.
| Ključ | Vrsta | Opis |
|---|---|---|
$created | ISO8601 | Vrijeme registracije ili otvaranja računa. |
$last_seen | ISO8601 | Vrijeme zadnje interakcije. |
Pretplata
Postavite ako vaš proizvod ima pakete.
| Ključ | Vrsta | Opis |
|---|---|---|
$plan | tekst | Slug razine — free, pro, enterprise. |
$subscription_status | tekst | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | Kad istječe trenutačno probno razdoblje. |
$mrr | broj | Mjesečni ponavljajući prihod u valuti računa. |
$subscription_started | ISO8601 | Kad je počela trenutačna pretplata. |
E-trgovina
Postavite ako prodajete proizvode.
| Ključ | Vrsta | Opis |
|---|---|---|
$lifetime_orders | broj | Broj dovršenih narudžbi. |
$lifetime_revenue | broj | Ukupna potrošnja. |
$aov | broj | Prosječna vrijednost narudžbe. |
$last_purchase | ISO8601 | Vrijeme zadnje uspješne kupnje. |
$first_purchase | ISO8601 | Prva uspješna kupnja. |
$cart_abandoned_count | broj | Ukupan broj napuštanja košarice. |
Mediji
Postavite ako objavljujete sadržaj.
| Ključ | Vrsta | Opis |
|---|---|---|
$content_tier | tekst | free / premium / paid. |
$subscribed_categories | CSV string ili polje | Kategorije koje korisnik prati. |
$watch_time_total | broj | Ukupno vrijeme gledanja u sekundama. |
$last_played | ISO8601 | Vrijeme zadnjeg pokretanja reprodukcije. |
Marketplace
Postavite ako ste dvostrana platforma.
| Ključ | Vrsta | Opis |
|---|---|---|
$seller_tier | tekst | Slug paketa na strani prodavatelja. |
$buyer_tier | tekst | Slug paketa na strani kupca. |
$listings_count | broj | Aktivni oglasi koje korisnik posjeduje. |
$reviews_count | broj | Recenzije koje je korisnik primio. |
$verified | boolean | KYC status. |
Program vjernosti
Postavite ako imate programe angažmana i nagrađivanja.
| Ključ | Vrsta | Opis |
|---|---|---|
$loyalty_points | broj | Trenutačno stanje iskoristivih bodova. |
$vip_level | tekst | Slug VIP razine. |
$referral_count | broj | Uspješne preporuke pripisane ovom korisniku. |
Savjet
Ne vidite svoj obrazac? Za prilagođene atribute koristite obične ključeve. Prikazat će se u panelu Custom Traits na dashboardu, bez zatrpavanja stupaca profila. Pet vertikalnih paketa iznad promišljene su pretpostavke najčešćih B2B obrazaca — terminologija specifična za vaš proizvod (npr. shipping_plan) ostaje bez prefiksa.
Super-svojstva
Parovi ključ/vrijednost na razini sesije automatski se dodaju svakom odlaznom događaju. Za razliku od atributa identify, koji opisuju identitet, super-svojstva opisuju kontekst sesije — aktivnu A/B varijantu, build flavor i uključene feature flagove. Ostaju sačuvana između pokretanja aplikacije, a brišu se pri reset(). Ako dođe do kolizije, prednost uvijek imaju properties postavljena 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 obavijesti
Dva su puta integracije. Odaberite A ako koristite FCM i želite najkraće funkcionalno postavljanje; odaberite B ako već imate prilagođeni FirebaseMessagingService koji ne možete preurediti ili želite izričitu kontrolu nad time koje FCM isporuke Kixo vidi.
Opcija A — naslijedite KixoFirebaseMessagingService (automatsko praćenje)
Naslijedite KixoFirebaseMessagingService i iz svojeg overrida pozovite super.onMessageReceived(...) — Kixo će automatski emitirati push_received (vidljivi payload) ili push_silent (samo podatkovni payload). Bazna klasa obrađuje i registraciju onNewToken ako je ne overrideate. Registracija AndroidManifest.xml ostaje ista kao i u običnom FCM servisu.
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 ovu opcionalnu klasu kompilira uz Firebase Messaging, ali Firebase ne dodaje tranzitivno u vašu aplikaciju. SDK deklarira Firebase kao compileOnly; aplikacija koja odabere ovu mogućnost već mora ovisiti o firebase-messaging, kao i svaki FCM receiver.
Opcija B — pozovite ručni API iz vlastitog FCM servisa
Registrirajte svoj FCM token u Kixo preko FirebaseMessagingService.onNewToken, a zatim svaku isporuku zabilježite izričito. Ovaj pristup koristite kad želite da Kixo vidi samo dio FCM isporuka. Isporuka na Android trenutačno 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 otvaranja obavijesti, odbacivanja ni akcijske gumbe. Te signale proslijedite iz notification intenta ili receivera 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-awaySnimka sesije
Prikažite stvarnu vizualnu rekonstrukciju onoga što je korisnik vidio. Pri svakom snimanju SDK kodira komprimirani kadar zaslona (JPEG sliku) zajedno sa strukturnom snimkom hijerarhije prikaza i prenosi oboje, tako da player na nadzornoj ploči može prikazati pikselno vjernu reprodukciju uz vremensku crtu interakcija. Replay za projekt konfigurirate u Nadzorna ploča → Postavke → Reprodukcija sesije. SDK tu projektnu politiku automatski čita i osvježava, uključujući maskiranje, načine snimanja i dopuštenje za prijenos 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)Ako je prijenos preko mobilne mreže isključen, replay na čekanju čeka dopuštenu mrežu.
Savjet
Maskirajte prije slanja. Kixo snima piksele, zato se maskiranje primjenjuje prije nego što bilo što napusti uređaj. Polja za lozinku i e-poštu automatski se prepoznaju i zatamnjuju; tekst u strukturnim snimkama prolazi kroz PII filtar; a svaki prikaz koji označite s setKixoMask(true) rasterizira se u neproziran pravokutnik u kadru prije nego što se kodira u JPEG — njegovi pikseli nikad ne napuštaju uređaj. Zasloni u Jetpack Compose prema zadanim su postavkama u cijelosti maskirani (pozovite setKixoMask(false) na najvanjskijem ComposeView da uključite zaslon koji ste prethodno provjerili). Operateri u nadzornoj ploči pregledavaju player replaya uz vremensku crtu događaja.
Prikupljanje podataka
SDK bilježi podatke uključene u vašem projektu te događaje i svojstva koja šalje aplikacija.
Otklanjanje poteškoća
Kixo.diagnostics() vraća snapshot stanja SDK-a samo za čitanje — koristan na skrivenom debug zaslonu ili u smoke testu. Odgovara na pitanje „zašto mi događaji ne prolaze?” bez debuggera.
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 statePrisilno pokrenite flush iz testnog harnessa — blokira do timeoutMs dok čeka mrežni round-trip:
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 događaje screen_view i strukturirane zapise screen_visit s metapodacima o zadržavanju i toku, bez dodatne postave. Za Jetpack Compose Navigation pozovite Kixo.screen iz LaunchedEffect vezanog uz rutu — SDK će tada vidjeti 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 programiranje
Javna površina SDK-a mala je i prilagođena code completionu — sve metode nalaze se na singletonu Kixo, svaki Kotlin primjer u ovom vodiču počinje s import io.kixo.sdk.Kixo, a naš README sadrži blok "AI agent quick reference" koji alati poput Claude Code, Cursor i Codex mogu izravno zalijepiti u svoj kontekst. Ako vaš agent zapne, kanonski početak je:
// 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 gornji odjeljak pisan je imajući taj način rada na umu — importi su uvijek eksplicitni, tipovi su uvijek imenovani, a SDK singleton nikad nema alias. Dajte ovu stranicu svom agentu i pustite ga da odradi posao.