我们在我们的应用程序中使用 multidex 很长时间了,但最近更新后它在 android API <19 上失败了 例如带有api 16的模拟器 它是标准的 java.lang.NoClassDefFoundError。
如果我为缺少的类定义 multidexKeepProguard,例如 java.lang.NoClassDefFoundError。 rx.plugins.RxJavaHooks 异常
-keep class rx.plugins.**{*;}
然后它将在不同的地方以相同的原因 NoClassDefFound 失败
这是运行器、应用程序和 list 设置:
https://gist.github.com/originx/1890599b57b0ee3e14a85a4732301cd9
日志:
https://gist.github.com/originx/887f80d405334f1903b3024eb5cd1024
构建环境设置:
安卓工作室 2.2.2 构建 #AI-145.3360264,构建于 2016 年 10 月 18 日 JRE:1.8.0_112-release-b05 x86_64 JVM:JetBrains s.r.o 的 OpenJDK 64 位服务器 VM
编译选项
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
可以在此处找到重现问题的 repo:
https://github.com/originx/multidex/tree/master
要运行请禁用即时运行
要重现 multidex 问题,请运行以下命令
./gradlew clean connectedPayGermanyCompatDebugAndroidTest
在任何设备或 API 16 模拟器上运行 GTI8190 4.1.2 上的测试失败由于 java.lang.NoClassDefFoundError,仪器运行失败
在我从 Google 团队获得更多信息之前,有什么解决此问题的建议吗?
最佳答案
Google 开发人员的解释:
The issue is that the rx.plugins.RxJavaHooks class referenced from the CustomJunitRunner.onCreate() method is in the secondary dex file of the main app, and you are accessing it before the class loaders get fully patched.
When the main application and test code share a dependency, we will remove it from the test's dependencies (as we expect it to be available in the main application). However, with legacy multidex, this is causing problems.
Currently, there are 2 workarounds:
Option 1 Ensure the rx.plugins.RxJavaHooks is in the main dex by creating a file multidexKeepProguard.pro and adding "-keep class rx.plugins.**"
Option 2 Remove references to RxJavaHooks from onCreate(), and move them to onStart() (not sure if this accomplishes when you want though): @Override public void onStart() { super.onStart(); //hook up schedulers to rxjava so espresso idling resouces can fetch it properly RxJavaHooks.setOnComputationScheduler(current -> Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)); RxJavaHooks.setOnIOScheduler(current -> Schedulers.from(AsyncTask.THREAD_POOL_EXECUTOR)); RxJavaHooks.setOnNewThreadScheduler(current -> 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.** { *; }
关于Android Espresso multidex 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40867407/