模拟器 API17 上的 AndroidRunTime 异常 NoClassDefFoundError 但 API22 上没有

AndroidRunTime exception NoClassDefFoundError on simulator API17 but not on API22

Android Studio:1.3.1 - Gradle 构建插件:1.1.2 - Gradle:1.3.0

在 Android Studio 上,我有一个应用 运行 在 Android API22(Lollipop,在两个模拟器上都很好 [=7​​3=]22和 Android phone API22,也适用于 API 21 - 但不低于 API 21).

在我的 Gradle 构建文件中,我有以下内容:

compileSdkVersion 22
buildToolsVersion "22.0.1"

defaultConfig {
    minSdkVersion 17
    targetSdkVersion 22
...
compile "commons-io:commons-io:2.4" //IO

因此,据我了解:我的应用程序是在 API 17 到 API 22 的设备上使用最新的 API (22) 到 运行 编译的(在兼容模式下为 22+)。

但是,当我在 API 17 模拟器上 运行 Android 应用程序时,它会在某些文件复制操作期间崩溃。 在崩溃之前,dalivkvm 抱怨找不到方法。

I/dalvikvm﹕ Could not find method org.apache.commons.io.FileUtils.copyInputStreamToFile, 
referenced from method FileCopy.batchCreate
W/dalvikvm﹕ VFY: unable to resolve static method 58205: Lorg/apache/commons/io/FileUtils;
.copyInputStreamToFile (Ljava/io/InputStream;Ljava/io/File;)V
D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x0058

然后是致命异常:

E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NoClassDefFoundError: org.apache.commons.io.FileUtils

现在显然可以存在和导入 apache 公共库,至少在 API 22 上(我提醒你,运行s 在设备和模拟器上都成功了)。

除了 Apache Commons 之外的其他库也会发生这种情况(如果我跳过使用 Apache Commons,那么另一个第三方库将导致类似的问题等等)。

我不知道为什么它不会 API 17 运行。在 API 18 和 19,API 上也有同样的问题20 不存在。

它似乎在 API 21 和 API 22 上都能正常工作。

我在这里寻找过类似的错误,但通常是因为人们只是忘记包含他们的 jar 库所以它没有帮助。


更新

我能够解决我自己的问题。

所以基本上,据我了解(但我没有时间进一步调查),问题是由于支持 "Multidex" 的方式在 Android 中发生了变化API 21(又名 Android 5.0)。

link: https://developer.android.com/tools/building/multidex.html 告诉我们:

Android 5.0 and higher uses a runtime called ART which natively supports loading multiple dex files from application APK files.

现在,似乎在进行多索引处理并尝试同时支持 "normal DEXing"(5.0/API21 之前)和 "ART oat files"(新的 "DEX" 文件之后5.0/API21) 在同一个应用程序中,您可能会遇到一些类似于我的问题(无法找到 API21 之前的某些方法,但应用程序在 API21 及更高版本上运行良好)。

我的应用程序达到了 65k 方法的限制,我必须支持 API17+。

无论如何,解决方法是禁用 multidex 并改用带有 "Proguard" 的 minifyEnabled,以便 Proguard 删除所有未使用的方法,并且方法总数最终低于 65k。

相关代码(在Gradle构建文件中):

defaultConfig {

    ...

    //Enabling multidex support (for more than 65k methods)
    multiDexEnabled false
}

buildTypes {
    debug {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
}

当然,这不是一个真正的解决方案,因为需要有效使用 65k 方法的人将不得不使用 multidex,但它对我来说做得很好,我不能在这些问题上花更多时间.

希望这对某人有所帮助。