Salt la documentație

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:

kotlin
// 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:

kotlin
// 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.

kotlin
// :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).

kotlin
// :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 ApplicationonCreate 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".

kotlin
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:

kotlin
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.

kotlin
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.

kotlin
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.

kotlin
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.

kotlin
// 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.

CheieTipDescriere
$emailșir de caractereAdresa principală de e-mail, folosită adesea ca cheie de unificare a identității.
$phoneșir de caractereNumăr de telefon în format E.164.
$nameșir de caractereNumele complet afișat.
$first_nameșir de caracterePrenume.
$last_nameșir de caractereNume de familie.
$avatar_urlșir de caractereURL-ul complet al imaginii de avatar a utilizatorului.

Geo

Context geografic.

CheieTipDescriere
$countryșir de caractereCod de țară ISO 3166.
$cityșir de caractereNumele orașului.
$regionșir de caractereStat sau provincie.
$timezoneșir de caractereZonă IANA precum America/Los_Angeles.
$languageșir de caractereEtichetă IETF precum en sau ru-RU.
$localeșir de caractereIdentificator complet de localizare.

Ciclu de viață

Când l-am văzut.

CheieTipDescriere
$createdISO8601Momentul înregistrării sau al creării contului.
$last_seenISO8601Ora ultimei interacțiuni.

Abonament

Folosește-l dacă produsul tău are planuri.

CheieTipDescriere
$planșir de caractereSlug-ul nivelului — free, pro, enterprise.
$subscription_statusșir de caractereactive / trial / cancelled / past_due.
$trial_endsISO8601Când expiră perioada de probă curentă.
$mrrnumărVenitul recurent lunar, în moneda contului.
$subscription_startedISO8601Când a început abonamentul curent.

Comerț electronic

Folosește-l dacă vinzi produse.

CheieTipDescriere
$lifetime_ordersnumărNumărul de comenzi finalizate.
$lifetime_revenuenumărCheltuieli totale.
$aovnumărValoarea medie a comenzii.
$last_purchaseISO8601Cea mai recentă achiziție finalizată cu succes.
$first_purchaseISO8601Prima achiziție reușită.
$cart_abandoned_countnumărNumărul total de abandonuri de coș.

Media

Folosește-l dacă publici conținut.

CheieTipDescriere
$content_tierșir de caracterefree / premium / paid.
$subscribed_categoriesșir CSV sau tablouCategoriile urmărite de utilizator.
$watch_time_totalnumărTimpul total de vizionare, în secunde.
$last_playedISO8601Cea mai recentă pornire a redării.

Marketplace

Folosește-l dacă produsul tău este o platformă cu două laturi.

CheieTipDescriere
$seller_tierșir de caractereSlug-ul nivelului pe partea vânzătorului.
$buyer_tierșir de caractereSlug-ul nivelului de pe partea cumpărătorului.
$listings_countnumărListări active deținute de utilizator.
$reviews_countnumărRecenziile primite de utilizator.
$verifiedbooleanStare KYC.

Loialitate

Folosește-l pentru programe de engagement și recompense.

CheieTipDescriere
$loyalty_pointsnumărSoldul curent de puncte care pot fi folosite.
$vip_levelșir de caractereSlug-ul nivelului VIP.
$referral_countnumărRecomandă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.

kotlin
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.

kotlin
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.

kotlin
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:

kotlin
import io.kixo.sdk.Kixo

Kixo.logPushOpened(payload = pushPayload)            // open
Kixo.logPushOpened(payload = pushPayload, actionId = "reply")  // action-button tap
Kixo.logPushDismissed(payload = pushPayload)         // swipe-away

Reluarea 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ă.

kotlin
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.

kotlin
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 state

Forțează un flush din infrastructura ta de test — blochează până la timeoutMs pentru un drum dus-întors în rețea:

kotlin
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.

kotlin
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:

kotlin
// 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.