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

FAQ: Android

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

Попадание в стектрейс ошибки пакета МТС Аналитики
Пакет ru.mts.analytics.* может появляться в стектрейсе из-за одновременного использования сторонней крашлитики и крашлитики МТС Аналитики, а также из-за функционала замера метрик в SDK 1.11.0 и выше. Это не означает ошибку SDK — реальная причина находится ниже по стеку.
Решение: Не является причиной корневой ошибки. Каждый случай рассматривается совместно с командой приложения.

Конфликты зависимостей Protobuf
Конфликты возникают между protobuf-java/protobuf-lite и protobuf-javalite. Пример ошибки: дублирование классов.
Решение: Использовать exclude group: 'com.google.protobuf', module: 'protobuf-javalite' или обновить firebase-config до версии 19.2.0 или выше.

Ошибка инициализации OkHttp
Ошибка NoClassDefFoundError возникает при использовании OkHttp > 5.0.
Решение: Использовать SDK МТС Аналитики версии 2.2.2+ или понизить версию OkHttp до 4.*.

Ошибка инициализации Room
Ошибка cannot override onCreate(SupportSQLiteDatabase) возникает при версии Room < 2.5.2.
Решение: Обновить версию Room до 2.5.2.

Ошибки исключения зависимостей Room
Исключение Room-зависимостей может привести к проблемам с базой данных.
Решение: Проверять на release minify сборках.

Конфликт интеграции с AppMetrica
AppMetrica запускается в отдельном процессе, но MTS SDK инициализируется в любом потоке.
Решение: Нет необходимости добавлять проверку на главный поток.

Ошибки отправки событий на сервис
Ошибка ConnectException может быть вызвана настройками сети, провайдером или роутером.
Решение: Отключить VPN, изменить источник интернета или SIM.

Ошибки NoClassDefFoundError при запуске теста
Инструментальные тесты могут падать из-за compileOnly-зависимостей.
Решение: Подменить интерфейс Аналитики с помощью mock-класса, используя try-catch и проверку на Robolectric.

Проблемы с поддержкой размера страницы памяти 16 кб
SDK -huawei и -allserv используют библиотеку com.huawei.hms:location:6.4.0.300, скомпилированную под 4КБ.
Решение: Форсировать загрузку версии 6.16.0.302 в build.gradle.

Попадание в стектрейс ошибки пакета МТС Аналитики

Пакет ru.mts.analytics.* может попасть в Stack Trace приложения по причинам:

  • Одновременно используется сторонняя крашлитика и крашлитика МТС Аналитики. Сначала ошибка перехватывается через uncaught exception handler, затем пробрасывается выше по стеку. Например в io.appmetrica uncaught exception handler
  • С версии SDK 1.11.0 используются врапперы над некоторыми колбэками Window и DecorView для замера метрик времени первого показа экрана-заглушки (static splash screen) и времени первого фрейма. Из-за этого возмножно попадание в стектрейс, например, с androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent
  • С версии SDK 1.17.0 добавлен функционал замеров сетевых запросов с помощью интерсепторов. При ошибках работы с сетью пакеты с публичными интерсепторами могут попасть в стектрейс

Если в стектрейсе ошибки попадается имя пакета Аналитики в примерно следующей последовательности (см. пример ниже), то это не ошибка SDK Аналитики — реальная причина находится ниже по стеку, например:

io.appmetrica.analytics.impl.Q1.uncaughtException (SourceFile:17)
ru.mts.analytics.sdk2.sb.a (SourceFile:2)
ru.mts.analytics.sdk2.sb$$ExternalSyntheticLambda0.uncaughtException (unavailable:2)
com.huawei.agconnect.crash.internal.a.uncaughtException (unavailable:35)

В данном примере видно, как ошибка произошла внутри com.huawei.agconnect была перехвачена UncaughtExceptionHandler МТС Аналитики, обработана и передана выше в UncaughtExceptionHandler AppMetrica. После этого она попала в крашлитику AppMetrica.

