【问题标题】:An error after adding a library to the Android project (More than one file was found with OS independent path 'META-INF/kotlinx-io.kotlin_module')将库添加到 Android 项目后出错(发现多个文件与操作系统无关的路径 'META-INF/kotlinx-io.kotlin_module')
【发布时间】:2019-06-23 14:02:14
【问题描述】:

我一直在玩在 Android Studio 3.3 中创建的“Hello World”项目(新的空项目),并决定 add a library (ktor) 加入该项目。我按照自述文件的说明,简单地将所需的东西添加到 gradle 文件中。当我使用 websockets 时,以下行已添加到应用程序的 gradle 构建文件中:

    implementation "io.ktor:ktor-client-websocket:$ktor_version"
    implementation "io.ktor:ktor-client-cio:$ktor_version"
    implementation "io.ktor:ktor-client-android:$ktor_version"
    implementation "io.ktor:ktor-client-cio:$ktor_version"

添加这些后,项目停止编译,我收到以下错误:

More than one file was found with OS independent path 'META-INF/kotlinx-io.kotlin_module'

有人能解释一下为什么会出现这个错误吗?我没有做任何违法的事情,我只是将库添加到在 Android Studio 中创建的简单、标准的空项目中,不知何故,在添加了新的依赖项后,事情就停止了。

我在 StackOverflow 和 GitHub Issues 上发现了一些类似的问题,但我没有找到很好的解释为什么会发生以及如何防止此类错误。我刚刚找到了一堆快速而简短的答案/解决方案,以“将其添加到您的项目配置中,它会起作用,相信我,我是专家”的方式编写,但我对此并不满意,因为我认为作为一名开发人员,我必须了解我在做什么以及为什么它会以这种方式工作,而 IMO 仅仅添加一个人不完全理解的东西是不专业的,希望它能解决问题。

所以,我尽力理解这个问题。据我根据其他答案了解,问题出在以下事实:我以某种方式最终在我的项目中拥有一个库的 2 个实例(?),因此 Gradle 无法理解选择哪个。但是后来我无法理解怎么办? (我没有添加任何其他“外部依赖项”)

至于解决方案,最常见的答案是将'META-INF/kotlinx-io.kotlin_module' 添加到excludePath 包装选项中,但我不明白为什么它应该是正确的。对我来说,这听起来像是在告诉构建系统“请从我的项目中排除这些路径/不要扫描它们以查找库”。但我不确定这是否是一种正确的方法,因为在这种情况下,我有效地从我的项目中排除了几个库/依赖项,这可能会导致运行时异常 NoClassDefFoundError 或将来出现类似情况。

第二个最常见的答案是将pickFirst 'META-INF/kotlinx-io.kotlin_module' 添加到打包选项中,这看起来更好一些,因为它告诉构建系统“当您有某个库的多个条目时,请使用您找到的第一个” ,即该库将包含在我的项目中,因此我是安全的,但作为一个来自 C/C++/Rust/System_Programming 世界的人,我仍然担心这个解决方案:就 C 而言(简化)让我们想象一下,我最终拥有 2 个不同版本(1.1、1.2)的库,并且我有一个头文件,如果我选择了错误的版本库(1.1),我希望我链接到库的 v.1.2 ,但使用较新的标题并期望它可以工作,嗯......它显然不会工作,我认为同样的问题可能会发生在Android上(但我不确定,因为我不是专家),即pickFirst 似乎是一个很好的解决方案,只要我们可以保证我们正在使用的库的“多个条目”具有同一个版本。

所以我现在尝试使用 pickFirst 方法,最终在我的 gradle 构建文件中添加了一个部分:

    packagingOptions {
        pickFirst 'META-INF/kotlinx-io.kotlin_module'
        pickFirst 'META-INF/atomicfu.kotlin_module'
        pickFirst 'META-INF/kotlinx-coroutines-io.kotlin_module'
    }

它完成了这项工作,但我仍然不确定它是否是最佳解决方案。我认为正确的方法是了解错误发生的原因并解决其根本原因,而不是尝试使用其他打包选项来解决它。

【问题讨论】:

    标签: android android-studio gradle kotlin android-gradle-plugin


    【解决方案1】:

    Android 不需要 APK 包的 META-INF 目录中的任何这些文件。

    META-INF 目录中的这些重复文件源自引用的库 -

    除了使用packagingOptions之外,别无他法。

    另请参阅:What is the purpose of META-INF? (Android APK != Java JAR)。

    这些确实是相似的包格式,但仍然不完全相同。

    【讨论】:

    • 谢谢,这很有道理。但是如果 META-INF 不是必需的,为什么在 Android 项目中默认不忽略呢?是否应该将其作为错误报告给 Gradle 或 Android Studio?另外,pickFirst 解决了这个问题,这意味着 META-INF 已经包含在 APK(?) 中,但我可能会认为它被忽略了,即可以包含在 APK 中的那个,但它没有任何在那里使用。我做对了吗?此外,来自引用库的重复项似乎是引用库中的错误,对吧?
    • @ScienceSE 在 Android 上它只是 META-INF/MANIFEST.MF, META-INF/CERT.SF, META-INF/CERT.RSA ...这不是一个错误,但几乎不基于包中唯一文件名的要求 - 和试图打包重复的文件名(它甚至无法确定这些文件是否相同)。
    • 是的,但问题是:我刚刚创建了一个空的 android 项目(即它不应该包含任何重复项),然后添加了一个库(如库的自述文件中所述),它开始抛出错误,据我所知,任何“入门” android 文档中都没有提到这些错误,这令人沮丧。如果 android 项目默认忽略其余的 META_INF 文件,那将是有意义的,IMO 会让事情变得更好,不是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多