Перейти к основному содержимому

Android SDK — интеграция для разработчика и ИИ-агента

к сведению

Документ выверен для SDK 2.8.0. Актуальную версию смотрите в Release Notes Android и подставляйте её вместо <SDK_VERSION>. Документ самодостаточен: по нему интеграцию можно выполнить полностью автономно, без вопросов к команде. Подходит и человеку, и ИИ-агенту (Claude Code, Cursor). Читается сверху вниз как playbook.

Оглавление​

Краткое содержание

Документ выверен для SDK 2.8.0. Актуальную версию смотрите в Release Notes Android и подставляйте её вместо <SDK_VERSION>. Документ самодостаточен: по нему интеграцию можно выполнить полностью автономно, без вопросов к команде. Подходит и человеку, и ИИ-агенту (Claude Code, Cursor). Читается сверху вниз как playbook.

TL;DR — золотой путь

Минимум, чтобы события пошли (флейвор allserv, замените плейсхолдеры вида `<FLOW_ID>` (см. таблицу плейсхолдеров ниже)):

  1. В settings.gradle.kts добавьте репозитории артефактов (SDK + Huawei для флейворов allserv/huawei):

    dependencyResolutionManagement {
    repositories {
    maven("https://packages.a.mts.ru/repository/maven-releases/") {
    name = "mts_analytics_sdk"
    content { includeGroupAndSubgroups("ru.mts.analytics") }
    }
    // транзитивные зависимости HMS для флейворов allserv/huawei —
    // артефактов com.huawei.* нет в google()/mavenCentral()
    maven("https://developer.huawei.com/repo/") {
    name = "huawei_repo"
    content { includeGroupAndSubgroups("com.huawei") }
    }
    }
    }
  2. В <module>/build.gradle.kts (где <module> — имя вашего Android-модуля, например app) добавьте зависимость:

    dependencies {
    implementation("ru.mts.analytics:android-sdk-allserv-v2:<SDK_VERSION>")
    }
  3. В AndroidManifest.xml добавьте разрешение:

    <uses-permission android:name="android.permission.INTERNET" />
  4. В Application выполните инициализацию и отправьте одно событие:

    import ru.mts.analytics.sdk2.publicapi.MTSAnalytics
    import ru.mts.analytics.sdk2.publicapi.config.MtsAnalyticsConfig
    import ru.mts.analytics.sdk2.publicapi.event.Event

    class App : android.app.Application() {
    override fun onCreate() {
    super.onCreate()
    val analytics = MTSAnalytics.getInstance(
    context = this,
    config = MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>").build(),
    )
    analytics.track(Event.AppEvent(eventName = "app_open"))
    }
    }

Проверка: adb logcat -s 'MA_ANALYTICS:*' — видны строки MA_CONFIG ->, MA_SESSION ->, MA_EMITTER ->. Единственный Android-тег логов SDK — MA_ANALYTICS; подсистема (MA_CONFIG, MA_SESSION, MA_EMITTER, MA_NETWORK) указывается префиксом внутри текста сообщения (MA_CONFIG -> ...), а не отдельным тегом. Дальше — полные шаги с проверками и опциями.

Предусловия и плейсхолдеры

Требования: Android (Kotlin), minSdk 23, targetSdk 36, compileSdk 36, JDK 17.

flowId — идентификатор потока аналитики. Если его нет — запросить на analytics.support@mts.ru (тема «Получение Flow ID»). Для интеграции подставляйте <FLOW_ID>.

В таблице плейсхолдеров указаны значения для подстановки:

  • <FLOW_ID> — UUID потока аналитики (пример: aabb1111-2c2d-3e3f-4444-555566667777).
  • <SDK_VERSION> — версия SDK (актуальная в Release Notes Android, пример: 2.8.0).
  • <APP_PACKAGE> — package приложения (пример: ru.example.app).
  • <UPTIME_PROVIDER_AUTHORITY> — уникальный authority провайдера (см. рецепт 8 app-start, пример: ru.example.app.MTSAUptimeProvider).

Шаг 1. Репозиторий артефактов

Добавьте адрес артефактов SDK в settings.gradle.kts:

dependencyResolutionManagement {
repositories {
maven("https://packages.a.mts.ru/repository/maven-releases/") {
name = "mts_analytics_sdk"
content { includeGroupAndSubgroups("ru.mts.analytics") }
}
}
}

Блок content { includeGroupAndSubgroups(...) } ограничивает репозиторий только артефактами SDK — Gradle не будет обращаться к нему за другими зависимостями.

Для флейворов allserv и huawei дополнительно нужен репозиторий Huawei. Эти флейворы тянут транзитивные зависимости HMS (com.huawei.hms:location, ads-identifier, ads-installreferrer), которых нет ни в google(), ни в mavenCentral() — без этого репозитория сборка падает с Could not find com.huawei.hms:...:

dependencyResolutionManagement {
repositories {
// транзитивные зависимости HMS (только для флейворов allserv/huawei)
maven("https://developer.huawei.com/repo/") {
name = "huawei_repo"
content { includeGroupAndSubgroups("com.huawei") }
}
}
}

Для флейворов google и noserv репозиторий Huawei не нужен.

Если резолюция не работает после изменения settings.gradle.kts, добавьте аналогичный блок repositories в корневой build.gradle.kts:

// корневой build.gradle.kts — резервный вариант при проблемах резолюции
allprojects {
repositories {
maven("https://packages.a.mts.ru/repository/maven-releases/") {
name = "mts_analytics_sdk"
content { includeGroupAndSubgroups("ru.mts.analytics") }
}
}
}

Резервный блок allprojects { repositories { ... } } не сработает, если в settings.gradle.kts задан repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) — тогда добавляйте репозиторий только в dependencyResolutionManagement (первый вариант).

DoD Шага 1: ./gradlew --refresh-dependencies help завершается успешно; репозиторий резолвится (нет Could not resolve ru.mts.analytics).

Шаг 2. Флейвор и зависимость

Выберите флейвор в зависимости от поддерживаемых сервисов:

Условие проектаФлейворАртефакт
Только Google Play Servicesgoogleru.mts.analytics:android-sdk-google-v2
Только Huawei HMShuaweiru.mts.analytics:android-sdk-huawei-v2
И Google, и Huaweiallservru.mts.analytics:android-sdk-allserv-v2
Без сервисов (крайний случай)noservru.mts.analytics:android-sdk-noserv-v2

noserv не собирает основные идентификаторы, что снижает точность аналитики. Для allserv/huawei обязателен репозиторий Huawei из Шага 1.

