Ir á documentación

Android SDK

O SDK de Kixo para Android admite Kotlin 2.0+ e Java, require minSdk 24 (Android 7.0) e está compilado contra compileSdk 35. A túa app anfitrioa segue sendo responsable do seu propio targetSdk. Cunha única chamada a Kixo.configure no teu Application.onCreate, rexístranse automaticamente pantallas, toques, sesións, fallos e eventos do ciclo de vida. O seguimento de push require a ponte de FCM que se describe máis abaixo. O seguimento automático das solicitudes de rede non forma parte da versión actual de Android. O SDK tamén admite repetición de sesións, identidade e obxectivos.

Inicio rápido

Tres ficheiros. Engade o repositorio Maven, engade a dependencia e despois insire dúas liñas na túa subclase de Application.

Requisitos de compilación: compileSdk 35, minSdk 24, Kotlin 2.0+ ou Java, e bytecode de 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")
        }
    }
}

Nota

Con isto queda feita toda a integración de analítica. Os seguimentos automáticos estándar están activados por defecto; para push aínda precisas a ponte de FCM que se describe máis abaixo. Sobrescribe indicadores concretos con KixoConfiguration.Builder(...) só cando o necesites.

Engádeo á túa app

O repositorio Maven de Kixo está aloxado en GitHub Pages. Engádeo xunto con google() e mavenCentral() en 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")
        }
    }
}

Despois, declara a dependencia no módulo da túa app:

kotlin
// app/build.gradle.kts
dependencies {
    implementation("io.kixo:kixo-android-sdk:0.1.20")
}

Consello

android.permission.INTERNET e android.permission.ACCESS_NETWORK_STATE xa veñen incluídos no manifesto do SDK. Os permisos de notificación seguen dependendo da túa app e decláranse cando activas as funcións push.

Proxectos con varios módulos

A configuración implementation de Gradle é non transitiva: declarar implementation("io.kixo:kixo-android-sdk:0.1.20") nun módulo de biblioteca (por exemplo, :core_domain) NON fai que Kixo sexa visible para :app nin para ningún outro consumidor. Hai dous patróns que funcionan; escolle un.

Patrón A: cada módulo que chama a Kixo declárao como dependencia (recomendado). Mantén o classpath de cada módulo no mínimo e evita recompilacións en cascada. Usa un catálogo de versións (libs.kixo.sdk) para cambiar a versión nun único lugar.

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
}

Patrón B: reexportar mediante api(...). É unha única declaración, pero a ABI pública do módulo de biblioteca pasa a incluír tipos de Kixo, así que calquera cambio de versión obriga a recompilar todos os módulos dependentes. Úsao só cando a biblioteca reutilice tipos de Kixo nas súas propias sinaturas públicas, por exemplo se devolve KixoDiagnostics desde unha función.

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
}

Aviso

Se durante a compilación ves Unresolved reference: Kixo nun módulo, ese módulo non declarou a súa propia dependencia do SDK. Engade a liña implementation anterior ou usa o patrón B.

Inicialización

Configura Kixo desde a túa subclase de Application: onCreate execútase antes de calquera activity, así que cada vista de pantalla, toque e evento do ciclo de vida queda rexistrado desde o primeiro fotograma. Rexistra Application no manifesto con 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",
        )
    }
}

Se precisas axustes máis finos —indicadores de auto-track, frecuencia de envío, mostraxe da repetición ou un host de API personalizado— crea KixoConfiguration explicitamente:

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)

Nota

Idempotente. Unha segunda chamada a configure desde o mesmo proceso é un no-op rexistrado como WARN: o SDK conserva a primeira configuración. Os eventos que o teu singleton de auth poña en cola antes de que antes configure estea dispoñible gárdanse nun buffer (límite: 50) e reenvíanse cando o SDK queda configurado, así que podes chamar a Kixo.identify(...) desde un global antes de que remate Application.onCreate.

Rexistrar eventos

Tres primitivas cobren a maior parte da instrumentación: track para os eventos, markGoal para os sinais de conversión e addBreadcrumb para o contexto que non forma parte dun evento.

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",
)

Consello

Os obxectivos clasifícanse. Os obxectivos marcados alimentan os funís de activación de Kixo e a tarefa diaria de detección de cambios: se o volume dun obxectivo cae un 70 % dunha semana para outra, aparecerá no dashboard coa insignia Require revisión. Usa markGoal para os poucos momentos que realmente importan e track para todo o demais.

Eventos estándar

Unha capa de conveniencia sobre Kixo.track para os eventos que Kixo recoñece polo nome: claves de cadea literais que o detector de eventos estándar do backend identifica. Tes validación en compilación da forma das propiedades e unha única fonte de verdade para os nomes.

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)

Identificar usuarios

Vincula os eventos posteriores a un ID de usuario estable e a un conxunto de trazos. A unión entre anónimo e identificado faise en Kixo: os eventos capturados antes de identify atribúense retroactivamente ao mesmo usuario.

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()

