【发布时间】: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