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-javavsprotobuf-javaliteprotobuf-litevsprotobuf-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-класса.
Для этого:
- Вынесите инициализацию SDK в отдельный класс, который можно подменить.
- Оберните инициализацию SDK проверкой на запуск в инструментальной среде.
- Опционально: если в проекте сохраняется локальная ссылка на экземпляр SDK,
добавьте возможность подменять её с помощью
mockилиnull. - Добавьте mock-тест.
- Подготовка инициализации 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
}
}
}
- Доработка класса, предоставляющего ссылку на экземпляр Аналитики
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
lateinit var instance: MtsAnalyticsApi?
internal fun setMtsaSdkInstance(context: Context, mockMtsaApi: MtsAnalyticsApi? = null) {
instance = mockMtsaApi ?: MtsAnalyticsProvider.getAnalytics(context)
}
- Тестирование с
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")
}
}
В этому случае не будет дополнительных конфликтов.