⚠️ Coidado co símbolo $ en Kotlin. As claves estándar de identidade levan o prefixo $ ($email, $name, $first_name) e, nun literal de Kotlin, debe escapar o símbolo $ como "\$email". Se escribes "$email", interpolas a túa variable email, polo que o valor acaba silenciosamente como un trazo personalizado e nunca enche as columnas de correo ou nome en Audience. A solución máis sinxela é usar a sobrecarga tipada (SDK 0.1.13+), que non se pode escribir mal: Kixo.setUserProperty(StandardProperty.EMAIL, email).

Etiquetar un usuario para segmentación

Usa setUserProperty cun valor boolean para engadir ao usuario unha etiqueta simple de si/non. A etiqueta mantense entre lanzamentos e serve para segmentos, campañas de correo e consultas de chat, sen ningunha configuración adicional máis alá da chamada ao 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",
))

As propiedades persisten mediante SharedPreferences entre lanzamentos e engádense automaticamente a todos os eventos saíntes. No chat, podes dicir cousas como "enviar un correo electrónico de benvida aos usuarios onde subscribe sexa true"; Kixo créache o segmento e prepara o borrador do modelo. Límpanse con Kixo.reset().

Catálogo estándar de propiedades

As claves de propiedade reservadas levan o prefixo $ para separarse dos teus atributos personalizados. O catálogo de Kixo inclúe 37 claves repartidas en 3 paquetes universais (identidade, xeografía e ciclo de vida) e 5 paquetes verticais B2B (subscrición, e-commerce, media, marketplace e fidelización). Define as que se apliquen ao teu produto: o dashboard adáptase e só mostra os paquetes que estean cubertos.

Identidade

Sempre relevante. Define as columnas da cabeceira do perfil.

ClaveTipoDescrición
$emailcadeaCorreo electrónico principal, a miúdo usado como clave de fusión para unir identidades.
$phonecadeaNúmero de teléfono E.164.
$namecadeaNome completo para mostrar.
$first_namecadeaNome.
$last_namecadeaApelidos.
$avatar_urlcadeaURL completa da imaxe de avatar do usuario.

Geo

Contexto xeográfico.

ClaveTipoDescrición
$countrycadeaCódigo de país segundo ISO 3166.
$citycadeaNome da cidade.
$regioncadeaEstado ou provincia.
$timezonecadeaZona IANA como America/Los_Angeles.
$languagecadeaEtiqueta IETF como en ou ru-RU.
$localecadeaIdentificador de configuración rexional completo.

Ciclo de vida

Cando o vimos.

ClaveTipoDescrición
$createdISO8601Momento do rexistro ou da creación da conta.
$last_seenISO8601Momento da última interacción.

Subscrición

Defíneo se o teu produto ten plans.

ClaveTipoDescrición
$plancadeaSlug do nivel: free, pro, enterprise.
$subscription_statuscadeaactive / trial / cancelled / past_due.
$trial_endsISO8601Cando caduca a proba actual.
$mrrnúmeroIngresos recorrentes mensuais na moeda da conta.
$subscription_startedISO8601Cando comezou a subscrición actual.

E-commerce

Defíneo se vendes produtos.

ClaveTipoDescrición
$lifetime_ordersnúmeroNúmero de pedidos completados.
$lifetime_revenuenúmeroGasto total.
$aovnúmeroValor medio do pedido.
$last_purchaseISO8601Compra completada máis recente.
$first_purchaseISO8601Primeira compra completada.
$cart_abandoned_countnúmeroNúmero total de abandonos do carriño.

Media

Defíneo se publicas contido.

ClaveTipoDescrición
$content_tiercadeafree / premium / paid.
$subscribed_categoriesCadea CSV ou arrayCategorías que segue o usuario.
$watch_time_totalnúmeroTempo total de reprodución en segundos.
$last_playedISO8601Inicio de reprodución máis recente.

Marketplace

Defíneo se o teu produto é unha plataforma de dúas partes.

ClaveTipoDescrición
$seller_tiercadeaSlug do nivel do vendedor.
$buyer_tiercadeaSlug do nivel no lado comprador.
$listings_countnúmeroAnuncios activos do usuario.
$reviews_countnúmeroValoracións recibidas polo usuario.
$verifiedbooleanEstado de KYC.

Fidelización

Defíneo se tes programas de participación e recompensas.

ClaveTipoDescrición
$loyalty_pointsnúmeroSaldo actual de puntos canxeables.
$vip_levelcadeaSlug do nivel VIP.
$referral_countnúmeroReferencias completadas con éxito atribuídas a este usuario.

Consello

Non ves o teu patrón? Usa claves simples para os atributos personalizados. Aparecen no panel Custom Traits do dashboard sen contaminar as columnas do perfil. Os 5 paquetes verticais de enriba son propostas orientadas ás formas B2B máis habituais; a terminoloxía específica de cada cliente (por exemplo, shipping_plan) queda sen prefixo.

Superpropiedades

