SDK Android
SDK-ul Kixo pentru Android suportă Kotlin 2.0+ și Java, necesită minSdk 24 (Android 7.0) și este compilat pentru compileSdk 35. Aplicația gazdă rămâne responsabilă pentru propriul targetSdk. Un singur apel Kixo.configure în Application.onCreate urmărește automat ecranele, atingerile, sesiunile, crash-urile și evenimentele de ciclu de viață. Pentru urmărirea notificărilor push ai nevoie de puntea FCM descrisă mai jos. Urmărirea automată a cererilor de rețea nu face parte din versiunea actuală pentru Android. SDK-ul suportă și session replay, identitate și obiective.
Pornire rapidă
Trei fișiere. Adaugă repository-ul Maven, adaugă dependența, apoi pune două linii în subclasa ta Application.
Cerințe de build: compileSdk 35, minSdk 24, Kotlin 2.0+ sau Java și bytecode Java 17.
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url = uri("https://raw.githubusercontent.com/kixoio/kixo-android-sdk/main/repo")
}
}
}Notă
Asta este toată integrarea de analytics. Urmăritoarele automate standard sunt active implicit; pentru push ai în continuare nevoie de puntea FCM de mai jos. Suprascrie opțiunile individuale cu KixoConfiguration.Builder(...) doar când este nevoie.
Adaugă în aplicație
Repository-ul Maven pentru Kixo este găzduit pe GitHub Pages. Adaugă-l alături de google() și mavenCentral() în 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")
}
}
}Apoi declară dependența în modulul aplicației:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Sfat
android.permission.INTERNET și android.permission.ACCESS_NETWORK_STATE sunt incluse în manifestul SDK-ului. Permisiunile pentru notificări rămân în responsabilitatea aplicației și se declară când activezi funcțiile de push.
Proiecte cu mai multe module
Configurația Gradle implementation este nu este tranzitivă: dacă declari implementation("io.kixo:kixo-android-sdk:0.1.20") într-un modul de bibliotecă (de exemplu :core_domain), Kixo NU devine vizibil pentru :app sau pentru orice alt consumator. Sunt două variante corecte — alege una.
Varianta A — fiecare modul care apelează Kixo îl declară explicit (recomandat). Menține classpath-ul fiecărui modul cât mai mic și evită rebuild-urile în cascadă. Folosește un version catalog (libs.kixo.sdk) ca să modifici versiunea într-un singur loc.
// :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
}Varianta B — reexpui prin api(...). Ai o singură declarație, dar ABI-ul public al modulului de bibliotecă include acum tipuri Kixo — orice schimbare de versiune reconstruiește toate modulele din aval. Folosește asta doar când biblioteca reutilizează tipuri Kixo în propriile semnături publice (de exemplu, returnează KixoDiagnostics dintr-o funcție).
// :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
}Avertisment
Dacă la compilare vezi Unresolved reference: Kixo într-un modul, acel modul nu are propria dependență de SDK — adaugă linia implementation de mai sus sau folosește varianta B.
Inițializare
Configurează Kixo din subclasa ta Application — onCreate rulează înaintea oricărei activități, astfel încât fiecare afișare de ecran, atingere și eveniment de ciclu de viață să fie capturate încă din primul cadru. Înregistrează Application în manifest cu 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",
)
}
}Pentru reglaje mai fine — opțiuni de urmărire automată, ritmul de flush, eșantionarea replay-ului, host API personalizat — construiește explicit un 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)Notă
Idempotent. Al doilea apel configure din același proces este un no-op logat la nivel WARN — SDK-ul păstrează prima configurare. Evenimentele puse în coadă de singletonul tău de autentificare înainte ca înainte configure să fie disponibil sunt tamponate (limită 50) și redate după ce SDK-ul este inițializat, astfel încât poți apela Kixo.identify(...) dintr-un global înainte să se termine Application.onCreate.
Urmărirea evenimentelor
Cea mai mare parte a instrumentării se bazează pe trei primitive: track pentru evenimente, markGoal pentru semnale de conversie și addBreadcrumb pentru context non-eveniment.
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",
)Sfat
Obiectivele au niveluri. Obiectivele marcate alimentează pâlniile de activare din Kixo și jobul zilnic de detectare a schimbărilor — un obiectiv al cărui volum scade cu 70% de la o săptămână la alta apare în dashboard cu badge-ul Necesită aprobare. Folosește markGoal pentru puținele momente care contează; track pentru tot restul.
Evenimente standard
Un strat de conveniență peste Kixo.track pentru evenimentele pe care Kixo le recunoaște după nume — chei string exacte, potrivite direct de detectorul de evenimente standard din backend. Oferă validare la compilare pentru forma proprietăților și o singură sursă de adevăr pentru denumiri.
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)Identifică utilizatorii
Leagă evenimentele viitoare de un ID de utilizator stabil și de un set de atribute. Asocierea dintre utilizatorul anonim și cel identificat se face în Kixo — evenimentele capturate înainte de identify sunt atribuite retroactiv aceluiași utilizator.
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()⚠️ Capcana semnului dolar în Kotlin. Cheile standard de identitate au prefixul $ ($email, $name, $first_name) — iar într-un literal Kotlin trebuie să escapezi semnul dolar ca "\$email". Dacă scrii "$email", faci interpolare cu variabila ta email, iar valoarea ajunge pe tăcute ca atribut personalizat și nu completează niciodată coloanele de e-mail / nume din Audience. Cea mai simplă soluție: folosește suprasarcina tipizată (SDK 0.1.13+), unde nu ai cum să greșești: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Etichetează un utilizator pentru segmentare
Folosește setUserProperty cu o valoare boolean pentru a atașa utilizatorului un marcaj simplu de tip da/nu. Marcajul persistă între lansări și poate fi folosit în segmente, campanii de e-mail și interogări în chat — fără configurare suplimentară în afară de apelul 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",
))Proprietățile se păstrează prin SharedPreferences între lansări și se atașează automat fiecărui eveniment trimis. În chat poți spune, de exemplu, "trimite un email de bun venit utilizatorilor unde subscribe este true" — Kixo îți construiește segmentul și îți pregătește șablonul. Se șterg la Kixo.reset().
Catalogul standard de proprietăți
Cheile de proprietăți rezervate folosesc prefixul $, ca să nu intre în conflict cu trăsăturile tale personalizate. Catalogul Kixo acoperă 37 de chei în 3 pachete universale (identitate, geo, ciclu de viață) și 5 pachete verticale B2B (abonamente, e-commerce, media, marketplace, loialitate). Setează doar ce se aplică produsului tău — dashboardul se adaptează și afișează doar pachetele pe care le populezi.
Identitate
Întotdeauna relevant. Definește coloanele din antetul profilului.
| Cheie | Tip | Descriere |
|---|---|---|
$email | șir de caractere | Adresa principală de e-mail, folosită adesea ca cheie de unificare a identității. |
$phone | șir de caractere | Număr de telefon în format E.164. |
$name | șir de caractere | Numele complet afișat. |
$first_name | șir de caractere | Prenume. |
$last_name | șir de caractere | Nume de familie. |
$avatar_url | șir de caractere | URL-ul complet al imaginii de avatar a utilizatorului. |
Geo
Context geografic.
| Cheie | Tip | Descriere |
|---|---|---|
$country | șir de caractere | Cod de țară ISO 3166. |
$city | șir de caractere | Numele orașului. |
$region | șir de caractere | Stat sau provincie. |
$timezone | șir de caractere | Zonă IANA precum America/Los_Angeles. |
$language | șir de caractere | Etichetă IETF precum en sau ru-RU. |
$locale | șir de caractere | Identificator complet de localizare. |
Ciclu de viață
Când l-am văzut.
| Cheie | Tip | Descriere |
|---|---|---|
$created | ISO8601 | Momentul înregistrării sau al creării contului. |
$last_seen | ISO8601 | Ora ultimei interacțiuni. |
Abonament
Folosește-l dacă produsul tău are planuri.
| Cheie | Tip | Descriere |
|---|---|---|
$plan | șir de caractere | Slug-ul nivelului — free, pro, enterprise. |
$subscription_status | șir de caractere | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | Când expiră perioada de probă curentă. |
$mrr | număr | Venitul recurent lunar, în moneda contului. |
$subscription_started | ISO8601 | Când a început abonamentul curent. |
Comerț electronic
Folosește-l dacă vinzi produse.
| Cheie | Tip | Descriere |
|---|---|---|
$lifetime_orders | număr | Numărul de comenzi finalizate. |
$lifetime_revenue | număr | Cheltuieli totale. |
$aov | număr | Valoarea medie a comenzii. |
$last_purchase | ISO8601 | Cea mai recentă achiziție finalizată cu succes. |
$first_purchase | ISO8601 | Prima achiziție reușită. |
$cart_abandoned_count | număr | Numărul total de abandonuri de coș. |
Media
Folosește-l dacă publici conținut.
| Cheie | Tip | Descriere |
|---|---|---|
$content_tier | șir de caractere | free / premium / paid. |
$subscribed_categories | șir CSV sau tablou | Categoriile urmărite de utilizator. |
$watch_time_total | număr | Timpul total de vizionare, în secunde. |
$last_played | ISO8601 | Cea mai recentă pornire a redării. |
Marketplace
Folosește-l dacă produsul tău este o platformă cu două laturi.
| Cheie | Tip | Descriere |
|---|---|---|
$seller_tier | șir de caractere | Slug-ul nivelului pe partea vânzătorului. |
$buyer_tier | șir de caractere | Slug-ul nivelului de pe partea cumpărătorului. |
$listings_count | număr | Listări active deținute de utilizator. |
$reviews_count | număr | Recenziile primite de utilizator. |
$verified | boolean | Stare KYC. |
Loialitate
Folosește-l pentru programe de engagement și recompense.
| Cheie | Tip | Descriere |
|---|---|---|
$loyalty_points | număr | Soldul curent de puncte care pot fi folosite. |
$vip_level | șir de caractere | Slug-ul nivelului VIP. |
$referral_count | număr | Recomandări reușite atribuite acestui utilizator. |
Sfat
Nu-ți regăsești modelul? Folosește chei simple pentru atribute personalizate. Ele apar în panoul Custom Traits din dashboard fără să încarce coloanele de profil. Cele 5 pachete verticale de mai sus sunt presupuneri informate despre cele mai comune structuri B2B — terminologia specifică fiecărui client (de exemplu shipping_plan) rămâne fără prefix.
Super-proprietăți
Perechi cheie/valoare la nivel de sesiune, atașate automat fiecărui eveniment trimis. Sunt diferite de atributele identify (care descriu identitatea); super-proprietățile descriu contextul sesiunii — varianta A/B activă, flavor-ul de build, feature flag-urile activate. Persistă între lansări și se șterg la reset(). În caz de conflict, properties per eveniment din track au întotdeauna prioritate.
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()Notificări push
Ai două căi de integrare. Alege A dacă folosești FCM și vrei cea mai scurtă configurare funcțională; alege B dacă ai deja un FirebaseMessagingService personalizat pe care nu îl poți restructura sau dacă vrei control explicit asupra livrărilor FCM pe care le vede Kixo.
Opțiunea A — extinzi KixoFirebaseMessagingService (urmărire automată)
Extinde KixoFirebaseMessagingService și apelează super.onMessageReceived(...) din override — Kixo emite automat push_received (payload vizibil) sau push_silent (doar date). Clasa de bază gestionează și înregistrarea onNewToken dacă nu o suprascrii. Înregistrarea AndroidManifest.xml rămâne neschimbată față de un serviciu FCM obișnuit.
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
}
}Notă
Kixo compilează această clasă opțională împotriva Firebase Messaging, dar nu adaugă Firebase tranzitiv în aplicația ta. SDK-ul declară Firebase ca compileOnly; dacă alegi această opțiune, aplicația trebuie deja să depindă de firebase-messaging, la fel ca în cazul oricărui receiver FCM.
Opțiunea B — apelezi manual API-ul din propriul serviciu FCM
Înregistrează tokenul FCM în Kixo prin FirebaseMessagingService.onNewToken, apoi înregistrează explicit fiecare livrare. Alege această variantă dacă vrei ca Kixo să vadă doar un subset al livrărilor FCM. Pe Android, urmărirea livrării acceptă momentan doar 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 nu oferă un hook universal de lifecycle pentru deschiderea notificărilor, închiderea lor sau butoanele de acțiune. Redirecționează aceste semnale din intent-urile sau receiver-ele de notificare pe care le creează aplicația ta:
import io.kixo.sdk.Kixo
Kixo.logPushOpened(payload = pushPayload) // open
Kixo.logPushOpened(payload = pushPayload, actionId = "reply") // action-button tap
Kixo.logPushDismissed(payload = pushPayload) // swipe-awayReluarea sesiunii
Redă o reconstrucție vizuală fidelă a ceea ce a văzut utilizatorul. La fiecare captură, SDK-ul codifică un cadru comprimat al ecranului (o imagine JPEG) împreună cu un instantaneu structural al ierarhiei de view-uri și le încarcă pe ambele, astfel încât playerul din dashboard să poată reda imaginea cu fidelitate la nivel de pixel alături de cronologia interacțiunilor. Configurează replay-ul proiectului în Panou de control → Setări → Redare sesiune. SDK-ul citește și reîmprospătează automat politica proiectului, inclusiv mascarea, modurile de captură și permisiunea de încărcare prin rețea mobilă.
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)Când încărcarea prin rețea mobilă este dezactivată, replay-urile din coadă așteaptă o rețea permisă.
Sfat
Maschează înainte de încărcare. Kixo capturează pixeli, așa că mascarea rulează înainte să părăsească orice date dispozitivul. Câmpurile de parolă și e-mail sunt detectate și redactate automat; textul din instantaneele structurale trece printr-un filtru PII; iar orice view marcat cu setKixoMask(true) este rasterizat ca un dreptunghi opac în cadru înainte codificarea JPEG — pixelii lui nu părăsesc niciodată dispozitivul. Ecranele Jetpack Compose sunt mascate integral în mod implicit (apelează setKixoMask(false) pe ComposeView cel mai exterior pentru a include un ecran pe care l-ai verificat deja). Operatorii verifică playerul de replay împreună cu cronologia evenimentelor din dashboard.
Colectarea datelor
SDK-ul captează datele activate în proiectul tău, precum și evenimentele și proprietățile trimise de aplicație.
Depanare
Kixo.diagnostics() returnează o imagine doar în citire a stării de sănătate a SDK-ului — utilă într-un ecran ascuns de depanare sau într-un smoke test. Îți spune „de ce nu curg evenimentele?” fără să deschizi debuggerul.
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 stateForțează un flush din infrastructura ta de test — blochează până la timeoutMs pentru un drum dus-întors în rețea:
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)Navigare în Compose
Rutele Activity / Fragment produc imediat evenimente screen_view și înregistrări structurate screen_visit, cu metadate despre timpul petrecut și flux, fără configurare suplimentară. Pentru Jetpack Compose Navigation, trimite Kixo.screen dintr-un LaunchedEffect indexat după rută — astfel, SDK-ul vede un singur eveniment pentru fiecare destinație, indiferent de numărul de recompuneri.
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()
}
}
}Agenți AI pentru programare
Suprafața publică a SDK-ului este mică și gândită pentru autocompletare: toate metodele sunt pe singletonul Kixo, toate exemplele Kotlin din acest ghid încep cu import io.kixo.sdk.Kixo, iar README include un bloc „AI agent quick reference” pe care instrumente precum Claude Code, Cursor și Codex îl pot lipi direct în context. Dacă agentul se blochează, punctul de pornire canonic este:
// 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."Notă
Fiecare secțiune de mai sus a fost scrisă pentru acest mod de lucru — importurile sunt mereu explicite, tipurile sunt numite complet, iar singletonul SDK nu primește niciodată alias. Dă această pagină agentului tău și lasă-l să continue.