В <module>/build.gradle.kts (выберите один вариант):

allserv

dependencies {
implementation("ru.mts.analytics:android-sdk-allserv-v2:<SDK_VERSION>")
}

google

dependencies {
implementation("ru.mts.analytics:android-sdk-google-v2:<SDK_VERSION>")
}

huawei

dependencies {
implementation("ru.mts.analytics:android-sdk-huawei-v2:<SDK_VERSION>")
}

noserv

dependencies {
implementation("ru.mts.analytics:android-sdk-noserv-v2:<SDK_VERSION>")
}

Если в проекте есть свои build-варианты, привязывайте по конфигурации:

dependencies {
"googleImplementation"("ru.mts.analytics:android-sdk-google-v2:<SDK_VERSION>")
"huaweiImplementation"("ru.mts.analytics:android-sdk-huawei-v2:<SDK_VERSION>")
}

DoD Шага 2: ./gradlew :<module>:dependencies --configuration debugRuntimeClasspath | grep ru.mts.analytics показывает выбранный артефакт версии <SDK_VERSION>; сборка ./gradlew :<module>:assembleDebug проходит.

Шаг 3. Разрешения манифеста

SDK автоматически мержит ряд разрешений через манифест-мерджер; потребителю нужно добавить только то, чего в манифесте SDK нет.

РазрешениеЗачемКто объявляет / когда добавлять
android.permission.INTERNETотправка событийпотребитель — в манифесте SDK отсутствует, автоматически не мержится; добавить обязательно
android.permission.ACCESS_NETWORK_STATEопределение типа сетиSDK — мержится автоматически; добавлять не нужно
android.permission.READ_EXTERNAL_STORAGEfingerprint (хранилище)SDK — объявлено с maxSdkVersion="32"; на API 33+ автоматически заменено READ_MEDIA_*; мержится автоматически
com.google.android.gms.permission.AD_IDAdvertisingIdSDK объявляет с tools:node="remove" (удаляет запись из манифеста); для google-флейвора на API 33+ добавляет потребитель или Google Play Services
com.google.android.providers.gsf.permission.READ_GSERVICESfingerprint (GSF)SDK — мержится автоматически; добавлять не нужно

Минимум для AndroidManifest.xml — всегда:

<!-- обязательно: SDK не объявляет INTERNET, мерджер не добавит автоматически -->
<uses-permission android:name="android.permission.INTERNET" />

Для google-флейвора на API 33+ SDK удаляет запись AD_ID из своего манифеста (tools:node="remove"); Google Play Services восстанавливает её автоматически. Добавляйте её явно только если GPS не поставляет её в вашем проекте:

<!-- google-флейвор + API 33+: SDK удаляет эту запись, добавляем явно -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />

Библиотеки Huawei (транзитивный com.huawei.hms:location → LocationLiteSdk) добавляют в merged-манифест приложения свои разрешения: ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_WIFI_STATE, CHANGE_WIFI_STATE, com.huawei.permission.ACCESS_HW_KEYSTORE. Манифест самого SDK их не объявляет. Учитывайте это при privacy-ревью и публикации в сторах: приложение начнёт декларировать доступ к геолокации.

Если приложение не использует геолокацию, разрешения можно исключить в своём AndroidManifest.xml (SDK активных запросов геолокации не делает — местоположение передаётся только вручную через analytics.setLocation(...)):

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:node="remove" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" tools:node="remove" />
</manifest>

DoD Шага 3: ./gradlew :<module>:processDebugManifest (или assembleDebug) проходит; в merged-манифесте присутствует INTERNET.

Шаг 4. Инициализация

import ru.mts.analytics.sdk2.publicapi.MTSAnalytics
import ru.mts.analytics.sdk2.publicapi.api.MtsAnalyticsApi
import ru.mts.analytics.sdk2.publicapi.config.MtsAnalyticsConfig
import ru.mts.analytics.sdk2.logger.LogLevel

class App : android.app.Application() {
lateinit var analytics: MtsAnalyticsApi
private set

override fun onCreate() {
super.onCreate()
analytics = MTSAnalytics.getInstance(
context = this,
config = MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setLogLevel(LogLevel.ERROR) // релиз: ERROR/OFF; отладка: VERBOSE
.setCrashReportingEnabled(true)
.build(),
)
}
}

getInstance(...) возвращает один и тот же экземпляр для одного flowId.

Обработка ошибок. Пустой, невалидный или нулевой UUID (00000000-0000-0000-0000-000000000000) в flowId → getInstance(...) бросает IllegalArgumentException("FlowId must be in UUID format, but was: ..."). Проверьте <FLOW_ID> до сборки.

DoD Шага 4: приложение стартует без падения; adb logcat -s 'MA_ANALYTICS:*' показывает строки MA_CONFIG -> и создание сессии MA_SESSION ->.

Шаг 5. Конфигурация

Все параметры задаются через MtsAnalyticsConfig.Builder при инициализации; изменить конфигурацию в runtime можно через analytics.updateConfig(...).

СеттерСмыслДефолтГраницы
setLogLevel(LogLevel)уровень логирования в logcatOFFVERBOSE, DEBUG, WARNING, ERROR, OFF
setLoggerDelegate(LoggerDelegate?)внешний обработчик логовnull—
setNetworkTrafficEnabled(Boolean)включить отправку событий по сетиtrue—
setCrashReportingEnabled(Boolean)перехватывать JVM-крашиfalse—
setNativeCrashReportingEnabled(Boolean)перехватывать native-крашиfalse—
setAnrMonitoringEnabled(Boolean)мониторинг ANRfalse—
setAnrMonitoringTimeout(Int)таймаут обнаружения ANR, секунды5мин 5
setCollectAppStartMetricsEnabled(Boolean)собирать метрики старта приложенияfalse—
setCollectUIMetricsEnabled(Boolean)собирать метрики UIfalse—
setActiveTimeout(Int)таймаут активной сессии, секунды1800мин 900, макс 86400
setBackgroundTimeout(Int)таймаут фоновой сессии, секунды1800мин 900, макс 86400
setEventStorageLimit(Int)лимит событий в локальном хранилище6000мин 3000, макс 20000
setAllowFallbackMode(Boolean)резервный режим работы в памяти при недоступности локального хранилищаfalse—
subscribeForInstallReferrer { }подписка на получение install_referrer (Map<String,String>) один раз при инициализациине заданподробнее — рецепт install referrer ниже

НЕ ДЕЛАЙ: не менять flowId в runtime — локальное хранилище событий создаётся заново, накопленные неотправленные события не переносятся.

Пример обновления конфигурации в runtime (без изменения flowId):

