Что означает ошибка Manifest Merger Failed
Ошибка Manifest merger failed — это критическая ошибка времени сборки в Android-проектах, которая останавливает процесс генерации финального AndroidManifest.xml для приложения. Она возникает, когда система слияния манифестов (Manifest Merger) обнаруживает неразрешимый конфликт между элементами из разных источников: вашего основного манифеста (src/main/AndroidManifest.xml), манифестов библиотечных модулей (.aar), флаворов (product flavors) или сборок (build types).
Типичный полный текст ошибки выглядит так:
Error: Manifest merger failed :
Attribute application@label value=(@string/app_name) from AndroidManifest.xml:... is also present at
AndroidManifest.xml:... value=(@string/other_name)
Suggestion: add 'tools:replace="android:label"' to <application> element at AndroidManifest.xml:... to override
Конфликт может касаться любых атрибутов: android:icon, android:label, activity#name, uses-permission, meta-data и других.
Причины возникновения
Ошибка вызвана строгими правилами слияния XML-документов. Основные причины:
- Дублирование элемента с одинаковым именем. Две или более библиотеки/модули объявляют
<activity>,<service>или<provider>с одинаковым атрибутомandroid:name. - Конфликт значений атрибута. Один и тот же атрибут (например,
android:allowBackupу<application>) имеет разные значения в разных манифестах. - Несовместимость
applicationId. В многомодульном проекте разные модули могут претендовать на основной пакет. - Конфликт разрешений (
uses-permission). Две библиотеки запрашивают одно и то же разрешение с разными уровнямиmaxSdkVersionилиandroid:required. - Повторное объявление компонента. Ваш манифест уже содержит
<activity>, которую добавляет подключенная AAR-библиотека (например, Firebase, Google Play Services).
Способы решения
Способ 1: Использование tools:replace (основной)
Это самый частый и точечный способ. Вы явно указываете merger, какой атрибут из вашего манифеста имеет приоритет.
- Определите конфликтующий атрибут из полного сообщения об ошибке (например,
android:label). - Откройте ваш основной
AndroidManifest.xml(обычноapp/src/main/AndroidManifest.xml). - Найдите элемент, который вызывает конфликт (чаще всего
<application>или конкретный<activity>). - Добавьте пространство имён
toolsв корневой элемент<manifest>, если его нет:<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.example.app"> - Добавьте атрибут
tools:replaceк конфликтующему элементу, указав через запятую все конфликтующие атрибуты:<application android:label="@string/app_name" android:icon="@mipmap/ic_launcher" tools:replace="android:label, android:icon"> ... </application> - Выполните чистую сборку:
Build -> Clean Project, затемBuild -> Rebuild Project.
Способ 2: Удаление конфликтующего элемента (tools:node='remove')
Если элемент из библиотеки вам не нужен (например, лишняя activity или permission), вы можете полностью удалить его из финального манифеста.
- Определите полный путь и имя элемента, который нужно удалить (из ошибки).
- В вашем манифесте объявите этот же элемент с атрибутом
tools:node='remove':
Важно:<!-- Удаляем activity, добавленная библиотекой 'com.example.unwanted:lib' --> <activity android:name="com.example.unwanted.SomeActivity" tools:node="remove" />android:nameдолжно точно совпадать с тем, что указано в ошибке.
Способ 3: Настройка зависимостей в Gradle
Иногда конфликт возникает из-за того, что Gradle подтягивает разные версии одной и той же библиотеки.
- Откройте файл
build.gradleмодуляapp. - Найдите секцию
dependencies. - Принудительно задайте версию для проблемной библиотеки, используя
implementationс версией илиresolutionStrategy:dependencies { // Явно указываем единую версию implementation 'com.google.android.material:material:1.12.0' // Или используем forced для всех зависимостей configurations.all { resolutionStrategy { force 'com.some.library:conflicting-lib:1.2.3' } } } - Синхронизируйте проект (кнопка 'Sync Now' в строке Gradle).
Способ 4: Глубокий анализ с помощью gradle команды
Для сложных случаев, когда ошибка не указывает конкретный файл, используйте детальный лог.
- Запустите сборку с максимальной детализацией из терминала (в корне проекта):
./gradlew assembleDebug --info --stacktrace - Ищите в выводе блок
Merging manifestилиManifest merger. Там будут перечислены все обрабатываемые файлы манифестов. - Найдите два файла, которые определяют один и тот же элемент. Обычно это
AndroidManifest.xmlиз вашего модуля и из папкиbuild/intermediates/merged_manifests/...или.aarфайлов вbuild/. - Вручную исправьте конфликт, используя способы 1 или 2.
Профилактика
- Версии библиотек. Держите зависимости в актуальном и совместимом состоянии. Используйте
./gradlew dependenciesдля анализа дерева зависимостей. - Структура проекта. Избегайте дублирования
<application>атрибутов в разныхbuild.gradle(flavors/build-types). Выносите общие атрибуты вmainманифест. - Кастомные разрешения. Если вы добавляете
uses-permission, проверьте, нет ли его уже в библиотеках. - Именование компонентов. Для собственных
Activity,Service,Receiverиспользуйте полные имена (с пакетом) или уникальные имена, чтобы минимизировать риск совпадения. - Регулярные чистые сборки. Периодически выполняйте
Build -> Clean Project, особенно после серьёзных изменений в зависимостях.
Часто задаваемые вопросы (FAQ)
❓ Конфликт возникает из-за библиотеки, которой нет в dependencies. Что делать?
Иногда транзитивная зависимость подтягивается через другую библиотеку. Найдите источник с помощью команды ./gradlew :app:dependencies и используйте exclude:
implementation('com.some:library:1.0') {
exclude group: 'com.conflicting', module: 'bad-lib'
}
❓ Ошибка Attribute meta-data#android.support.VERSION value=... already defined. Как исправить?
Это классический конфликт версий библиотек поддержки (AndroidX). Убедитесь, что все библиотеки используют одну и ту же версию androidx.*:androidx.*:1.0.0 или com.android.support:appcompat-v7:28.0.0. Включите android.useAndroidX=true и android.enableJetifier=true в gradle.properties.
❓ Manifest merger failed с флавором (flavor). Где искать?
Конфликт может быть между манифестом main и манифестом конкретного флавара (например, src/free/AndroidManifest.xml). Проверьте оба. Решение — вынести общие элементы в main, а специфичные для флавара оставить в его манифесте, используя tools:replace при необходимости.
❓ После исправления ошибка остаётся. Почему?
- Кэш Gradle. Выполните
File -> Invalidate Caches and Restart...в Android Studio. - Не та версия. Убедитесь, что вы редактировали манифест в правильном
sourceSet(main,debug,flavorName). - Ошибка в другом месте. Возможно, есть второй конфликт. Внимательно прочитайте весь стек ошибки до конца.