Решение

Это нормальное поведение и не является причиной корневой ошибки. Каждый такой случай рассматривается совместно с командой приложения.

Конфликты зависимостей Protobuf

Для отправки данных библиотека использует google protobuf-javalite.

Известно о конфликтах задвоения классов между:

  • protobuf-java vs protobuf-javalite
  • protobuf-lite vs protobuf-javalite

Версия protobuf-java включает в себя классы javalite, и java не рекомендуется для мобильных продуктов. Пакет protobuf-lite — это устаревшая версия пакета protobuf-javalite. Конфликты этих библиотек приводят к ошибке компиляции, например:

Duplicate

class com.
google.protobuf.AbstractProtobufList found
in modules
jetified-protobuf-javalite-3.23.4(com.google.protobuf:protobuf-javalite:3.23.4)
and jetified-protobuf-lite-3.0.1(com.google.protobuf:protobuf-lite:3.0.1)

Решение

Если у вас более свежая версия javalite, может помочь exclude javalite библиотеки

implementation("ru.mts.analytics:android-sdk-google:$mts_analytics_version") {
exclude group: 'com.google.protobuf', module: 'protobuf-javalite'
}

Некоторые библиотеки firebase могут тянуть за собой версию библиотеки protobuffer protobuf-lite. Например:

implementation "com.google.firebase:firebase-config:19.0.*"

Эта версия устаревшая и конфликтует с Android SDK МТС Аналитики. Обновите firebase-config до версии 19.2.0, или 20.*+.

Ошибка инициализации OkHttp

Если в проекте используется версия OkHttp > 5.* и возникает ошибка

java.lang.NoClassDefFoundError: Failed resolution of: Lokhttp3/internal/Util;

Начиная с версии 5.x (с 5.0.0-alpha.4), класс OkHttp Util переехал в другой пакет — UtilCommon.

Решение

  • Использовать SDK МТС Аналитики версии 2.2.2 или выше, где удалено использование классов из пакета okhttp internal
  • В проекте понизить версию OkHttp до 4.*

Ошибка инициализации Room

Если используется версия Room < 2.5.2 и возникает ошибка