analytics.updateConfig(
MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setLogLevel(LogLevel.VERBOSE)
.setActiveTimeout(3600)
.build(),
)

DoD Шага 5: конфигурация применяется без перезапуска; adb logcat -s 'MA_ANALYTICS:*' отражает новые значения через MA_CONFIG ->.

Шаг 6. Отправка событий

Event.AppEvent — универсальный шаблон. Обязателен eventName; остальные поля опциональны (зарезервированные ключи из ru.mts.analytics.sdk2.publicapi.MtsDimensions подставляются автоматически).

import ru.mts.analytics.sdk2.publicapi.event.Event

analytics.track(
Event.AppEvent(
eventName = "purchase_tap",
screenName = "cart",
customDimensions = mapOf("item_id" to "42", "price" to 199),
),
)

// Открытие экрана — спец-значение eventName:
analytics.track(Event.AppEvent(eventName = "scrn", screenName = "main"))

Короткие перегрузки:

analytics.track("app_open")
analytics.track("app_open", "source", "push")
analytics.track("app_open", "source" to "push", "step" to 1)
analytics.track("app_open", mapOf("source" to "push"))

Ошибки — Event.ErrorEvent с полем throwable (стектрейс обрезается ~5000 символов):

runCatching { risky() }.onFailure { analytics.track(Event.ErrorEvent(throwable = it, errMsg = "risky failed")) }

DoD Шага 6: после track(...) в adb logcat -s 'MA_ANALYTICS:*' виден MA_EMITTER ->. Отправка в сеть (MA_NETWORK ->) идёт батчами: события (кроме ErrorEvent) уходят при накоплении батча (по умолчанию 10 событий) либо по таймауту простоя — поэтому для проверки отправьте ~10 track(...) (не считая системных событий и resolve*). ErrorEvent отправляется сразу, вне батча. Подтверждение доставки в консоли МТС Аналитики — ручной шаг (у ИИ-агента нет доступа к консоли; не считать это провалом).

Шаг 7. Приёмка (Definition of Done)

Локально проверяемо (агент может подтвердить сам):

  • ./gradlew :<module>:assembleDebug — успех.
  • Зависимость резолвится: ./gradlew :<module>:dependencies | grep ru.mts.analytics → <SDK_VERSION>.
  • Приложение запускается без падения.
  • adb logcat -s 'MA_ANALYTICS:*' при старте показывает MA_CONFIG ->, MA_SESSION ->.
  • После ~10 track(...) видны MA_EMITTER -> и MA_NETWORK -> (события батчатся по ~10 либо уходят по таймауту простоя; ErrorEvent — сразу).

Ручной шаг (человек): подтвердить приход событий в консоли МТС Аналитики.

Если события не идут → Приложение: troubleshooting.

Рецепты по подсистемам

1. Краши JVM/Kotlin + native + ANR

Когда: нужно автоматически перехватывать фатальные JVM-ошибки, native-краши (C++/NDK) и ANR.

MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setCrashReportingEnabled(true) // JVM/Kotlin-краши
.setNativeCrashReportingEnabled(true) // native-краши (NDK)
.setAnrMonitoringEnabled(true) // ANR watchdog
.setAnrMonitoringTimeout(5) // мин 5 сек
.build()

Подробнее: Краши и ANR.


2. Performance — трассировка и метрики UI

Когда: нужно замерять время операций, перехватывать HTTP-запросы или собирать метрики старта/UI.

// Включить в конфиге:
MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setCollectAppStartMetricsEnabled(true) // метрики старта: нужны MTSAUptimeProvider + AppCompatActivity — см. рецепт 8
.setCollectUIMetricsEnabled(true)
.build()

// Ручная трассировка:
val trace: MTTrace = analytics.performance.newTrace("my_operation")
trace.start()
// ... операция ...
trace.stop()

HTTP-перехватчик для OkHttp Позволяет автоматически собирать сетевые метрики производительности. Для этого необходимо добавить перехватчик MTInterceptor в билдер OkHttpClient.

Remote Config / эксперименты Помогает получать конфигурацию с сервера и участвовать в A/B-тестах. SDK предоставляет интерфейс MARemoteConfig для установки дефолтных значений и запроса актуальных данных с сервера.

E-commerce Позволяет отправлять события электронной коммерции (просмотры, корзина, покупки) в форматах GA4 и Universal Analytics. Используются специализированные классы событий EcommerceGA4Event и EcommerceUAEvent.

Deep link — передача URI в аналитику Позволяет фиксировать переходы по внешним ссылкам (deep link). Необходимо вызывать метод трекинга URI в методах onCreate и onNewIntent активности.

Link Manager — короткие ссылки и deep link В тексте вы найдете руководство по решению задачи обработки брендированных коротких ссылок МТС. Инструкция охватывает две задачи: внешние переходы через Android App Links и внутренние переходы внутри приложения.

  • Для внешних переходов требуется регистрация поддомена и SHA-256 ключа для публикации assetlinks.json.
  • В манифесте настраивается intent-filter с autoVerify="true" для точного хоста.
  • Для внутренних ссылок (из чатов, баннеров) используется метод resolveLink, который раскрывает короткую ссылку в реальный URL для навигации внутри приложения, избегая открытия браузера.
  • На устройствах Huawei рекомендуется использовать resolveLink как устойчивый способ маршрутизации.

Install Referrer — источник установки Помогает определить источник установки приложения (Google, Huawei, RuStore и др.). SDK поддерживает получение реферрала через колбэк при инициализации или через Flow после инициализации.

App-start metrics — провайдер времени запуска Позволяет собирать точные метрики холодного старта приложения. Для этого необходимо добавить провайдер MTSAUptimeProvider в манифест и включить сбор метрик в конфиге. Метрики собираются корректно только при использовании AppCompatActivity.

MTS ID cross-auth — воронка аутентификации Позволяет отслеживать шаги воронки авторизации через MTS ID. События трекаются с указанием уникального токена сессии и названия шага воронки.

Web-session query — связь сессий app ↔ web Помогает передать идентификатор мобильной сессии в WebView или браузер для сквозной аналитики. SDK предоставляет асинхронный метод для получения строки запроса с идентификатором сессии.

Профиль пользователя — userId, userAgent, location Позволяет глобально устанавливать идентификатор пользователя, User-Agent и геолокацию. Идентификатор пользователя сохраняется между перезапусками, геолокацию можно задать через координаты или объект Location.

