Android SDK
Kixo Android SDK падтрымлівае Kotlin 2.0+ і Java, патрабуе minSdk 24 (Android 7.0) і сабраны супраць compileSdk 35. Хост-праграма па-ранейшаму сама адказвае за свой targetSdk. Адзін выклік Kixo.configure у вашым Application.onCreate аўтаматычна адсочвае экраны, націскі, сесіі, збоі і падзеі жыццёвага цыклу. Для адсочвання push патрэбны мост FCM, апісаны ніжэй. Аўтаадсочванне сеткавых запытаў пакуль не ўваходзіць у бягучы Android-рэліз. SDK таксама падтрымлівае replay сесій, ідэнтычнасць і мэты.
Хуткі старт
Тры файлы. Дадайце Maven-рэпазіторый, дадайце залежнасць, а потым устаўце два радкі ў свой падклас Application.
Патрабаванні да зборкі: compileSdk 35, minSdk 24, Kotlin 2.0+ або Java, і 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")
}
}
}Заўвага
На гэтым інтэграцыя аналітыкі завершана. Стандартныя auto-tracker-ы ўключаныя па змаўчанні; для push усё яшчэ патрэбны мост FCM ніжэй. Пераазначайце асобныя сцягі праз KixoConfiguration.Builder(...) толькі пры неабходнасці.
Дадаць у праграму
Maven-рэпазіторый Kixo размешчаны на GitHub Pages. Дадайце яго побач з google() і mavenCentral() у 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")
}
}
}Пасля гэтага аб’явіце залежнасць у модулі праграмы:
// app/build.gradle.kts
dependencies {
implementation("io.kixo:kixo-android-sdk:0.1.20")
}Парада
android.permission.INTERNET і android.permission.ACCESS_NETWORK_STATE ужо ўключаныя ў маніфест SDK. Дазволы на апавяшчэнні застаюцца пад кантролем вашай праграмы і аб’яўляюцца, толькі калі вы ўключаеце функцыі push.
Шматмодульныя праекты
Канфігурацыя implementation у Gradle — не транзітыўна: калі аб’явіць implementation("io.kixo:kixo-android-sdk:0.1.20") у модулі-бібліятэцы (напрыклад, :core_domain), гэта НЕ зробіць Kixo бачным для :app ці любога іншага спажыўца. Працуюць два варыянты — выберыце адзін.
Pattern A — кожны модуль, які выклікае Kixo, аб’яўляе залежнасць самастойна (рэкамендуецца). захоўвае classpath кожнага модуля мінімальным і пазбягае каскадных перазборак. Выкарыстоўвайце каталог версій (libs.kixo.sdk), каб мяняць версію ў адным месцы.
// :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 — рээкспарт праз api(...). Адна дэкларацыя, але ў публічны ABI модуля бібліятэкі цяпер уваходзяць тыпы Kixo — любое павышэнне версіі перазбярэ ўсе залежныя модулі. Выкарыстоўвайце гэта толькі тады, калі бібліятэка паўторна выкарыстоўвае тыпы Kixo ў сваіх публічных сігнатурах (напрыклад, вяртае 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
}Папярэджанне
Калі падчас кампіляцыі модуля вы бачыце Unresolved reference: Kixo, у гэтага модуля няма ўласнай залежнасці ад SDK — дадайце радок implementation вышэй або выкарыстоўвайце Pattern B.
Ініцыялізацыя
Наладзьце Kixo ў вашым падкласе Application — onCreate выконваецца раней за любую activity, таму кожны прагляд экрана, націск і падзея жыццёвага цыклу будуць захоплены з першага кадра. Зарэгіструйце Application у manifest праз 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",
)
}
}Калі патрэбныя дакладныя налады (сцягі auto-track, інтэрвал flush, sampling для replay, уласны хост API), стварыце 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)Заўвага
Ідэмпатэнтна. Другі выклік configure у тым жа працэсе — no-op з запісам у WARN; SDK пакідае першую канфігурацыю. Падзеі, якія ваша auth-singleton чаргуе да таго, як перад configure спрацуе, буферызуюцца (ліміт 50) і прайграваюцца пасля ініцыялізацыі SDK, таму Kixo.identify(...) можна выклікаць з глабальнага кода яшчэ да завяршэння Application.onCreate.
Адсочванне падзей
Аснову інструментацыі звычайна складаюць тры прымітывы: track для падзей, markGoal для сігналаў канверсіі і addBreadcrumb для кантэксту па-за падзеямі.
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",
)Парада
Мэты маюць прыярытэт. Пазначаныя мэты выкарыстоўваюцца ў варонках актывацыі Kixo і ў штодзённым cron для выяўлення зменаў — калі аб’ём мэты падае на 70% тыдзень да тыдня, у дашбордзе яна з’явіцца з бейджам Патрэбна праверка. markGoal выкарыстоўвайце для нешматлікіх сапраўды важных момантаў; track — для ўсяго астатняга.
Стандартныя падзеі
Сінтаксічны цукар над Kixo.track для падзей, якія Kixo пазнае па назве, — літаральныя радковыя ключы, якія супастаўляе дэтэктар стандартных падзей на backend. Праверка формы ўласцівасцей на этапе кампіляцыі і адна крыніца праўды для назваў.
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)Ідэнтыфікаваць карыстальнікаў
Прывязвае наступныя падзеі да стабільнага id карыстальніка і набору traits. Звязванне ананімнага і вядомага карыстальніка адбываецца ў Kixo — падзеі, захопленыя да identify, заднім чыслом будуць аднесены да таго ж карыстальніка.
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()⚠️ Пастка са знакам даляра ў Kotlin. Стандартныя ключы ідэнтычнасці маюць прэфікс $ ($email, $name, $first_name) — і ў радковым літэрале Kotlin вы павінен экранаваць знак даляра як "\$email". Калі напісаць "$email", значэнне зменнай email будзе падстаўлена праз інтэрпаляцыю радка, таму значэнне ціха запішацца як trait карыстальніцкі і не запоўніць слупкі email / name у Audience. Самы просты варыянт — выкарыстаць тыпізаваны overload (SDK 0.1.13+), з якім немагчыма памыліцца: Kixo.setUserProperty(StandardProperty.EMAIL, email).
Пазначыць карыстальніка для сегментацыі
Выкарыстоўвайце setUserProperty са значэннем boolean, каб дадаць карыстальніку простую пазнаку «так/не». Яна захоўваецца паміж запускамi і выкарыстоўваецца ў сегментах, email-кампаніях і запытах у чатах — без дадатковай налады, толькі праз выклік 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",
))Уласцівасці захоўваюцца праз SharedPreferences паміж запускамi і аўтаматычна дадаюцца да кожнай выходнай падзеі. У чаце можна пісаць нешта кшталту "адправіць вітальны email карыстальнікам, у якіх subscribe = true" — Kixo сам створыць сегмент і падрыхтуе чарнавік шаблону. Ачышчаюцца пры Kixo.reset().
Стандартны каталог уласцівасцей
Зарэзерваваныя ключы ўласцівасцей маюць прэфікс $, таму не канфліктуюць з вашымі ўласнымі traits. Каталог Kixo ахоплівае 37 ключоў у 3 універсальных пакетах (ідэнтычнасць, геа, жыццёвы цыкл) і 5 вертыкальных пакетах B2B (падпіска, e-commerce, медыя, маркетплэйс, лаяльнасць). Задавайце толькі тое, што пасуе вашаму прадукту, — dashboard сам адаптуецца і пакажа толькі запоўненыя пакеты.
Identity
Заўсёды актуальна. Задае слупкі ў загалоўку профілю.
| Ключ | Тып | Апісанне |
|---|---|---|
$email | радок | Асноўны email, часта служыць ключом зліцця для звязвання ідэнтычнасці. |
$phone | радок | Нумар тэлефона ў фармаце E.164. |
$name | радок | Поўнае адлюстроўванае імя. |
$first_name | радок | Імя. |
$last_name | радок | Прозвішча. |
$avatar_url | радок | Поўны URL да выявы аватара карыстальніка. |
Geo
Геаграфічны кантэкст.
| Ключ | Тып | Апісанне |
|---|---|---|
$country | радок | Код краіны паводле ISO 3166. |
$city | радок | Назва горада. |
$region | радок | Штат або правінцыя. |
$timezone | радок | IANA zone накшталт America/Los_Angeles. |
$language | радок | IETF tag накшталт en або ru-RU. |
$locale | радок | Поўны ідэнтыфікатар лакалі. |
Жыццёвы цыкл
Калі мы бачылі гэтага карыстальніка.
| Ключ | Тып | Апісанне |
|---|---|---|
$created | ISO8601 | Час рэгістрацыі або стварэння акаўнта. |
$last_seen | ISO8601 | Час апошняга ўзаемадзеяння. |
Падпіска
Задавайце, калі ў вашага прадукту ёсць тарыфныя планы.
| Ключ | Тып | Апісанне |
|---|---|---|
$plan | радок | Slug тарыфу — free, pro, enterprise. |
$subscription_status | радок | active / trial / cancelled / past_due. |
$trial_ends | ISO8601 | Калі заканчваецца бягучы пробны перыяд. |
$mrr | лік | Штомесячны рэгулярны даход у валюце акаўнта. |
$subscription_started | ISO8601 | Калі пачалася бягучая падпіска. |
Электронная камерцыя
Задавайце, калі прадаяце тавары.
| Ключ | Тып | Апісанне |
|---|---|---|
$lifetime_orders | лік | Колькасць завершаных заказаў. |
$lifetime_revenue | лік | Агульныя выдаткі. |
$aov | лік | Сярэдні чэк. |
$last_purchase | ISO8601 | Апошняя паспяховая пакупка. |
$first_purchase | ISO8601 | Першая паспяховая пакупка. |
$cart_abandoned_count | лік | Агульная колькасць пакінутых кошыкаў за ўвесь час. |
Медыя
Задавайце, калі публікуеце кантэнт.
| Ключ | Тып | Апісанне |
|---|---|---|
$content_tier | радок | free / premium / paid. |
$subscribed_categories | CSV string або array | Катэгорыі, за якімі сочыць карыстальнік. |
$watch_time_total | лік | Агульны час прагляду ў секундах за ўвесь час. |
$last_played | ISO8601 | Апошні запуск прайгравання. |
Маркетплэйс
Задавайце, калі ваш прадукт — двухбаковая платформа.
| Ключ | Тып | Апісанне |
|---|---|---|
$seller_tier | радок | Slug тарыфу на баку прадаўца. |
$buyer_tier | радок | Slug узроўню на баку пакупніка. |
$listings_count | лік | Актыўныя аб’явы, якімі валодае карыстальнік. |
$reviews_count | лік | Водгукі, якія атрымаў карыстальнік. |
$verified | boolean | Статус KYC. |
Лаяльнасць
Задавайце для праграм узаемадзеяння і ўзнагарод.
| Ключ | Тып | Апісанне |
|---|---|---|
$loyalty_points | лік | Бягучы баланс даступных для выкарыстання балаў. |
$vip_level | радок | Slug узроўню VIP. |
$referral_count | лік | Паспяховыя рэфералы, аднесеныя да гэтага карыстальніка. |
Парада
Не бачыце свайго шаблону? Выкарыстоўвайце простыя ключы для custom traits. Яны з’явяцца ў панэлі Custom Traits у аналітычнай панэлі і не будуць засмечваць слупкі профілю. Пяць вертыкальных набораў вышэй — гэта практычныя здагадкі для самых тыповых формаў у B2B; спецыфічная для кліента тэрміналогія (напрыклад, shipping_plan) застаецца без прэфіксаў.
Super-properties
Пары ключ/значэнне на ўзроўні сесіі, якія аўтаматычна дадаюцца да кожнай выходнай падзеі. Гэта не тое самае, што traits identify (яны апісваюць ідэнтычнасць); super-properties апісваюць кантэкст сесіі — актыўны варыянт A/B, build flavor, уключаныя feature flags. Захоўваюцца паміж запускамi; ачышчаюцца пры reset(). Калі ўзнікае канфлікт, значэнні properties у 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-апавяшчэнні
Ёсць два шляхі інтэграцыі. Выбірайце A, калі вы на FCM і хочаце самую кароткую рабочую наладу; выбірайце B, калі ў вас ужо ёсць уласны FirebaseMessagingService, які вы не можаце перабудаваць, або калі вам патрэбны дакладны кантроль над тым, якія дастаўкі FCM бачыць Kixo.
Варыянт A — наследаваць KixoFirebaseMessagingService (аўтаадсочванне)
Стварыце падклас KixoFirebaseMessagingService і выклічце super.onMessageReceived(...) у сваім override — Kixo аўтаматычна адпраўляе push_received (бачны payload) або push_silent (толькі даныя). Базавы клас таксама апрацоўвае рэгістрацыю onNewToken, калі вы яе не override-іце. Рэгістрацыя AndroidManifest.xml не адрозніваецца ад звычайнага FCM service.
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
}
}Заўвага
Kixo кампілюе гэты неабавязковы клас супраць Firebase Messaging, але не дадае Firebase ў вашу праграму транзітыўна. SDK аб’яўляе Firebase як compileOnly; праграма, якая выбірае гэты варыянт, ужо павінна залежаць ад firebase-messaging, як і любы FCM receiver.
Варыянт B — выклікаць ручны API са свайго FCM service
Зарэгіструйце токен FCM у Kixo праз FirebaseMessagingService.onNewToken, а потым яўна лагіруйце кожную дастаўку. Выбірайце гэты шлях, калі хочаце, каб Kixo бачыў толькі частку даставак FCM. На Android дастаўка цяпер падтрымлівае толькі 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 не дае ўніверсальнага lifecycle-hook для адкрыццяў, закрыццяў або кнопак дзеянняў у апавяшчэннях. Перадайце гэтыя сігналы з notification intent-аў або receiver-аў, якія стварае ваша праграма:
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Прайграванне сесій
Replay дае рэальную візуальную рэканструкцыю таго, што бачыў карыстальнік. Пры кожным захопе SDK кадуе сціснуты кадр экрана (выява JPEG) разам са структурным здымкам іерархіі view і загружае абодва — таму прайгравальнік у дашбордзе можа паказваць піксельна дакладнае прайграванне поруч са шкалой узаемадзеянняў. Наладзьце replay для праекта ў Панэль кіравання → Налады → Паўтор сесіі. SDK аўтаматычна чытае і абнаўляе гэтую праектную палітыку, у тым ліку маскіраванне, рэжымы захопу і дазвол на загрузку праз мабільную сетку.
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)Калі загрузка праз мабільную сетку адключана, replay у чарзе чакае сеткі, якая дазволена палітыкай.
Парада
Маскіраванне перад загрузкай. Kixo захоплівае пікселі, таму маскіраванне спрацоўвае перад да таго, як што-небудзь пакіне прыладу. Палі з паролямі і e-mail вызначаюцца аўтаматычна і рэдагуюцца; тэкст у структурных здымках праходзіць праз фільтр PII; а любы view, які вы пазначыце праз setKixoMask(true), растэрызуецца ў непразрысты прамавугольнік у кадры перад перад кадаваннем JPEG — яго пікселі ніколі не пакідаюць прыладу. Экраны Jetpack Compose па змаўчанні маскіруюцца цалкам (выклічце setKixoMask(false) на знешнім ComposeView, каб уключыць экран, які вы ўжо праверылі). У дашбордзе аператары пракручваюць прайгравальнік replay паралельна са шкалой часу падзей.
Збор даных
SDK збірае даныя, уключаныя ў вашым праекце, а таксама падзеі і ўласцівасці, якія адпраўляе ваша праграма.
Адладка
Kixo.diagnostics() вяртае здымак стану SDK толькі для чытання — зручна для схаванага debug-экрана або smoke-тэсту. Дазваляе зразумець, «чаму не ідуць падзеі», без 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 stateПрымусова выканайце flush з вашага тэставага harness-а — выклік блакуецца да timeoutMs на сеткавы 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
Маршруты Activity / Fragment адразу ствараюць screen_viewevents і гатовыя структурныя запісы screen_visit з метаданымі пра працягласць і пераходы. Для Jetpack Compose Navigation выклікайце Kixo.screen з LaunchedEffect, прывязаным да route, — тады SDK убачыць адну падзею на кожны пункт прызначэння незалежна ад колькасці recomposition.
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-агенты для напісання кода
Публічная паверхня SDK невялікая і зручная для code completion: усе метады знаходзяцца на singleton Kixo, кожны Kotlin-прыклад у гэтым кіраўніцтве пачынаецца з import io.kixo.sdk.Kixo, а наш README змяшчае блок «AI agent quick reference», які інструменты накшталт Claude Code, Cursor і Codex могуць адразу ўставіць у свой кантэкст. Калі ваш агент затрымаўся, базавы старт такі:
// 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."Заўвага
Усе раздзелы вышэй напісаныя з улікам такога працоўнага працэсу: imports заўсёды відавочныя, тыпы заўсёды названыя, а singleton SDK ніколі не мае alias. Перадайце гэтую старонку свайму агенту і дайце яму весці працэс.