cannot override onCreate(SupportSQLiteDatabase) in Delegate
protected void onCreate(SupportSQLiteDatabase _db) {
^
attempting to assign weaker access privileges; was public

Решение

Поднять версию Room до 2.5.2.

Ошибки исключения зависимостей Room

Исключение room-зависимостей из библиотеки может привести к поломке работе с базой данных.

Например:

    exclude group: 'androidx.room', module: 'room-ktx'
exclude group: 'androidx.room', module: 'room-runtime'
exclude group: 'androidx.room', module: 'room-compiler'

Симптомы:

  • выглядит, как считывание nullable записей из пустых таблиц базы данных: преференсы, конфигурации, сессия, события. В logcat будут приходить попытки создать сессию, сохранить события и т.п.
  • похоже на поломку type converters или protobuf по итогу минификации

Решение

Проверять на release minify сборках.

Конфликт интеграции с AppMetrica

Подробнее о требованиях к установке AppMetrica

AppMetrica запускается в отдельном процессе, где повторно инициализирует application-класс приложения. Из-за этого для инициализации предлагается делать проверку на главный поток

if (isMainProcess()) {
// Initializing third-party libraries after verification.
}

В SDK МТС Аналитики такую проверку можно не добавлять — библиотека инициализируется в любом потоке. Если это не главный поток, создаются пустые сущности менеджеров: Tracker, Emitter и Session с конфигурацией «по умолчанию».

Ошибки отправки событий на сервис

С тестируемого девайса нет доступа к сервису metric api, 404 из браузера или в логах указано:

NETWORK -> Status send data
error:java.net.ConnectException: Failed to
connect to api.a.mts.ru/0.0.0.0:443
NETWORK -> Status send data:null

Причины:

  • На девайсе включены кастомные настройки отправки трафика, работы с SSL, VPN
  • Провайдер связи фильтрует или блокирует трафик на этот адрес
  • Настройки фильтрации или блокировки на роутере

Решение

  • Отключить VPN и настройки фильтрации на период тестирования
  • Сменить источник интернет-трафика, SIM

Ошибки NoClassDefFoundError при запуске инструментального теста

Ряд библиотек подключаются к проекту SDK МТС Аналитики в режиме compileOnlyи не попадают в зависимости через .pom-файл. Вызов обёрнут в try-catch — это позволяет не подтягивать лишние зависимости.

Инструментальный тест с помощью Robolectric может падать в момент начала работы SandboxClassLoader при инициализации.

Решение

Чтобы действующие тесты не падали, подмените интерфейс Аналитики с помощью mock-класса.

Для этого:

  1. Вынесите инициализацию SDK в отдельный класс, который можно подменить.
  2. Оберните инициализацию SDK проверкой на запуск в инструментальной среде.
  3. Опционально: если в проекте сохраняется локальная ссылка на экземпляр SDK, добавьте возможность подменять её с помощью mock или null.
  4. Добавьте mock-тест.
Пример
  1. Подготовка инициализации SDK
internal object MtsAnalyticsProvider {
private val TAG = MtsAnalyticsProvider::class.java.simpleName

fun getAnalytics(context: Context): MtsAnalyticsApi? {
return if (isRunningInRobolectric().not()) {
runCatching {
MTSAnalytics.getInstance(
context,
MtsAnalyticsConfig.Builder(flowId = BuildConfig.YOUR_FLOW_ID).build()
)
}.onFailure {
Log.d(TAG, "Fail to init MTSA")
}.getOrNull()
} else {
Log.d(TAG, "Robolectric detected")
null
}
}

private fun isRunningInRobolectric(): Boolean {
return try {
Class.forName("org.robolectric.Robolectric")
true
} catch (e1: ClassNotFoundException) {
false
} catch (e2: Exception) {
false
}
}
}
  1. Доработка класса, предоставляющего ссылку на экземпляр Аналитики
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
lateinit var instance: MtsAnalyticsApi?
internal fun setMtsaSdkInstance(context: Context, mockMtsaApi: MtsAnalyticsApi? = null) {
instance = mockMtsaApi ?: MtsAnalyticsProvider.getAnalytics(context)
}
  1. Тестирование с mock
@RunWith(AndroidJUnit4::class)
class MtsaInitTest {

private val mtsaProvider = mockk<MtsAnalyticsProvider>()
private val mtsaApiMock = mockk<MtsAnalyticsApi>()

@Test
fun checkMtsaDependencies() {
every {
mtsaProvider.getAnalytics(ApplicationProvider.getApplicationContext())
} returns mtsaApiMock

DependenciesInjector.setMtsaSdkInstance(
context = ApplicationProvider.getApplicationContext(),
mockMtsaApi = mtsaApiMock
)
}
}

Проблемы с поддержкой размера страницы памяти 16 кб

Google абстрагировала ядро Linux в Android, назвав это Generic Kernel Image. Вендоры должны работать с ним без модификации через специальный интерфейс - KMI.

Начиная с версии Android 15, поддержка страниц памяти размером 16K стала обязательной:

Это относится и к транзитивным зависимостям — в зависимостях должны быть подключены библиотеки, которые также поддержали новые требования.

SDK МТС Аналитики в артефактах -huawei и -allserv подключает зависимость «com.huawei.hms:location:6.4.0.300», где версия 6.4.0.300 скомпилирована под размер страницы 4КБ.

Решение

Если известно, к какой конкретно зависимости Google предъявляет претензии, то в build.gradle модуля приложения (например, :app) перед блоком зависимостей можно форсировать скачивание корректной версии транзитивной зависимости.

Пример

Локация от Huawei — 6.16.0.302 уже скомпилирована под 16 кб.

configurations.all {
resolutionStrategy {
force("com.huawei.hms:location:6.16.0.302")
}
}

В этому случае не будет дополнительных конфликтов.