我一直在玩在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个具有2个不同版本(1.1、1.2)的库,并且我有一个头文件,如果我选择了错误的版本库,则该文件期望我针对库的v.1.2链接( 1.1),但使用较新版本的标头,并希望它能正常工作,...显然不起作用,我认为在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'
}
完成了这项工作,但我仍然不确定这是否是最佳解决方案。我认为正确的方法是理解错误发生的原因并解决错误的根本原因,而不是尝试使用其他打包方法来解决该问题。
答案 0 :(得分:3)
Android不需要APK包的META-INF
目录中的任何这些文件。
META-INF
目录中的这些重复文件源自引用的库-
除了使用packagingOptions
之外,没有其他事情可做。
另请参见:What is the purpose of META-INF?(Android APK
!= Java JAR
)。
这些确实是相似的软件包格式,但仍然不完全相同。