Android SDK
SDK Android i Kixo mbështet Kotlin 2.0+ dhe Java, kërkon minSdk 24 (Android 7.0) dhe është ndërtuar kundrejt compileSdk 35. Aplikacioni juaj host mbetet përgjegjës për targetSdk e vet. Një thirrje e vetme Kixo.configure në Application.onCreate gjurmon automatikisht ekranet, tap-et, sesionet, crash-et dhe ngjarjet e ciklit të jetës. Gjurmimi i push kërkon urën FCM të përshkruar më poshtë. Gjurmimi automatik i kërkesave të rrjetit nuk bën pjesë në versionin aktual Android. SDK mbështet gjithashtu replay të sesioneve, identitet dhe objektiva.
Nisje e shpejtë
Tre skedarë. Shtoni repo-n Maven, shtoni varësinë, pastaj vendosni dy rreshta në nënklasën tuaj Application.
Kërkesat e build-it: compileSdk 35, minSdk 24, Kotlin 2.0+ ose Java, dhe 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")
}
}
}Shënim
Kaq është i gjithë integrimi i analitikës. Auto-tracker-at standardë janë të aktivizuar si parazgjedhje; për push duhet ende ura FCM më poshtë. Mbishkruani flamuj individualë me KixoConfiguration.Builder(...) vetëm kur keni nevojë.
Shtojeni në aplikacionin tuaj
Repo-ja Maven e Kixo hostohet në GitHub Pages. Shtojeni krah google() dhe 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")
}
}
}Pastaj deklaroni varësinë në modulin e aplikacionit tuaj:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Këshillë
android.permission.INTERNET dhe android.permission.ACCESS_NETWORK_STATE përfshihen në manifestin e SDK. Lejet për njoftime mbeten nën kontrollin e aplikacionit tuaj dhe deklarohen vetëm kur aktivizoni funksionet push.
Projekte me shumë module
Konfigurimi implementation i Gradle është jo transitiv: deklarimi i implementation("io.kixo:kixo-android-sdk:0.1.20") në një modul library (p.sh. :core_domain) NUK e bën Kixo të dukshëm për :app apo për ndonjë konsumator tjetër. Ka dy modele që funksionojnë — zgjidhni njërin.
Pattern A — çdo modul që thërret Kixo e deklaron vetë. e mban classpath-in e çdo moduli sa më të vogël dhe shmang rindërtimet zinxhir. Përdorni një version catalog (libs.kixo.sdk) që versionin ta ndryshoni vetëm në një vend.
// :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
}Pattern B — riekспортojeni përmes api(...). Është vetëm një deklarim, por ABI publike e modulit library tani përfshin tipe Kixo — çdo rritje versioni rindërton të gjithë modulet që varen prej tij. Përdoreni vetëm kur library ripërdor tipe Kixo në nënshkrimet e veta publike (p.sh. kur një funksion kthen 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
}Paralajmërim
Nëse shihni Unresolved reference: Kixo në kohë kompilimi brenda një moduli, atij moduli i mungon varësia e vet ndaj SDK — shtoni rreshtin implementation më sipër ose përdorni Pattern B.
Inicializim
Konfigurojeni Kixo nga nënklasa juaj e Application — onCreate ekzekutohet para çdo activity-je, ndaj çdo shikim ekrani, tap dhe ngjarje e ciklit të jetës kapet që në kuadrin e parë. Regjistrojeni Application në manifest me 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",
)
}
}Për rregullime më të imëta (flamujt e auto-track, ritmi i flush, kampionimi i replay, host i personalizuar API), ndërtoni shprehimisht një 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)Shënim
Idempotent. Një thirrje e dytë e configure nga i njëjti proces është një no-op që regjistrohet si WARN — SDK mban konfigurimin e parë. Ngjarjet e futura në radhë nga singleton-i juaj i autentikimit para se para configure të kryhet ruhen në buffer (maksimumi 50) dhe ridërgohen sapo SDK të jetë lidhur, kështu që mund të thërrisni Kixo.identify(...) nga një global përpara se Application.onCreate të përfundojë.
Gjurmoni ngjarje
Tre primitive mbajnë pjesën më të madhe të instrumentimit tuaj: track për ngjarjet, markGoal për sinjalet e konvertimit dhe addBreadcrumb për kontekstin që nuk është ngjarje.
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",
)Këshillë
Objektivat vlerësohen sipas niveleve. Objektivat e shënuara ushqejnë hinkat e aktivizimit të Kixo dhe detyrën ditore cron për zbulimin e ndryshimeve — një objektiv, vëllimi i të cilit bie 70% nga java në javë, shfaqet në dashboard me etiketën Kërkon rishikim. Përdorni markGoal për ato pak momente që kanë vërtet rëndësi; track për gjithçka tjetër.
Ngjarje standarde
Shtresë lehtësuese mbi Kixo.track për ngjarjet që Kixo i njeh nga emri — çelësa string fiks që përputhen nga detektori i backend-it për ngjarjet standarde. Validim në compile-time i formës së vetive dhe një burim i vetëm i së vërtetës për emërtimin.
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)Identifiko përdoruesit
Lidhini ngjarjet që vijnë më pas me një user id të qëndrueshëm dhe me një grup traits. Kalimi nga anonim në përdorues të njohur bëhet në Kixo — ngjarjet e kapura para identify i atribuohen më pas të njëjtit përdorues.
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()⚠️ Kurthi i shenjës së dollarit në Kotlin. Çelësat standardë të identitetit kanë prefiksin $ ($email, $name, $first_name) — dhe në një literal Kotlin duhet ta escaponi shenjën e dollarit si "\$email". Nëse shkruani "$email", string-u interpolon variablën tuaj email, ndaj vlera përfundon pa u kuptuar si trait i personalizuar dhe nuk mbush kurrë kolonat Audience email / name. Zgjidhja më e thjeshtë është të përdorni overload-in e tipizuar (SDK 0.1.13+), që s’gaboheni dot: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Etiketo një përdorues për segmentim
Përdorni setUserProperty me një vlerë boolean për t’i shtuar përdoruesit një etiketë të thjeshtë po/jo. Etiketa ruhet mes hapjeve të aplikacionit dhe përdoret nga segmentet, fushatat me email dhe pyetjet në chat — pa asnjë konfigurim tjetër përtej thirrjes së 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",
))Vetitë ruhen përmes SharedPreferences mes hapjeve të aplikacionit dhe i bashkëngjiten automatikisht çdo ngjarjeje dalëse. Në chat mund të thoni gjëra si "dërgo një email mirëseardhjeje për përdoruesit ku subscribe është true" — Kixo e ndërton segmentin dhe ju përgatit draftin e shabllonit. Pastrohen me Kixo.reset().
Katalogu standard i vetive
Çelësat e rezervuar të vetive mbajnë prefiksin $, që të dallohen nga tiparet e tua të personalizuara. Katalogu i Kixo mbulon 37 çelësa në 3 paketa universale (identitet, gjeografi, cikël jete) dhe 5 paketa vertikale B2B (abonim, e-commerce, media, treg, besnikëri). Vendos vetëm ato që vlejnë për produktin tënd — dashboard-i përshtatet dhe shfaq vetëm paketat që ke plotësuar.
Identiteti
Gjithmonë e vlefshme. Përcakton kolonat e header-it të profilit.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$email | varg | Email-i kryesor, shpesh çelësi i bashkimit për lidhjen e identitetit. |
$phone | varg | Numër telefoni E.164. |
$name | varg | Emri i plotë i shfaqur. |
$first_name | varg | Emri. |
$last_name | varg | Mbiemri. |
$avatar_url | varg | URL-ja e plotë e imazhit të avatarit të përdoruesit. |
Geo
Kontekst gjeografik.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$country | varg | Kodi i vendit sipas ISO 3166. |
$city | varg | Emri i qytetit. |
$region | varg | Shtet ose provincë. |
$timezone | varg | Zonë IANA si America/Los_Angeles. |
$language | varg | Tag IETF si en ose ru-RU. |
$locale | varg | Identifikuesi i plotë i locale-it. |
Cikli i jetës
Kur e kemi parë.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$created | ISO8601 | Koha e regjistrimit ose e krijimit të llogarisë. |
$last_seen | ISO8601 | Koha e ndërveprimit të fundit. |
Abonim
Vendose nëse produkti yt ka plane.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$plan | varg | Slug-u i nivelit — free, pro, enterprise. |
$subscription_status | varg | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | Kur skadon prova aktuale. |
$mrr | numër | Të ardhurat mujore periodike në monedhën e llogarisë. |
$subscription_started | ISO8601 | Kur nisi abonimi aktual. |
E-commerce
Vendose nëse shet produkte.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$lifetime_orders | numër | Numri i porosive të përfunduara. |
$lifetime_revenue | numër | Shpenzimi total. |
$aov | numër | Vlera mesatare e porosisë. |
$last_purchase | ISO8601 | Blerja e fundit e suksesshme. |
$first_purchase | ISO8601 | Blerja e parë e suksesshme. |
$cart_abandoned_count | numër | Numri total i braktisjeve të shportës. |
Media
Vendose nëse publikon përmbajtje.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$content_tier | varg | free / premium / paid. |
$subscribed_categories | String CSV ose array | Kategoritë që ndjek përdoruesi. |
$watch_time_total | numër | Koha totale e shikimit në sekonda. |
$last_played | ISO8601 | Nisja më e fundit e riprodhimit. |
Treg
Vendose nëse je platformë me dy anë.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$seller_tier | varg | Slug-u i nivelit në anën e shitësit. |
$buyer_tier | varg | Slug-u i nivelit në anën e blerësit. |
$listings_count | numër | Listime aktive në pronësi të përdoruesit. |
$reviews_count | numër | Vlerësimet që ka marrë përdoruesi. |
$verified | boolean | Statusi KYC. |
Besnikëri
Vendose nëse ke programe angazhimi dhe shpërblimesh.
| Çelës | Lloji | Përshkrimi |
|---|---|---|
$loyalty_points | numër | Bilanci aktual i pikëve të përdorshme. |
$vip_level | varg | Slug-u i nivelit VIP. |
$referral_count | numër | Referime të suksesshme që i atribuohen këtij përdoruesi. |
Këshillë
Nuk e sheh modelin tënd? Përdor çelësa të thjeshtë për traits custom. Ato shfaqen te paneli Custom Traits në dashboard, pa ndotur kolonat e profilit. 5 paketat vertikale më sipër janë sugjerime të arsyetuara për format më të zakonshme B2B — terminologjia specifike e klientit (p.sh. shipping_plan) mbetet pa prefiks.
Super-properties
Çifte çelës/vlerë për sesionin, që i bashkëngjiten automatikisht çdo ngjarjeje dalëse. Ndryshe nga traits identify (që përshkruajnë identitetin), super-properties përshkruajnë kontekstin e sesionit — varianti aktiv A/B, build flavor, feature flags të aktivizuara. Ruhen mes hapjeve të aplikacionit; pastrohen me reset(). Në rast përplasjeje, properties për ngjarje në track kanë gjithmonë përparësi.
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()Njoftime push
Dy rrugë integrimi. Zgjidhni A nëse përdorni FCM dhe doni konfigurimin më të shkurtër funksional; zgjidhni B nëse keni tashmë një FirebaseMessagingService të personalizuar që nuk mund ta ristrukturoni ose nëse doni kontroll të qartë mbi cilat dorëzime FCM sheh Kixo.
Opsioni A — zgjeroni KixoFirebaseMessagingService (gjurmim automatik)
Krijoni një nënklasë të KixoFirebaseMessagingService dhe thërrisni super.onMessageReceived(...) nga override-i juaj — Kixo emeton automatikisht push_received (payload i dukshëm) ose push_silent (vetëm data). Klasa bazë merret edhe me regjistrimin onNewToken, nëse nuk e bëni override. Regjistrimi AndroidManifest.xml mbetet njësoj si te një shërbim normal FCM.
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
}
}Shënim
Kixo e kompilion këtë klasë opsionale kundrejt Firebase Messaging, por nuk e shton Firebase në aplikacionin tuaj në mënyrë transitore. SDK e deklaron Firebase si compileOnly; një aplikacion që zgjedh këtë opsion duhet të ketë tashmë varësi nga firebase-messaging, si çdo receiver FCM.
Opsioni B — thërrisni API-n manualisht nga shërbimi juaj FCM
Regjistrojeni token-in tuaj FCM te Kixo përmes FirebaseMessagingService.onNewToken, pastaj regjistroni shprehimisht çdo dorëzim. Përdoreni këtë rrugë kur doni që Kixo të shohë vetëm një pjesë të dorëzimeve FCM. Dorëzimi në Android mbështet aktualisht vetëm 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 nuk ofron një hook universal të lifecycle për hapjet e njoftimeve, mbylljet ose butonat e veprimit. Përcillini këto sinjale nga intent-et ose receiver-at e njoftimeve që krijon aplikacioni juaj:
import io.kixo.sdk.Kixo
Kixo.logPushOpened(payload = pushPayload) // open
Kixo.logPushOpened(payload = pushPayload, actionId = "reply") // action-button tap
Kixo.logPushDismissed(payload = pushPayload) // swipe-awayRiprodhim sesioni
Riprodhoni një rindërtim real dhe vizual të asaj që pa përdoruesi. Në çdo kapje, SDK kodon një kuadër të ngjeshur të ekranit (një imazh JPEG) bashkë me një pamje strukturore të hierarkisë së view-ve, dhe i ngarkon të dyja — që luajtësi në dashboard të japë një riprodhim me saktësi pikseli krahas kronologjisë së ndërveprimeve. Konfiguroni replay për projektin te Paneli → Cilësimet → Riluajtja e sesionit. SDK e lexon dhe e rifreskon automatikisht atë politikë projekti, përfshirë maskimin, mënyrat e kapjes dhe lejen për ngarkim përmes rrjetit celular.
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)Kur ngarkimi përmes rrjetit celular është i çaktivizuar, replay i futur në radhë pret derisa të ketë një rrjet të lejuar.
Këshillë
Maskoni para ngarkimit. Kixo kap pikselë, ndaj maskimi zbatohet para se të largohet çfarëdo nga pajisja. Fushat e fjalëkalimit dhe email-it zbulohen dhe redaktohen automatikisht; teksti në pamjet strukturore kalon përmes një filtri PII; dhe çdo view që e shënoni me setKixoMask(true) rasterizohet si drejtkëndësh opak në kuadrin para se të kodohet JPEG — pikselët e tij nuk dalin kurrë nga pajisja. Ekranet Jetpack Compose maskohen tërësisht si parazgjedhje (thirrni setKixoMask(false) te ComposeView më i jashtëm për të përfshirë një ekran që e keni audituar). Operatorët e pastrojnë riprodhimin edhe në panelin e riprodhimit, edhe në kronologjinë e ngjarjeve në dashboard.
Mbledhja e të dhënave
SDK kap të dhënat që janë aktivizuar në projektin tuaj, si edhe ngjarjet dhe vetitë që dërgon aplikacioni juaj.
Diagnostikim
Kixo.diagnostics() kthen një pamje vetëm për lexim të gjendjes së SDK — e dobishme në një ekran të fshehur debug ose në një smoke test. I jep përgjigje pyetjes “pse nuk po kalojnë ngjarjet?” pa hapur debugger.
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 stateDetyroni një flush nga test harness-i juaj — bllokon deri në timeoutMs për një vajtje-ardhje rrjeti:
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
Rrugët e Activity / Fragment prodhojnë menjëherë ngjarje screen_view dhe regjistrime të strukturuara screen_visit me metadatë për kohëqëndrim dhe rrjedhë, pa konfigurim shtesë. Për Jetpack Compose Navigation, dërgoni Kixo.screen nga një LaunchedEffect i lidhur me route-in — SDK pastaj sheh një ngjarje për çdo destinacion, pavarësisht sa herë rindërtohet composable-i.
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()
}
}
}Agjentë AI për kodim
Sipërfaqja publike e SDK është e vogël dhe e ndërtuar për code-completion — çdo metodë është te singleton-i Kixo, çdo shembull Kotlin në këtë udhëzues nis me import io.kixo.sdk.Kixo, dhe README ynë përfshin një bllok “AI agent quick reference” që mjete si Claude Code, Cursor dhe Codex mund ta fusin drejtpërdrejt në kontekst. Nëse agjenti juaj ngec, pika kanonike e nisjes është:
// 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."Shënim
Çdo seksion më sipër është shkruar duke pasur parasysh këtë rrjedhë pune — import-et janë gjithmonë të shprehura qartë, tipet emërtohen gjithmonë dhe singleton-i i SDK nuk alias-ohet kurrë. Jepjani këtë faqe agjentit tuaj dhe lëreni të vazhdojë prej andej.