Я играл с проектом "Hello World", созданным в Android Studio 3.3 (новый пустой проект), и решил добавить библиотеку (ktor) в проект.Я следовал инструкциям README и просто добавил нужные вещи в файл Gradle.Когда я работал с веб-сокетами, в файл 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 Проблемы, но я не нашел хорошего объяснения, почему это происходит и как предотвратить такие ошибки.Я только что нашел несколько быстрых и коротких ответов / решений, написанных так: «Добавьте это в конфигурацию вашего проекта, и это сработает, поверьте мне, я эксперт», но я не удовлетворен этим, поскольку ядумаю, что как разработчик я должен понимать, что я делаю и почему это работает таким образом, и 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'
}
, которыйсделал работу, но я все еще не уверен, что это лучшее решение.Я думаю, что правильным подходом было бы понять причину ошибки и устранить ее причину, а не пытаться обойти ее с помощью дополнительных параметров упаковки.