SDK-in-SDK — схема AnalyticsHostDelegate Предназначена для экосистемных модулей (Eco SDK), встраиваемых в хост-приложение. Модуль не должен создавать собственный экземпляр SDK, а должен делегировать вызовы хосту. В модуле запрещено включать отчетность о крашах, добавлять провайдер времени запуска и зависимости install-referrer.

Fallback mode — работа без базы данных Позволяет SDK продолжать работу в памяти, если SQLite недоступен. Режим следует отключать в продакшене, так как события не сохраняются при перезапуске приложения.

Приложение: таблицы В статье приведены таблицы флейворов, флагов конфигурации и разрешений, а также раздел Troubleshooting с описанием частых ошибок (невалидный FlowId, отсутствие интернета, конфликты версий) и способов их решения.

Глоссарий В разделе описаны основные классы SDK, их назначение и публичные интерфейсы, включая работу с событиями, конфигурацией, производительностью и логированием.

Актуальность инструкции Рекомендуется проверять актуальную версию SDK и изменения в Release Notes при обновлении библиотеки.

TL;DR — золотой путь​

Минимум, чтобы события пошли (флейвор allserv, замените плейсхолдеры вида `<FLOW_ID>` (см. таблицу плейсхолдеров ниже)):

1. settings.gradle.kts — репозитории артефактов (SDK + Huawei для флейворов allserv/huawei):

dependencyResolutionManagement {
repositories {
maven("https://packages.a.mts.ru/repository/maven-releases/") {
name = "mts_analytics_sdk"
content { includeGroupAndSubgroups("ru.mts.analytics") }
}
// транзитивные зависимости HMS для флейворов allserv/huawei —
// артефактов com.huawei.* нет в google()/mavenCentral()
maven("https://developer.huawei.com/repo/") {
name = "huawei_repo"
content { includeGroupAndSubgroups("com.huawei") }
}
}
}

2. <module>/build.gradle.kts (где <module> — имя вашего Android-модуля, например app) — зависимость:

dependencies {
implementation("ru.mts.analytics:android-sdk-allserv-v2:<SDK_VERSION>")
}

3. AndroidManifest.xml — разрешение:

<uses-permission android:name="android.permission.INTERNET" />

4. Application — инициализация и одно событие:

import ru.mts.analytics.sdk2.publicapi.MTSAnalytics
import ru.mts.analytics.sdk2.publicapi.config.MtsAnalyticsConfig
import ru.mts.analytics.sdk2.publicapi.event.Event

class App : android.app.Application() {
override fun onCreate() {
super.onCreate()
val analytics = MTSAnalytics.getInstance(
context = this,
config = MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>").build(),
)
analytics.track(Event.AppEvent(eventName = "app_open"))
}
}

Проверка: adb logcat -s 'MA_ANALYTICS:*' — видны строки MA_CONFIG ->, MA_SESSION ->, MA_EMITTER ->. Единственный Android-тег логов SDK — MA_ANALYTICS; подсистема (MA_CONFIG, MA_SESSION, MA_EMITTER, MA_NETWORK) указывается префиксом внутри текста сообщения (MA_CONFIG -> ...), а не отдельным тегом. Дальше — полные шаги с проверками и опциями.

Предусловия и плейсхолдеры​

Требования: Android (Kotlin), minSdk 23, targetSdk 36, compileSdk 36, JDK 17.

flowId — идентификатор потока аналитики. Если его нет — запросить на analytics.support@mts.ru (тема «Получение Flow ID»). Для интеграции подставляйте <FLOW_ID>.

ПлейсхолдерЧто подставитьПример
<FLOW_ID>UUID потока аналитикиaabb1111-2c2d-3e3f-4444-555566667777
<SDK_VERSION>версия SDK — актуальная в Release Notes Android2.8.0
<APP_PACKAGE>package приложенияru.example.app
<UPTIME_PROVIDER_AUTHORITY>уникальный authority провайдера — см. рецепт 8 (app-start)ru.example.app.MTSAUptimeProvider

Шаг 1. Репозиторий артефактов​

Добавьте адрес артефактов SDK в settings.gradle.kts:

dependencyResolutionManagement {
repositories {
maven("https://packages.a.mts.ru/repository/maven-releases/") {
name = "mts_analytics_sdk"
content { includeGroupAndSubgroups("ru.mts.analytics") }
}
}
}
к сведению

Блок content { includeGroupAndSubgroups(...) } ограничивает репозиторий только артефактами SDK — Gradle не будет обращаться к нему за другими зависимостями.

Для флейворов allserv и huawei дополнительно нужен репозиторий Huawei. Эти флейворы тянут транзитивные зависимости HMS (com.huawei.hms:location, ads-identifier, ads-installreferrer), которых нет ни в google(), ни в mavenCentral() — без этого репозитория сборка падает с Could not find com.huawei.hms:...:

dependencyResolutionManagement {
repositories {
// транзитивные зависимости HMS (только для флейворов allserv/huawei)
maven("https://developer.huawei.com/repo/") {
name = "huawei_repo"
content { includeGroupAndSubgroups("com.huawei") }
}
}
}

Для флейворов google и noserv репозиторий Huawei не нужен.

Если резолюция не работает после изменения settings.gradle.kts, добавьте аналогичный блок repositories в корневой build.gradle.kts:

// корневой build.gradle.kts — резервный вариант при проблемах резолюции
allprojects {
repositories {
maven("https://packages.a.mts.ru/repository/maven-releases/") {
name = "mts_analytics_sdk"
content { includeGroupAndSubgroups("ru.mts.analytics") }
}
}
}
к сведению

Резервный блок allprojects { repositories { ... } } не сработает, если в settings.gradle.kts задан repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) — тогда добавляйте репозиторий только в dependencyResolutionManagement (первый вариант).

DoD Шага 1: ./gradlew --refresh-dependencies help завершается успешно; репозиторий резолвится (нет Could not resolve ru.mts.analytics).

Шаг 2. Флейвор и зависимость​

Выберите флейвор в зависимости от поддерживаемых сервисов:

Условие проектаФлейворАртефакт
Только Google Play Servicesgoogleru.mts.analytics:android-sdk-google-v2
Только Huawei HMShuaweiru.mts.analytics:android-sdk-huawei-v2
И Google, и Huaweiallservru.mts.analytics:android-sdk-allserv-v2
Без сервисов (крайний случай)noservru.mts.analytics:android-sdk-noserv-v2
к сведению

noserv не собирает основные идентификаторы, что снижает точность аналитики. Для allserv/huawei обязателен репозиторий Huawei из Шага 1.

<module>/build.gradle.kts (выберите один вариант):

dependencies {
implementation("ru.mts.analytics:android-sdk-allserv-v2:<SDK_VERSION>")
}

