Android Эспрессо мультидекс сбой
Мы используем мультидекс в нашем приложении в течение длительного времени, но в последнее время с последним обновлением происходит сбой на Android API <19, например, эмулятор с API 16. Это стандартный java.lang.NoClassDefFoundError.
Если я определю multidexKeepProguard для отсутствующего класса, например, java.lang.NoClassDefFoundError. rx.plugins.RxJavaHooks исключение
-keep class rx.plugins.**{*;}
тогда он просто потерпит неудачу в другом месте по той же самой причине NoClassDefFound
Вот бегун, приложение и настройка манифеста:
https://gist.github.com/originx/1890599b57b0ee3e14a85a4732301cd9
Logcat:
https://gist.github.com/originx/887f80d405334f1903b3024eb5cd1024
Настройка среды сборки:
Android Studio 2.2.2, сборка #AI-145.3360264, построена 18 октября 2016 г. JRE: 1.8.0_112-release-b05 x86_64 JVM: 64-битная виртуальная машина OpenJDK от JetBrains sro
Варианты компиляции
compile 'com.android.support:multidex:1.0.1'
Информация о сборке инструментов:
classpath 'com.android.tools.build:gradle:2.2.2'
compileSdkVersion 25
buildToolsVersion '25'
defaultConfig {
applicationId "app.packagename.com"
minSdkVersion 16
targetSdkVersion 25
testInstrumentationRunner "de.payback.app.CustomAndroidJUnitRunner"
multiDexEnabled true
}
dexOptions {
jumboMode true
preDexLibraries false
javaMaxHeapSize "4g"
maxProcessCount = 8
}
debug {
applicationIdSuffix '.debug'
versionNameSuffix '-debug'
signingConfig signingConfigs.debug
minifyEnabled false
shrinkResources debugShrinkResourcesEnabled
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../proguardRules/proguard-rules.pro', '../proguardRules/proguard-debug-rules.pro'
// multiDexKeepProguard file('../proguardRules/multidex-proguard.pro')
testProguardFiles getDefaultProguardFile('proguard-android.txt'), '../proguardRules/proguard-rules.pro', '../proguardRules/proguard-debug-test-rules.pro'
testCoverageEnabled false
}
release {
minifyEnabled true
shrinkResources true
testProguardFiles getDefaultProguardFile('proguard-android.txt'), '../proguardRules/proguard-rules.pro'
proguardFiles getDefaultProguardFile('proguard-android.txt'), '../proguardRules/proguard-rules.pro'
// multiDexKeepProguard file('../proguardRules/multidex-proguard.pro')
}
Я перепробовал все: от расширения MultiDexApplication до пользовательского MultiDex.install (context) до использования MultiDexRunner.
всегда одни и те же результаты
при использовании файла multidexkeepproguard для классов, которые обычно не обнаруживаются, они находятся в основном файле dex, но, конечно, чего-то не хватает, что указывает на то, что multidex не был правильно установлен и инициализирован
Отчет об ошибках Google:
https://code.google.com/p/android/issues/detail?id=228449
репо для воспроизведения проблемы можно найти здесь:
https://github.com/originx/multidex/tree/master
Для запуска, пожалуйста, отключите мгновенный запуск
Чтобы воспроизвести проблему мультидекса, выполните следующую команду
./gradlew clean connectedPayGermanyCompatDebugAndroidTest
выполнить на любом устройстве или эмуляторе API 16. Тесты на GTI8190 4.1.2 завершились неудачно. Сбой запуска инструментария из-за java.lang.NoClassDefFoundError
Какие-нибудь предложения, как обойти это, пока я не получу больше информации от команды Google?
1 ответ
Объяснение от Google dev:
Проблема заключается в том, что класс rx.plugins.RxJavaHooks, на который ссылается метод CustomJunitRunner.onCreate(), находится во вторичном файле dex основного приложения, и вы обращаетесь к нему до того, как загрузчики классов будут полностью исправлены.
Когда основное приложение и тестовый код разделяют зависимость, мы удалим ее из зависимостей теста (поскольку мы ожидаем, что она будет доступна в основном приложении). Однако с устаревшим мультидексом это вызывает проблемы.
В настоящее время есть 2 обходных пути:
Вариант 1 Убедитесь, что rx.plugins.RxJavaHooks находится в главном разделе, создав файл multidexKeepProguard.pro и добавив "-keep class rx.plugins. **"
Вариант 2 Удалите ссылки на RxJavaHooks из onCreate () и переместите их в onStart() (хотя не уверен, что это выполняется, когда вы этого хотите): @Override public void onStart() { super.onStart(); // подключаем планировщики к rxjava, чтобы эспрессо-ресурсы на холостом ходу могли правильно его получить RxJavaHooks.setOnComputationScheduler(current -> Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)); RxJavaHooks.setOnIOScheduler(текущий -> Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)); RxJavaHooks.setOnNewThreadScheduler(текущий -> Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)); }
Решение
Временное решение
Таким образом, текущий обходной путь будет либо использовать файл multidexKeepProguard.pro и в вашей конфигурации отладки указать на этот файл:
debug {
applicationIdSuffix '.debug'
multiDexKeepProguard file('../proguardRules/multidex-proguard.pro')
}
Ваш файл multidex proguard должен содержать классы, которых нет в основном файле dex, в моем случае это был RxJavaPlugin, поэтому мой файл multidexproguard содержит:
-keep class rx.** { *; }