Pares clave/valor por sesión que se engaden automaticamente a todos os eventos saíntes. A diferenza dos trazos identify, que describen a identidade, as superpropiedades describen o contexto da sesión: a variante A/B activa, o flavor da compilación ou as feature flags activadas. Mantéñense entre lanzamentos e límpanse con reset(). Se hai conflito, sempre prevalecen as properties do evento en track.

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()

Notificacións push

Hai dúas vías de integración. Escolle a A se usas FCM e queres a configuración funcional máis curta; escolle a B se xa tes un FirebaseMessagingService personalizado que non podes reestruturar ou se queres controlar explicitamente que entregas de FCM ve Kixo.

Opción A: estender KixoFirebaseMessagingService (seguimento automático)

Subclasifica KixoFirebaseMessagingService e chama a super.onMessageReceived(...) desde o teu override: Kixo emite automaticamente push_received (payload visible) ou push_silent (só datos). A clase base tamén xestiona o rexistro de onNewToken se non o sobrescribes. O rexistro de AndroidManifest.xml non cambia respecto a un servizo FCM normal.

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
    }
}

Nota

Kixo compila esta clase opcional contra Firebase Messaging, pero non engade Firebase á túa app de forma transitiva. O SDK declara Firebase como compileOnly; se a túa app escolle esta opción, xa debe depender de firebase-messaging, igual que calquera receiver de FCM.

Opción B: chamar á API manual desde o teu propio servizo FCM

Rexistra o teu token de FCM en Kixo mediante FirebaseMessagingService.onNewToken e despois rexistra cada entrega de forma explícita. Usa esta vía se queres que Kixo vexa só unha parte das entregas de FCM. En Android, a entrega só admite FCM polo momento.

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 non ofrece un gancho universal do ciclo de vida para as aperturas, os descartes ou os botóns de acción das notificacións. Reenvía eses sinais desde os intents ou receivers de notificación que cree a túa app:

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

Reprodución de sesións

Reproduce unha reconstrución visual real do que viu o usuario. En cada captura, o SDK codifica un fotograma comprimido da pantalla —unha imaxe JPEG— xunto cunha instantánea estrutural da xerarquía de vistas e sobe ambas as dúas cousas, para que o reprodutor do dashboard poida ofrecer unha reprodución precisa a nivel de píxel xunto coa cronoloxía de interaccións. Configura a repetición do proxecto en Panel → Configuración → Repetición de sesións. O SDK le e actualiza automaticamente esa política do proxecto, incluídos o enmascaramento, os modos de captura e o permiso para subir por rede móbil.

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)

Se a subida por rede móbil está desactivada, a repetición en cola queda á espera dunha rede permitida.

Consello

Enmascara antes de subir. Kixo captura píxeles, así que o enmascaramento aplícase antes de que nada saia do dispositivo. Os campos de contrasinal e correo electrónico detéctanse e ocúltanse automaticamente; o texto das instantáneas estruturais pasa por un filtro de PII; e calquera vista que marques con setKixoMask(true) rasterízase como un rectángulo opaco no fotograma antes de codificar o JPEG, así que os seus píxeles nunca saen do dispositivo. As pantallas de Jetpack Compose enmáscaranse enteiras por defecto (chama a setKixoMask(false) no ComposeView máis externo para incluír unha pantalla que xa revisaches). No dashboard, os operadores revisan o reprodutor da repetición xunto coa cronoloxía de eventos.

Recollida de datos

O SDK captura os datos activados no proxecto e os eventos e propiedades que envía a túa aplicación.

Depuración

Kixo.diagnostics() devolve unha instantánea de só lectura do estado do SDK. É útil nunha pantalla oculta de depuración ou nunha proba de fume. Responde a "por que non están entrando os meus eventos?" sen necesidade de depurador.

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

Forza un flush desde o teu contorno de probas: bloqueará ata timeoutMs mentres espera unha ida e volta de rede:

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)

Compose Navigation

As rutas de Activity / Fragment xeran eventos screen_view inmediatos e rexistros estruturados de screen_visit con metadatos de permanencia e fluxo sen configuración adicional. En Jetpack Compose Navigation, dispara Kixo.screen desde un LaunchedEffect indexado pola ruta; así o SDK verá un evento por destino, independentemente do número de recomposicións.

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()
        }
    }
}

Axentes de programación con AI

A API pública do SDK é pequena e está deseñada para funcionar ben co autocompletado: todos os métodos están no singleton Kixo, todos os exemplos de Kotlin desta guía comezan con import io.kixo.sdk.Kixo e o noso README inclúe un bloque "AI agent quick reference" que ferramentas como Claude Code, Cursor e Codex poden pegar directamente no contexto. Se o teu axente se atasca, este é o punto de partida canónico:

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

Nota

Todas as seccións anteriores están escritas pensando nese fluxo de traballo: as importacións son sempre explícitas, os tipos sempre aparecen co seu nome e o singleton do SDK nunca se aliasa. Pásalle esta páxina ao teu axente e deixa que traballe.