Если в проекте есть свои build-варианты, привязывайте по конфигурации:

dependencies {
"googleImplementation"("ru.mts.analytics:android-sdk-google-v2:<SDK_VERSION>")
"huaweiImplementation"("ru.mts.analytics:android-sdk-huawei-v2:<SDK_VERSION>")
}

DoD Шага 2: ./gradlew :<module>:dependencies --configuration debugRuntimeClasspath | grep ru.mts.analytics показывает выбранный артефакт версии <SDK_VERSION>; сборка ./gradlew :<module>:assembleDebug проходит.

Шаг 3. Разрешения манифеста​

SDK автоматически мержит ряд разрешений через манифест-мерджер; потребителю нужно добавить только то, чего в манифесте SDK нет.

РазрешениеЗачемКто объявляет / когда добавлять
android.permission.INTERNETотправка событийпотребитель — в манифесте SDK отсутствует, автоматически не мержится; добавить обязательно
android.permission.ACCESS_NETWORK_STATEопределение типа сетиSDK — мержится автоматически; добавлять не нужно
android.permission.READ_EXTERNAL_STORAGEfingerprint (хранилище)SDK — объявлено с maxSdkVersion="32"; на API 33+ автоматически заменено READ_MEDIA_*; мержится автоматически
com.google.android.gms.permission.AD_IDAdvertisingIdSDK объявляет с tools:node="remove" (удаляет запись из манифеста); для google-флейвора на API 33+ добавляет потребитель или Google Play Services
com.google.android.providers.gsf.permission.READ_GSERVICESfingerprint (GSF)SDK — мержится автоматически; добавлять не нужно

Минимум для AndroidManifest.xml — всегда:

<!-- обязательно: SDK не объявляет INTERNET, мерджер не добавит автоматически -->
<uses-permission android:name="android.permission.INTERNET" />

Для google-флейвора на API 33+ SDK удаляет запись AD_ID из своего манифеста (tools:node="remove"); Google Play Services восстанавливает её автоматически. Добавляйте её явно только если GPS не поставляет её в вашем проекте:

<!-- google-флейвор + API 33+: SDK удаляет эту запись, добавляем явно -->
<uses-permission android:name="com.google.android.gms.permission.AD_ID" />
Флейворы allserv/huawei: транзитивные разрешения HMS

Библиотеки Huawei (транзитивный com.huawei.hms:location → LocationLiteSdk) добавляют в merged-манифест приложения свои разрешения: ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION, ACCESS_WIFI_STATE, CHANGE_WIFI_STATE, com.huawei.permission.ACCESS_HW_KEYSTORE. Манифест самого SDK их не объявляет. Учитывайте это при privacy-ревью и публикации в сторах: приложение начнёт декларировать доступ к геолокации.

Если приложение не использует геолокацию, разрешения можно исключить в своём AndroidManifest.xml (SDK активных запросов геолокации не делает — местоположение передаётся только вручную через analytics.setLocation(...)):

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:node="remove" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" tools:node="remove" />
</manifest>

DoD Шага 3: ./gradlew :<module>:processDebugManifest (или assembleDebug) проходит; в merged-манифесте присутствует INTERNET.

Шаг 4. Инициализация​

import ru.mts.analytics.sdk2.publicapi.MTSAnalytics
import ru.mts.analytics.sdk2.publicapi.api.MtsAnalyticsApi
import ru.mts.analytics.sdk2.publicapi.config.MtsAnalyticsConfig
import ru.mts.analytics.sdk2.logger.LogLevel

class App : android.app.Application() {
lateinit var analytics: MtsAnalyticsApi
private set

override fun onCreate() {
super.onCreate()
analytics = MTSAnalytics.getInstance(
context = this,
config = MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setLogLevel(LogLevel.ERROR) // релиз: ERROR/OFF; отладка: VERBOSE
.setCrashReportingEnabled(true)
.build(),
)
}
}

getInstance(...) возвращает один и тот же экземпляр для одного flowId.

Обработка ошибок. Пустой, невалидный или нулевой UUID (00000000-0000-0000-0000-000000000000) в flowId → getInstance(...) бросает IllegalArgumentException("FlowId must be in UUID format, but was: ..."). Проверьте <FLOW_ID> до сборки.

DoD Шага 4: приложение стартует без падения; adb logcat -s 'MA_ANALYTICS:*' показывает строки MA_CONFIG -> и создание сессии MA_SESSION ->.

Шаг 5. Конфигурация​

Все параметры задаются через MtsAnalyticsConfig.Builder при инициализации; изменить конфигурацию в runtime можно через analytics.updateConfig(...).

СеттерСмыслДефолтГраницы
setLogLevel(LogLevel)уровень логирования в logcatOFFVERBOSE, DEBUG, WARNING, ERROR, OFF
setLoggerDelegate(LoggerDelegate?)внешний обработчик логовnull—
setNetworkTrafficEnabled(Boolean)включить отправку событий по сетиtrue—
setCrashReportingEnabled(Boolean)перехватывать JVM-крашиfalse—
setNativeCrashReportingEnabled(Boolean)перехватывать native-крашиfalse—
setAnrMonitoringEnabled(Boolean)мониторинг ANRfalse—
setAnrMonitoringTimeout(Int)таймаут обнаружения ANR, секунды5мин 5
setCollectAppStartMetricsEnabled(Boolean)собирать метрики старта приложенияfalse—
setCollectUIMetricsEnabled(Boolean)собирать метрики UIfalse—
setActiveTimeout(Int)таймаут активной сессии, секунды1800мин 900, макс 86400
setBackgroundTimeout(Int)таймаут фоновой сессии, секунды1800мин 900, макс 86400
setEventStorageLimit(Int)лимит событий в локальном хранилище6000мин 3000, макс 20000
setAllowFallbackMode(Boolean)резервный режим работы в памяти при недоступности локального хранилищаfalse—
subscribeForInstallReferrer { }подписка на получение install_referrer (Map<String,String>) один раз при инициализациине заданподробнее — рецепт install referrer ниже
warning

НЕ ДЕЛАЙ: не менять flowId в runtime — локальное хранилище событий создаётся заново, накопленные неотправленные события не переносятся.

Пример обновления конфигурации в runtime (без изменения flowId):

analytics.updateConfig(
MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setLogLevel(LogLevel.VERBOSE)
.setActiveTimeout(3600)
.build(),
)

DoD Шага 5: конфигурация применяется без перезапуска; adb logcat -s 'MA_ANALYTICS:*' отражает новые значения через MA_CONFIG ->.

