
حل مشكلة Manifest merger failed في أندرويد ستوديو نهائياً
تعد مشكلة Manifest merger failed واحدة من أكثر العقبات التي تواجه
مطوري أندرويد إحباطاً، ليس لصعوبتها البرمجية، بل لغموض الرسائل التي يظهرها
"أندرويد ستوديو". في هذا القسم، سنقوم بتفكيك هذا اللغز لنفهم ما الذي يحدث خلف الكواليس.
في المشاريع البسيطة، قد تظن أن ملف AndroidManifest.xml هو ملف واحد فقط.
لكن في المشاريع المعقدة، الحقيقة مختلفة تماماً. تطبيقك هو نتاج دمج عدة ملفات "مانيفست" في آن واحد:
- الملف الرئيسي (Main Manifest): الذي تكتبه أنت في مجلد main.
- ملفات المكتبات (Library Manifests): كل مكتبة تضيفها في الـ dependencies (مثل Firebase أو Facebook SDK) تملك ملف مانيفست خاص بها.
- ملفات نكهات التطبيق (Build Variants): إذا كان لديك نسخ debug أو release.
* عملية الدمج (Merging) هي الوظيفة التي يقوم بها نظام Gradle لجمع
كل هذه الملفات في ملف واحد نهائي يُحزم داخل الـ APK. يحدث الخطأ عندما
يجد النظام "تضارباً" لا يستطيع حله تلقائياً؛ مثل أن تحاول مكتبة خارجية فرض إعداد (مثل android:allowBackup="true") بينما تطلب أنت في ملفك الرئيسي (false).
هنا يتوقف Gradle عن العمل ويطلق صرخته الشهيرة: Manifest merger failed.
كيف تكتشف وجود خطأ Manifest merger failed ؟
لا يظهر هذا الخطأ أثناء كتابة الكود (Compile-time) بل يظهر أثناء عملية البناء (Build).
ستلاحظ الأعراض التالية:
نافذة Build: تظهر رسالة باللون الأحمر مكتوب فيها
. Execution failed for task ':app:processDebugMainManifest'
* جملة محبطة تقول Manifest merger failed with multiple errors, see logs.
- فشل التثبيت: في بعض الأحيان يفشل تشغيل التطبيق على المحاكي (Emulator)
وتظهر رسائل تضارب الـ Authorities.
** نحن لا نريد فقط "إخفاء" الخطأ، بل نريد إصلاحه بجذور تقنية سليمة.
في الأسطر القادمة، سننتقل من حالة الحيرة أمام رسالة الخطأ الغامضة إلى مرحلة الاحتراف،
حيث ستتعلم كيف تستخدم أدوات أندرويد ستوديو المخفية لتحديد السطر المسبب للمشكلة بالضبط،
وكيف تستخدم أوامر الـ Tools Namespace لإجبار Gradle على تنفيذ أوامرك أنت، وليس أوامر المكتبات الخارجية.
كيف تكتشف السبب الحقيقي لخطأ Manifest merger failed؟
يكمن التحدي الأكبر في هذا الخطأ في أن أندرويد ستوديو غالباً ما يعطيك
رسالة عامة في واجهة "Build" الرئيسية، مما يجعل المطورين يشعرون
بأنهم يطاردون "شبحاً". الحقيقة هي أن السبب موجود ومكتوب بدقة،
لكنه مخفي في أدوات متقدمة داخل البيئة التطويرية. إليك خريطة الطريق
لاستخراج السبب الحقيقي من أعماق المشروع :
1- تبويب Merged Manifest: سلاحك السري الأول
هذه هي الأداة الأكثر قوة والأقل استخداماً من قبل المطورين المبتدئين.
بدلاً من تخمين مكان التضارب، يتيح لك أندرويد ستوديو رؤية النتيجة النهائية لعملية الدمج قبل اكتمالها.
* كيفية الوصول إليه : 1. افتح ملف AndroidManifest.xml الخاص بمشروعك.
2. انظر إلى أسفل نافذة الكود؛ ستجد تبويبين: Text (أو Code) و Merged Manifest.
3. اضغط على Merged Manifest.
* ستظهر لك لوحة مقسمة؛ في جهة اليسار ترى المانيفست النهائي،
وفي جهة اليمين ترى Manifest Log. إذا وجد أندرويد ستوديو تضارباً،
فسيظهر باللون الأحمر في هذه اللوحة مع ذكر اسم المكتبة التي تسببت في المشكلة
بالضبط (مثلاً: تضارب بين مشروعك ومكتبة Firebase).
2- قراءة الـ Build Log: استخراج التفاصيل
عندما يفشل بناء المشروع، تكتفي نافذة Build بقول "Failed".
لكي تعرف "لماذا"، عليك الغوص في السجلات:
* البحث عن الجملة المفتاحية: ابحث دائماً عن جملة See the log for details أو
اضغط على رابط Toggle View (أيقونة الأسطر الصغيرة) في
نافذة Build لتتحول الواجهة من رسومية إلى نصية.
* تحليل الرسائل الحمراء: ابحث عن الكلمات التي تبدأ بـ Conflicting tag أو
Attribute ... is also present in .... هذه الرسائل تخبرك بالسمة المتضاربة
(مثل الـ Icon أو Theme) ومكان وجودها في المكتبة الخارجية.
3- استخدام أمر --stacktrace في الـ Terminal
أحياناً يكون الخطأ ناتجاً عن مشكلة في نظام Gradle نفسه وليس مجرد تضارب سمات.
هنا يأتي دور الـ Terminal:
* التنفيذ: افتح تبويب Terminal في أسفل أندرويد ستوديو واكتب الأمر التالي:
./gradlew assembleDebug --stacktrace
* هذا الأمر يجبر Gradle على طباعة تقرير مفصل جداً (Stacktrace) يوضح
التسلسل البرمجي الذي أدى للفشل. سيكشف لك هذا التقرير ما إذا كان الخطأ ناتجاً عن
إصدارات SDK غير متوافقة أو مكتبات مفقودة.
4- تحليل الـ Manifest Merger Report: التقرير النصي الكامل
هل تعلم أن Gradle يولد ملفاً نصياً كاملاً يشرح فيه كل قرار اتخذه أثناء دمج الملفات؟
هذا التقرير هو "الصندوق الأسود" لمشروعك.
- اذهب إلى مجلد مشروعك ثم اتبع المسار التالي:
app/build/outputs/logs/manifest-merger-debug-report.txt
* يوضح لك هذا التقرير المصدر الأصلي لكل سطر في المانيفست النهائي.
إذا تم تغيير قيمة معينة بشكل لم تطلبه، سيخبرك التقرير:
"تم تغيير هذه القيمة بواسطة المكتبة X في السطر Y".
هذا المستوى من التفاصيل هو ما يفصل المطور المحترف عن الهاوي.
الأسباب الـ 12 الأكثر شيوعاً وحلولها الجذرية لعام 2026
بعد أن تعلمنا كيف نحدد مكان الخطأ حان الوقت لمواجهة الجناة الحقيقيين.
تختلف أسباب فشل الدمج، ولكنها غالباً ما تدور حول تضارب في السياسات بين مشروعك
والمكتبات الخارجية. إليك التفاصيل التقنية لكل سبب وكيفية القضاء عليه :
أولاً: تضارب إصدارات الـ SDK (Min, Target & Compile)
يحدث هذا عندما تحاول استخدام مكتبة حديثة تتطلب minSdkVersion أعلى
مما حددته في مشروعك، أو عندما تطلب مكتبة إصدار compileSdk أحدث.
- ستظهر رسالة تخبرك أن المكتبة X تتطلب الإصدار 26 بينما مشروعك يستخدم 21.
- الحل: تحديث إصدارات الـ SDK في ملف build.gradle لتتوافق مع متطلبات المكتبة،
أو استخدام سطر التجاوز (سيتم شرحه في الحالات التطبيقية بالأسفل).
ثانياً: تكرار السمات (Attribute Conflict)
أشهر تضارب يواجه المطورين. تطلب أنت في تطبيقك
android:allowBackup="false" للأمان، بينما تأتي مكتبة (مثل مكتبة إعلانات أو إحصائيات)
وتطلبها true. هنا يتوقف Gradle لأنه لا يعرف أي أمر ينفذ.
- الحل: استخدام وسم tools:replace في المانيفست لإجبار النظام على استخدام قيمتك أنت.
ثالثاً: معضلة الـ android:exported في أندرويد +12
منذ أندرويد 12، أصبح لزاماً تعريف خاصية exported بوضوح (true أو false) لأي
مكون (Activity, Service, Receiver) يحتوي على intent-filter.
- المشكلة: قد تستخدم مكتبة قديمة لم يتم تحديثها، وبالتالي ينقصها هذا التعريف، مما يؤدي لفشل دمج المانيفست بالكامل.
رابعاً: صراع العمالقة (AndroidX vs Support Library)
لا يمكن للمشروع أن يعيش بقلبين؛ إما أن تستخدم مكتبات AndroidX الحديثة أو
مكتبات الدعم القديمة. الخلط بينهما هو "تذكرة مجانية" لظهور خطأ Manifest merger failed.
- الحل: تفعيل خاصية Jetifier التي تقوم بتحويل المكتبات القديمة تلقائياً لتتوافق مع AndroidX.
خامساً: تضارب الـ Package Name و Namespace
يحدث عندما يتم تعريف مكتبتين بنفس الـ package في المانيفست، أو وجود تعارض في
تسمية الـ namespace داخل ملفات build.gradle (Kotlin/Groovy).
* الحلول التطبيقية لأكثر 7 حالات تعقيداً لمشكلة Manifest merger failed
لا يتوقف دور المطور المحترف عند معرفة سبب الخطأ، بل يمتد لامتلاك
"الأدوات البرمجية" القادرة على حسم التضاربات بما يتوافق مع رؤية المشروع.
في هذا القسم، سنستعرض السيناريوهات الأكثر تعقيداً التي تسبب فشل
بناء المشروع (Build Failure) ونضع بين يديك الأكواد والحلول الجذرية التي تجبر
نظام Gradle على تجاوز تعنت المكتبات الخارجية.
الحالة 1: تضارب السمات والماكرو السحري (tools:replace)
تعتبر هذه الحالة هي "السيناريو الكلاسيكي" لمعظم أخطاء دمج المانيفست.
تحدث عندما تحاول مكتبة خارجية (Library) فرض قيمة لسمة معينة داخل وسم
<application>، مثل رغبة مكتبة إحصائيات في تفعيل النسخ الاحتياطي
(allowBackup="true") بينما تفرض سياسة تطبيقك تعطيله.
لحل هذا التضارب وفرض إرادتك البرمجية، اتبع الخطوات الدقيقة التالية:
1. تفعيل نظام التحكم (Namespace):
أولاً، يجب أن تعرّف مساحة أسماء "الأدوات" في رأس ملف المانيفست الرئيسي لتمكين أوامر التجاوز:
XML
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.your.project"
xmlns:tools="http://schemas.android.com/tools"> <!-- تفعيل أدوات التحكم -->
--
2. استخدام أمر الاستبدال الجذري:
داخل وسم <application>، قم بتحديد السمات التي تريد استبدالها مهما كان ما تطلبه المكتبات الأخرى:
XML
<application
android:allowBackup="false"
android:theme="@style/AppTheme"
android:label="@string/app_name"
tools:replace="android:allowBackup, android:theme, android:label">
<!-- السطر أعلاه يخبر الـ Merger: "استخدم قيمي أنا وتجاهل البقية" -->
</application>
--
** لماذا هذا هو الحل الأمثل؟
باستخدام tools:replace، أنت تنهي حالة "الحيرة" التي يقع فيها نظام Gradle
عند المقارنة بين ملف المانيفست عالي الأولوية (مشروعك) والملفات منخفضة
الأولوية (المكتبات). هذا الماكرو السحري هو المفتاح الأول لتنظيف سجل الأخطاء من الرسائل الحمراء المزعجة.
الحالة 2: حل مشكلة Android 12 والمكتبات القديمة
إذا كان الخطأ بسبب نقص android:exported في مكتبة خارجية لا تملك السيطرة عليها:
- افتح تبويب Merged Manifest لتحديد الـ Activity المسبب للمشكلة.
- قم بإعادة تعريف هذا الـ Activity في مانيفست مشروعك الرئيسي مع إضافة
android:exported="true" (أو false حسب الحاجة) وستقوم عملية الدمج بتكملة النقص تلقائياً.
الحالة 3: تجاوز متطلبات الـ MinSDK (tools:overrideLibrary)
إذا أصرت مكتبة على إصدار أعلى وأنت متأكد أنها لن تسبب انهياراً لتطبيقك في الإصدارات الأقدم:
XML
<manifest ...>
<uses-sdk tools:overrideLibrary="com.example.problematic.library"/>
</manifest>
--
الحالة 4: حل تضارب الـ Namespace
تأكد في أحدث إصدارات Gradle من تعريف الـ namespace داخل بلوك android في ملف build.gradle:
Gradle
android {
namespace 'com.yourname.project'
// ...
}
--
الحالة 5: تفعيل الـ Jetifier لإنهاء صراع الإصدارات
اذهب إلى ملف gradle.properties وتأكد من وجود الأسطر التالية:
Properties
android.useAndroidX=true
android.enableJetifier=true
--
هذا سيجعل Gradle يعيد صياغة المكتبات القديمة برمجياً لتناسب مشروعك الحديث.
الحالة 6: تضارب الـ Providers (FileProvider)
عند استخدام مكتبات متعددة لفتح الكاميرا أو الملفات، قد يتكرر الـ android:authorities.
* الحل: اجعل الـ authority دائماً فريداً باستخدام الـ ${applicationId}:
android:authorities="${applicationId}.fileprovider"
الحالة 7: خدمات جوجل و Firebase
غالباً ما يحدث التضارب بسبب اختلاف إصدارات play-services.
*الحل: استخدم Firebase BoM (Bill of Materials) لإجبار جميع مكتبات
Firebase و Google على العمل بإصدارات متوافقة مع بعضها البعض تلقائياً دون تدخل منك.
خطوات استخدام أداة Manifest Merger Tool كالمحترفين
لفهم كيفية حل أي خطأ دمج مستقبلاً، يجب أن تدرك أن عملية الدمج
ليست عشوائية بل تخضع لقواعد صارمة تشبه قوانين المرور. أداة Manifest Merger
تعمل بناءً على نظام أولويات يحدد من يملك الكلمة الأخيرة عند حدوث تضارب.
*كيف يعمل الـ Merger ونظام الأولويات؟
عندما يبدأ Gradle في بناء تطبيقك، فإنه يضع ملفات المانيفست في "هرم" من الأولويات:
1- الأولوية العليا (High Priority): ملف المانيفست الرئيسي لمشروعك (الموجود في src/main). قراراتك هنا هي الأهم.
2- الأولوية المتوسطة: ملفات المانيفست الخاصة بنكهات التطبيق (Build Flavors) وأنواع البناء (Debug/Release).
3- الأولوية الدنيا (Low Priority): ملفات المانيفست الموجودة داخل المكتبات الخارجية (Dependencies).
*القاعدة الذهبية: إذا طلبت أنت شيئاً وطلبت المكتبة شيئاً آخر، سيتوقف المحرك
ويسألك عن الحل (الخطأ الشهير)، إلا إذا استخدمت "أدوات السيطرة" لتأكيد أولويتك.
أكواد الحل: تفعيل قوة الـ Tools Namespace
لكي تبدأ في إصدار أوامر التحكم، يجب أولاً تعريف "مساحة الأسماء" (Namespace) الخاصة بالأدوات في رأس ملف AndroidManifest.xml. بدون هذا السطر، لن يفهم أندرويد ستوديو أوامر التجاوز التي ستكتبها.
XML
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.your.package.name"
xmlns:tools="http://schemas.android.com/tools"> ```
--
** أمثلة عملية: كيف تجبر المشروع على تنفيذ قرارك؟
لنفترض أن مكتبة خارجية تفرض ثيماً معايناً يسبب فشل الدمج.
يمكنك استخدام السمة `tools:replace` أو `tools:node` للسيطرة:
*استبدال سمة معينة: لفرض "أيقونة" التطبيق الخاصة بك وتجاهل أي أيقونة تأتي من مكتبة خارجية:
`tools:replace="android:icon, android:theme"`
*حذف عنصر بالكامل: إذا كانت هناك مكتبة تضيف "صلاحية" (Permission) لا تريدها
في تطبيقك، يمكنك حذفها برمجياً أثناء الدمج:
`<uses-permission android:name="android.permission.SEND_SMS" tools:node="remove" />`
--
نصائح هامة لتجنب مشاكل المانيفست في المشاريع المعقدة
الوقاية دائماً أفضل من قضاء ساعات في قراءة سجلات الأخطاء.
إليك استراتيجيات المطورين المحترفين في عام 2026 للحفاظ على سلامة مشاريعهم المعقدة.
1- تحديث المكتبات بانتظام: تقليل احتمالية التضارب
أغلب أخطاء المانيفست (خاصة المتعلقة بـ `android:exported`)
تظهر بسبب استخدام مكتبات قديمة لم تواكب تحديثات أندرويد.
*النصيحة : استخدم خاصية Project Structure في أندرويد ستوديو لمراقبة التحديثات، أو استخدم إضافات مثل Version Catalog لتوحيد إصدارات المكتبات وضمان توافقها مع إصدار الـ SDK الخاص بك.
2- تنظيف المشروع (Clean & Rebuild): الخطوة السحرية
أحياناً ينجح الدمج تقنياً، لكن تظل هناك ملفات "مؤقتة" (Cache) قديمة تسبب تعارضاً وهمياً.
* لماذا تعمل؟ عملية Clean Project تقوم بحذف مجلد `build` بالكامل، مما يجبر Gradle على إعادة تشغيل الـ Manifest Merger من الصفر على نظافة، وهو ما يحل الكثير من الأخطاء التي تظهر بعد تعديل ملفات `build.gradle`.
3- مراقبة الـ Dependency Tree: كشف المشاكل الخفية
قد تضيف مكتبة واحدة بسيطة، وتفاجأ بأنها قامت بجلب 10 مكتبات أخرى خلفها
(Transitive Dependencies)، واحدة منها هي المسببة للخطأ.
**الأمر السحري: افتح الـ Terminal واكتب:
`./gradlew app:dependencies`
*الفائدة: سيعرض لك شجرة كاملة توضح كل مكتبة ومن أين أتت، مما يسهل عليك
تحديد المكتبة القديمة التي تسبب تضارب المانيفست لاستبعادها (Exclude) أو تحديثها.
مقالات ذات صلة :
* متى يكون حذف مجلد .gradle و .idea هو الحل الأخير؟
إذا قمت بكل شيء ولا يزال الخطأ يظهر (رغم أن الكود سليم 100%)،
فقد يكون هناك فساد في ملفات إعدادات بيئة التطوير نفسها.
* الحل النووي: أغلق أندرويد ستوديو، اذهب لمجلد المشروع، واحذف مجلد
`.gradle` (الذي يحتوي على الكاش الثقيل) ومجلد `.idea` (إعدادات المشروع).
عند إعادة فتح المشروع، سيقوم أندرويد ستوديو ببناء كل شيء من الصفر
وكأنك قمت بتحميله للتو، وغالباً ما تنتهي المشكلة هنا.
الأسئلة الشائعة حول Manifest merger failed
- هل مسح مجلد الـ .gradle يحل المشكلة دائماً؟
ليس دائماً، لكنه يحل المشاكل الناتجة عن كاش فاسد. إذا كان الخطأ برمجياً
(تضارب سمات)، فالمسح لن يفيد ويجب استخدام tools:replace.
- ماذا أفعل إذا كان الخطأ من مكتبة خارجية لا يمكنني تعديل كودها؟
هذا هو دور المانيفست الرئيسي في مشروعك؛ يمكنك إعادة تعريف العنصر المسبب للمشكلة
وإضافة tools:node="merge" أو tools:replace للسيطرة عليه من الخارج.
- لماذا ينجح البناء (Build) أحياناً ويفشل عند محاولة توليد الـ APK؟
لأن عملية توليد الـ APK (أو الـ Bundle) تقوم بعملية دمج نهائية وشاملة لكل الموارد،
وتفحص القيود بدقة أكبر من مجرد البناء السريع للمحاكي.
- هل يؤثر استخدام الـ Jetifier على وقت بناء المشروع؟
نعم، يزيد قليلاً من وقت البناء لأنه يحول المكتبات القديمة برمجياً، لكنه ضروري جداً
لمنع تضارب المانيفست بين مكتبات AndroidX والمكتبات القديمة.
- كيف أتأكد من أن مشكلة android:exported قد حُلت بالكامل؟
بعد محاولة الإصلاح، افتح تبويب Merged Manifest؛ إذا لم تجد أي علامات حمراء،
ووجد سطر android:exported موجوداً في كل المكونات، فأنت في أمان.
- هل يمكن أن يتسبب تكرار اسم الـ Package في فشل الدمج؟
بكل تأكيد، لا يمكن دمج ملفين لهما نفس معرف الحزمة (Package ID) إذا كان لكل منهما
سمات مختلفة، ويجب توحيدها أو تغيير أحدهما.
الخاتمة
يعتبر خطأ Manifest merger failed اختباراً حقيقياً لمهاراتك كمطور أندرويد
في إدارة المشاريع المعقدة. من خلال فهمك لنظام الأولويات واستخدام أدوات
التشخيص مثل Merged Manifest و Versions Catalog، لن تعود رسائل
الخطأ الحمراء عائقاً أمام إبداعك. تذكر دائماً أن نظام Gradle هو صديقك،
وكل ما يحتاجه هو تعليمات واضحة منك لحل النزاعات البرمجية.