Android Espresso multidex 失败

Android Espresso multidex fail

我们在我们的应用程序中使用 multidex 很长时间了,但最近的最新更新在 android API <19 上失败了 例如api 16 的模拟器 是标准的 java.lang.NoClassDefFoundError.

如果我定义 multidexKeepProguard 用于丢失 class 例如 java.lang.NoClassDefFoundError。 rx.plugins.RxJavaHooks 异常

-keep class rx.plugins.**{*;}

然后它将在不同的地方失败,原因与NoClassDefFound

相同

这是 运行ner、应用程序和清单设置:

https://gist.github.com/originx/1890599b57b0ee3e14a85a4732301cd9

Logcat:

https://gist.github.com/originx/887f80d405334f1903b3024eb5cd1024

构建环境设置:

Android Studio 2.2.2 构建 #AI-145.3360264,构建于 2016 年 10 月 18 日 JRE: 1.8.0_112-release-b05 x86_64 JVM:JetBrains 的 OpenJDK 64 位服务器虚拟机 s.r.o

编译选项

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

的所有方法

总是相同的结果

如果对通常找不到的 classes 使用 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 GTI8190 4.1.2 上的 16 个模拟器测试失败 Instrumentation 运行 由于 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.** { *; }