Шаг 6. Отправка событий​

Event.AppEvent — универсальный шаблон. Обязателен eventName; остальные поля опциональны (зарезервированные ключи из ru.mts.analytics.sdk2.publicapi.MtsDimensions подставляются автоматически).

import ru.mts.analytics.sdk2.publicapi.event.Event

analytics.track(
Event.AppEvent(
eventName = "purchase_tap",
screenName = "cart",
customDimensions = mapOf("item_id" to "42", "price" to 199),
),
)

// Открытие экрана — спец-значение eventName:
analytics.track(Event.AppEvent(eventName = "scrn", screenName = "main"))

Короткие перегрузки:

analytics.track("app_open")
analytics.track("app_open", "source", "push")
analytics.track("app_open", "source" to "push", "step" to 1)
analytics.track("app_open", mapOf("source" to "push"))

Ошибки — Event.ErrorEvent с полем throwable (стектрейс обрезается ~5000 символов):

runCatching { risky() }.onFailure { analytics.track(Event.ErrorEvent(throwable = it, errMsg = "risky failed")) }

DoD Шага 6: после track(...) в adb logcat -s 'MA_ANALYTICS:*' виден MA_EMITTER ->. Отправка в сеть (MA_NETWORK ->) идёт батчами: события (кроме ErrorEvent) уходят при накоплении батча (по умолчанию 10 событий) либо по таймауту простоя — поэтому для проверки отправьте ~10 track(...) (не считая системных событий и resolve*). ErrorEvent отправляется сразу, вне батча. Подтверждение доставки в консоли МТС Аналитики — ручной шаг (у ИИ-агента нет доступа к консоли; не считать это провалом).

Шаг 7. Приёмка (Definition of Done)​

Локально проверяемо (агент может подтвердить сам):

  • ./gradlew :<module>:assembleDebug — успех.
  • Зависимость резолвится: ./gradlew :<module>:dependencies | grep ru.mts.analytics → <SDK_VERSION>.
  • Приложение запускается без падения.
  • adb logcat -s 'MA_ANALYTICS:*' при старте показывает MA_CONFIG ->, MA_SESSION ->.
  • После ~10 track(...) видны MA_EMITTER -> и MA_NETWORK -> (события батчатся по ~10 либо уходят по таймауту простоя; ErrorEvent — сразу).

Ручной шаг (человек): подтвердить приход событий в консоли МТС Аналитики.

Если события не идут → Приложение: troubleshooting.

Рецепты по подсистемам​

1. Краши JVM/Kotlin + native + ANR​

Когда: нужно автоматически перехватывать фатальные JVM-ошибки, native-краши (C++/NDK) и ANR.

MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setCrashReportingEnabled(true) // JVM/Kotlin-краши
.setNativeCrashReportingEnabled(true) // native-краши (NDK)
.setAnrMonitoringEnabled(true) // ANR watchdog
.setAnrMonitoringTimeout(5) // мин 5 сек
.build()

Подробнее: Краши и ANR.


2. Performance — трассировка и метрики UI​

Когда: нужно замерять время операций, перехватывать HTTP-запросы или собирать метрики старта/UI.

// Включить в конфиге:
MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setCollectAppStartMetricsEnabled(true) // метрики старта: нужны MTSAUptimeProvider + AppCompatActivity — см. рецепт 8
.setCollectUIMetricsEnabled(true)
.build()

// Ручная трассировка:
val trace: MTTrace = analytics.performance.newTrace("my_operation")
trace.start()
// ... операция ...
trace.stop()

// HTTP-перехватчик для OkHttp:
val interceptor: MTInterceptor = analytics.performance.httpTracker.interceptor
val okHttpClient = OkHttpClient.Builder().addInterceptor(interceptor).build()

3. Remote Config / эксперименты​

Когда: нужно получать конфигурацию с сервера и участвовать в A/B-экспериментах.

val remoteConfig: MARemoteConfig = analytics.remoteConfig
// Установить дефолты и запросить актуальные значения:
remoteConfig.fetchRemoteConfigValuesAndActivate { result ->
val value = remoteConfig.activeConfig.value?.stringValue("feature_flag") ?: "default"
}

Подробнее: Remote Config.


4. E-commerce​

Когда: нужно отправлять события e-commerce (просмотры, добавление в корзину, покупки).

// GA4-контракт (имена событий — классы, не enum-константы):
analytics.track(
Event.EcommerceGA4Event(
eventName = EcommerceGA4Name.ViewItem(),
ecommerceGA4 = EcommerceGA4(items = listOf(/* EcommerceGA4Item(...) */)),
)
)

// UA-контракт:
analytics.track(
Event.EcommerceUAEvent(
eventName = EcommerceUAName.Detail(),
ecommerceUA = EcommerceUA(detail = Detail(products = listOf(/* Product(...) */))),
)
)

Подробнее: E-Commerce Android.


Когда: нужно зафиксировать переход по deep link (из внешнего источника).

// В Activity.onCreate и onNewIntent:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
intent?.data?.let { uri -> analytics.track(uri = uri) }
}

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
intent.data?.let { uri -> analytics.track(uri = uri) }
}

Подробнее: Deep Link Android.


