AndroidRunTime 异常 NoClassDefFoundError 在模拟器 API17 上,但不在 API22 上

2023-12-22

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

在 Android Studio 上,我有一个应用程序可以在 Android API22 上完美运行(Lollipop,在模拟器 API22 和 Android 手机 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 (22) 编译的,可以在 API 17 到 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 commons 库可以存在并导入,至少在 API 22 上(我提醒你,它在设备和模拟器上都成功运行)。

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

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

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

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


UPDATES

  • MultiDex 已启用。在 API 21 (Lollipop) 上,支持 multidex 的方式已更改(请参阅https://developer.android.com/tools/building/multidex.html https://developer.android.com/tools/building/multidex.html)。所以可能与此有关。

  • 当应用程序处于“调试模式”时,Gradle 在“发布模式”下构建模块(当应用程序处于调试状态时,为什么 Gradle 会在发布模式下构建我的模块 https://stackoverflow.com/questions/27277433/why-does-gradle-build-my-module-in-release-mode-when-the-app-is-in-debug/27277864#27277864)

  • 我尝试重建,用这些文件创建一个新项目,但没有成功。

  • “commons-io:commons-io:xxx”文件夹位于 Gradle 缓存文件夹中。


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

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

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

Android 5.0 及更高版本使用名为 ART 的运行时,它本身 支持从应用程序APK文件加载多个dex文件。

现在,当多重索引并尝试在同一应用程序中支持“正常 DEXing”(5.0/API21 之前)和“ART oat 文件”(5.0/API21 之后的新“DEX”文件)时,您可能会遇到一些问题与我的类似(无法找到 API21 之前的一些方法,但应用程序在 API21 及以上版本上运行良好)。

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

无论如何,解决方法是禁用 multidex 并使用 minifyEnabled 和“Proguard”,以便 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,但它对我来说很好地完成了工作,我不能在这些问题上花费更多时间。

希望这会对某人有所帮助。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AndroidRunTime 异常 NoClassDefFoundError 在模拟器 API17 上,但不在 API22 上 的相关文章

随机推荐