Когда: брендированные короткие ссылки МТС (https://<поддомен>.url.mts.ru/...) должны открывать нужный экран приложения (а если приложение не установлено — вести на сайт). Здесь две разные задачи, которые часто путают:

  • A. Внешний переход — пользователь нажал на ссылку в браузере / другом приложении / SMS → нужно открыть ваше приложение на целевом экране (Android App Links).
  • B. Ссылка внутри приложения — короткая ссылка встроена в UI, пришла из чата поддержки, баннера, push-уведомления → нужно открыть контент в приложении, а не в браузере. Решается через resolveLink (шаг 6.3). На App Links здесь полагаться нельзя: если ссылку открывает сам код приложения (через WebView / Custom Tab / чат-SDK или как веб-URL), переход обычно идёт мимо App Links — в браузер.

Регистрация (один раз). Письмо на analytics.support@mts.ru, тема «Регистрация в Link Manager»: поддомен (<продукт>.url.mts.ru), SHA-256 ключа подписи приложения, имя пакета. По ним Link Manager публикует на домене Digital Asset Links (assetlinks.json) — это и включает автопроверку App Links.

Шаг 6.1. Манифест — App Links (внешние переходы, задача A).

<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTask"> <!-- singleTask или singleTop — чтобы срабатывал onNewIntent -->

<!-- Автопроверка App Links: ТОЛЬКО https и ТОЛЬКО точный хост (wildcard *.url.mts.ru не верифицируется) -->
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="<продукт>.url.mts.ru" />
</intent-filter>
</activity>

Условия, без которых App Links не сработает (и ссылка уйдёт в браузер):

  • autoVerify работает только по https. http-ссылки не верифицируются; если нужно ловить и их — вынесите http в отдельный intent-filter без autoVerify и обрабатывайте такой переход через resolveLink (шаг 6.3).
  • Только точный хост. Wildcard android:host="*.url.mts.ru" в autoVerify-фильтре проверку Digital Asset Links не проходит — указывайте зарегистрированный поддомен <продукт>.url.mts.ru явно (по одному <data> на каждый поддомен).
  • assetlinks.json на домене. Автопроверка тянет https://<продукт>.url.mts.ru/.well-known/assetlinks.json с вашим пакетом и SHA-256 — его публикует Link Manager по данным регистрации. Без него статус не будет verified.
  • android:exported="true" (обязательно с API 31) и категории DEFAULT + BROWSABLE.
  • launchMode — singleTask или singleTop (чтобы повторные переходы приходили в onNewIntent, а не открывали новый экземпляр экрана).

Проверить верификацию на устройстве: adb shell pm get-app-links <APP_PACKAGE> — для домена ожидается verified. Если none / legacy_failure — проверьте доступность assetlinks.json и точное совпадение SHA-256 и имени пакета.

Шаг 6.2. Обработать открытие приложения по ссылке — в Activity#onCreate и Activity#onNewIntent:

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
handleLink(intent)
}

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
setIntent(intent) // важно для singleTask
handleLink(intent)
}

private fun handleLink(intent: Intent?) {
val uri = intent?.data ?: return
analytics.track(uri) // 1) зафиксировать факт перехода
// 2) короткая ссылка Link Manager? — раскрыть через resolveLink и маршрутизировать по location;
// обычный deep link — маршрутизировать напрямую.
if (uri.authority?.contains("url.mts.ru") == true) {
lifecycleScope.launch {
when (val result = analytics.resolveLink(url = uri)) {
is DeepLinkResult.Success -> routeInApp(result.location, result.params)
is DeepLinkResult.Error -> routeInApp(uri.toString(), emptyMap()) // фолбэк
}
}
} else {
routeInApp(uri.toString(), emptyMap())
}
}

Шаг 6.3. Ссылка ВНУТРИ приложения — раскрыть и маршрутизировать, НЕ отдавать в браузер (задача B).

Это решение проблемы «ссылка из чата или встроенная ссылка открывается в браузере». Не вызывайте startActivity(ACTION_VIEW, url) для короткой ссылки — сначала раскройте её:

lifecycleScope.launch {
when (val result = analytics.resolveLink(url = uri)) {
is DeepLinkResult.Success -> routeInApp(result.location, result.params) // открыть экран в приложении
is DeepLinkResult.Error -> openInBrowser(uri) // фолбэк, если раскрыть не удалось
}
}

resolveLink делает сетевой запрос к бэкенду Link Manager (принудительно использует https, добавляет maAppInstalled / maOsName=android) и возвращает:

  • DeepLinkResult.Success(location: String, params: Map<String, Any?>) — location = целевой URL редиректа, params = параметры ссылки (вложенность ≤ 3 уровней); по ним стройте in-app навигацию.
  • DeepLinkResult.Error(error: Throwable) — невалидный URL или сетевая ошибка.

Доступен и колбэк-вариант: analytics.resolveLink(url) { result -> }.

НЕ ДЕЛАЙ / частые вопросы (из реальных обращений)
  • Ссылка из чата поддержки / баннера / захардкоженная не откроется сама через App Links — App Links работает только для переходов ИЗВНЕ приложения. Внутри приложения перехватывайте URL и вызывайте resolveLink (шаг 6.3). Это тот же случай, что и с короткими ссылками AppsFlyer.
  • Не открывайте короткую *.url.mts.ru ссылку напрямую в браузере / Custom Tab — сначала resolveLink, иначе пользователь уйдёт в браузер вместо экрана приложения.
  • Без регистрации (SHA-256 + пакет → assetlinks.json) внешняя автопроверка App Links не пройдёт, и система предложит открыть браузер.

Huawei / AppGallery. Отдельной Huawei-специфики в SDK нет и не требуется: resolveLink (шаг 6.3) — обычный сетевой вызов и работает на любом флейворе/сторе (google/huawei/allserv/noserv). Именно resolveLink + ручной роутинг — устойчивый способ маршрутизации на Huawei-устройствах, не зависящий от Google-верификации. OS-level App Links (шаг 6.1) — механизм Android (AOSP), не привязан к Google Play Services.

Подробнее: Link Manager для Android и отслеживание Deeplink.


7. Install Referrer — источник установки​

Когда: нужно знать, откуда пользователь установил приложение (Google, Huawei, RuStore, Galaxy, GetApps).

// Вариант 1 — колбэк при инициализации (срабатывает один раз):
MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.subscribeForInstallReferrer { referrers ->
val google = referrers["Google"]
}
.build()

// Вариант 2 — Flow (подписка после инициализации):
analytics.installReferrerFlow.collect { referrers ->
val rustore = referrers["Rustore"]
}

Дополнительные зависимости для конкретных магазинов (RuStore, Galaxy, GetApps) подключайте по документации соответствующего магазина.

Подробнее: Install Referrer Android.


8. App-start metrics — провайдер времени запуска​

Когда: нужно собирать точные метрики времени холодного старта приложения.

В AndroidManifest.xml (authority должен быть уникальным для каждого приложения):

<provider
android:name="ru.mts.analytics.sdk2.publicapi.providers.MTSAUptimeProvider"
android:authorities="<UPTIME_PROVIDER_AUTHORITY>"
android:exported="false" />

В конфиге:

MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setCollectAppStartMetricsEnabled(true)
.build()
Важно

Метрики старта собираются полностью только при обоих условиях: (1) провайдер MTSAUptimeProvider добавлен в манифест (выше), и (2) стартовая Activity наследует androidx.appcompat.app.AppCompatActivity. В Compose-шаблоне Android Studio по умолчанию ComponentActivity, в которой нет части lifecycle-методов — тогда TTID/TTFD и метрики видимости первого экрана не соберутся.


9. MTS ID cross-auth — воронка аутентификации​

Когда: нужно отслеживать шаги воронки авторизации через MTS ID с привязкой к сессии аутентификации.

// Начало авторизации:
analytics.track(
Event.AppEvent(
eventName = "vntLogin",
mtsIdAuthState = authState, // уникальный токен сеанса аутентификации
funnelName = "fnl_auth",
funnelStep = "fnl_auth_st1",
)
)

10. Web-session query — связь сессий app ↔ web​

Когда: нужно передать идентификатор мобильной сессии в WebView/браузер для сквозной аналитики.

// Асинхронный вариант (предпочтителен):
lifecycleScope.launch {
val queryItem = analytics.getWebSessionQueryItemAsync(url = "https://example.mts.ru")
// queryItem вернёт строку вида "_ma=1008798411687163870.1687163881292"
val webUrl = "$baseUrl?$queryItem"
openWebView(webUrl)
}

11. Профиль пользователя — userId, userAgent, location​

Когда: нужно глобально установить идентификатор пользователя, User-Agent WebView или геолокацию.

// userId — сохраняется между перезапусками; null — сброс:
analytics.setUserId(userId = "user-guid-123")

// userAgent — в памяти, не переживает рестарт:
analytics.setUserAgent(userAgent = Helpers.getUserAgentOrNull(context))

// Геолокация:
analytics.setLocation(latitude = 55.751244, longitude = 37.618423)
// или через android.location.Location:
analytics.setLocation(location = myLocation)

12. SDK-in-SDK — схема AnalyticsHostDelegate​

Когда: ваш продукт — это экосистемный модуль (Eco SDK), который встраивается в хост-приложение МТС, уже содержащее MTSA. Eco SDK не встраивает собственный экземпляр MTSA — он делегирует все вызовы экземпляру хоста через AnalyticsHostDelegate.

Подробная схема интеграции: SDK-in-SDK Android.

warning

НЕ ДЕЛАЙ в релизном Eco SDK:

  • не включать setCrashReportingEnabled(true) / setNativeCrashReportingEnabled(true) / setAnrMonitoringEnabled(true) — перехват крашей и ANR в модуле конфликтует с хост-приложением;
  • не добавлять MTSAUptimeProvider в манифест модуля — authority должен быть уникален на приложение, в хост-приложении он уже объявлен;
  • не подключать зависимости install-referrer (RuStore, Galaxy, GetApps) в модульном артефакте — это зона ответственности хоста.

13. Fallback mode — работа без базы данных​

Когда: устройство не поддерживает SQLite или база данных недоступна; нужно, чтобы SDK не падал, а продолжал работу в памяти.

MtsAnalyticsConfig.Builder(flowId = "<FLOW_ID>")
.setAllowFallbackMode(true) // режим работы в памяти при недоступности локального хранилища
.build()
warning

НЕ ДЕЛАЙ: не включать fallback mode по умолчанию в продакшн — события не переживают перезапуск приложения.


Приложение: таблицы​

Каноничные таблицы флейворов, флагов конфигурации и разрешений — см. разделы Шаг 1, Шаг 2 и Шаг 3 выше.

Troubleshooting​

Симптом / ошибкаПричинаФикс
IllegalArgumentException: FlowId must be in UUID formatпустой/невалидный/нулевой UUIDподставить корректный <FLOW_ID>
События не приходят в консольнет INTERNET / отключён трафикдобавить INTERNET; проверить setNetworkTrafficEnabled(true)
В logcat нет MA_* логовlogLevel = OFFsetLogLevel(LogLevel.VERBOSE) на время отладки
Could not resolve ru.mts.analytics:...не добавлен или неверно указан репозиторийпроверить URL из Шага 1
Could not find com.huawei.hms:... (флейвор allserv/huawei)нет репозитория Huawei — артефактов com.huawei.* нет в google()/mavenCentral()добавить https://developer.huawei.com/repo/ (Шаг 1)
Конфликт версий (например, netty и guava)транзитивные зависимостиresolutionStrategy { force(...) } в модуле
App-start метрики пустые на ComposeComponentActivity вместо AppCompatActivityизвестное ограничение; см. рецепт 8 (app-start)
Сборка требует minSdk 23RuStore install-referrer требует 23поднять minSdk до 23
R8/ProGuard ломает SDK—обычно не требуется: SDK поставляет consumer-rules.pro автоматически

Глоссарий​

Класс (FQN)Назначение
ru.mts.analytics.sdk2.publicapi.MTSAnalyticsточка входа SDK; getInstance(context, config) возвращает MtsAnalyticsApi
ru.mts.analytics.sdk2.publicapi.api.MtsAnalyticsApiосновной публичный интерфейс: track, updateConfig, setUserId, resolveLink и др.
ru.mts.analytics.sdk2.publicapi.config.MtsAnalyticsConfigконфигурация SDK; строится через вложенный Builder(flowId)
ru.mts.analytics.sdk2.publicapi.event.Event.AppEventуниверсальное событие МТС-разметки (eventName, screenName, customDimensions и др.)
ru.mts.analytics.sdk2.publicapi.event.Event.ErrorEventсобытие с прикреплённым Throwable; стектрейс обрезается до ~5000 символов
ru.mts.analytics.sdk2.publicapi.event.Event.EcommerceUAEventсобытие электронной торговли в формате Universal Analytics
ru.mts.analytics.sdk2.publicapi.event.Event.EcommerceGA4Eventсобытие электронной торговли в формате GA4
ru.mts.analytics.sdk2.publicapi.MtsDimensionsобъект с константами стандартных dimension-ключей МТС
ru.mts.analytics.sdk2.publicapi.Helpersутилиты: getUserAgentOrNull, getDeviceId и др.
ru.mts.analytics.sdk2.publicapi.api.apicontract.DeepLinkResultрезультат resolveLink: содержит URI и параметры deep link
ru.mts.analytics.sdk2.logger.LogLevelenum уровней логирования: VERBOSE, DEBUG, WARNING, ERROR, OFF
ru.mts.analytics.sdk2.publicapi.remoteconfig.MARemoteConfigинтерфейс доступа к удалённой конфигурации и A/B-экспериментам
ru.mts.analytics.sdk2.publicapi.performance.MTPerformanceинтерфейс для ручного измерения производительности (трейсы)
ru.mts.analytics.sdk2.publicapi.performance.MTTraceотдельный трейс; start(), stop()
ru.mts.analytics.sdk2.publicapi.performance.MTInterceptorOkHttp-перехватчик для автоматического сбора сетевых метрик
ru.mts.analytics.sdk2.publicapi.providers.MTSAUptimeProviderContentProvider для сбора метрик app-start; authority уникален на приложение

Актуальность инструкции​

Актуальную версию SDK и изменения между версиями проверяйте в Release Notes Android. При обновлении SDK перепроверьте инструкцию и синхронизируйте документ.