إدارة ملفات البيان

توضّح هذه الصفحة آلية دمج البيان وكيفية تطبيق إعدادات دمج المفضّلة لمعالجة تعارضات الدمج. للحصول على مقدمة عن ملف بيان التطبيق، يُرجى الاطّلاع على نظرة عامة على بيان التطبيق.

دمج ملفات بيان متعددة

يمكن أن يحتوي ملف APK أو حزمة Android App Bundle على ملفAndroidManifest.xml واحد فقط، ولكن قد يحتوي مشروعك على Android Studio على عدة ملفات بيان يوفّرها مجموعة المصادر الرئيسية ونُسخ الإصدار والمكتبات المستورَدة. عند إنشاء تطبيقك، يُدمج Gradle جميع ملفات البيان في ملف بيان واحد يتم حزمه في تطبيقك.

تجمع أداة دمج البيان جميع عناصر XML من كل ملف من خلال اتّباع قواعد النهمك للدمج والالتزام بالخيارات المفضّلة للدمج التي حدّدتها باستخدام سمات XML خاصة.

ملاحظة: استخدِم عرض البيان المدمج، الموضّح في القسم التالي، لمعاينة نتائج البيان المدمج والعثور على أخطاء التضارب.

دمج الأولويات

تجمع أداة الدمج جميع ملفات البيان في ملف واحد بشكل تسلسلي، استنادًا إلى الأولوية لكل ملف بيان. على سبيل المثال، إذا كان لديك ثلاثة ملفات بيان، يتم دمج ملف البيان الأقل أولوية في ملف البيان التالي الأعلى أولوية، ثم يتم دمج هذا الملف فيملف البيان الأكثر أولوية، كما هو موضّح في الشكل 1.

الشكل 1. عملية دمج ثلاثة ملفات بيان ، من أدنى أولوية إلى أعلى أولوية

هناك ثلاثة أنواع أساسية من ملفات البيان التي يمكن دمجها معًا، وأولويات الدمج هي كما يلي (الأولوية الأعلى أولاً):

  1. ملف البيان الخاص بنوع الإصدار

    إذا كانت لديك مجموعات مصادر متعددة لخيار المنتج، تكون أولويات البيان على النحو التالي:

    • ملف بيان خيار التصميم (مثل src/demoDebug/)
    • ملف بيان نوع الإصدار (مثل src/debug/)
    • بيان نكهة المنتج (مثل src/demo/)

      إذا كنت تستخدِم سمات النكهات، تتوافق أولويات البيان مع ترتيب كل سمة في ملف flavorDimensions (الأول هو الأعلى أولوية).

  2. ملف البيان الرئيسي لمكوّن التطبيق
  3. ملف البيان من مكتبة مضمّنة

    إذا كانت لديك مكتبات متعددة، تتطابق أولويات ملف البيان الخاصة بها مع ترتيب ظهورها في كتلة Gradle dependencies.

على سبيل المثال، يتم دمج بيان مكتبة في البيان الرئيسي، ثم يتم دمج البيان الرئيسي في بيان الصيغة. تجدر الإشارة إلى أنّ هذه هي أولى أولويات الدمج لجميع مجموعات المصادر، كما هو موضّح في الإنشاء باستخدام مجموعات المصادر.

ملاحظة مهمة: تلغي إعدادات الإنشاء من ملف build.gradle أي سمات مقابلة فيملف البيان المدمج. على سبيل المثال، تلغي سمة minSdk من ملف build.gradle أوملف build.gradle.kts السمة المطابقة في عنصر <uses-sdk> البيان. لتجنّب حدوث أي التباس، اترك عنصر <uses-sdk> وحدِّد هذه السمات في ملف build.gradle فقط. لمزيد من التفاصيل، يُرجى الاطّلاع على مقالة ضبط الإصدار.

الإعدادات الإرشادية لحل تعارض الدمج

يمكن لأداة الدمج مطابقة كل عنصر XML من بيان واحد مع عنصر مماثل في بيان آخر بشكل منطقي. لمعرفة تفاصيل عن آلية عمل المطابقة، يُرجى الاطّلاع على أولويات الدمج في القسم السابق.

إذا لم يتطابق عنصر من البيان الأقل أولوية مع أي عناصر في البيان الأعلى أولوية، تتم إضافته إلى البيان المدمج. ومع ذلك، إذا كان هناك عنصر مطابق، تحاول أداة الدمج دمج كل السمات من كل عنصر في العنصر نفسه. إذا تبيّن للّأداة أنّ كلاً من البيانَين يحتويان على السمة نفسها بقيم مختلفة، يحدث تعارض في الدمج.

يوضّح الجدول 1 النتائج المحتمَلة عندما تحاول أداة الدمج دمج جميع السمات في العنصر نفسه.

الجدول 1: السلوك التلقائي للدمج لقيم السمة

سمة ذات أولوية عالية سمة ذات أولوية منخفضة نتيجة دمج السمة
بلا قيمة بلا قيمة لا قيمة (استخدام القيمة التلقائية)
القيمة ب القيمة ب
القيمة "أ" بلا قيمة القيمة "أ"
القيمة "أ" القيمة "أ"
القيمة ب خطأ تعارض: يجب إضافة علامة قاعدة الدمج.

ومع ذلك، هناك بعض الحالات التي تتصرف فيها أداة الدمج بشكلٍ مختلف لتجنُّب تعارضات الدمج:

  • لا يتم أبدًا دمج السمات في العنصر <manifest> معًا، بل يتم استخدام السمات من البيان الأعلى أولوية فقط.
  • تستخدم السمة android:required في العنصرين <uses-feature> و <uses-library> دمجًا من النوع أو. في حال حدوث تعارض، يتم تطبيق "true" ويتم دائمًا تضمين الميزة أو المكتبة المطلوبة في بيان واحد.
  • تستخدم السمات في عنصر <uses-sdk> دائمًا القيمة الواردة منملف البيان ذي الأولوية الأعلى، باستثناء الحالات التالية:
    • عندما يكون البيان الأقل أولوية يحتوي على قيمة minSdk أعلى، يحدث خطأ ما لم يتم تطبيق قاعدة الدمج overrideLibrary.
    • عندما يكون لملف البيان الأقل أولوية قيمة targetSdkVersion أقل، تستخدم أداة الدمج القيمة من ملف البيان الأعلى أولوية، وتضيف أيضًا أي أذونات نظام ضرورية لضمان استمرار عمل المكتبة المستورَدة بشكل صحيح (في الحالات التي يتضمّن فيها إصدار Android الأعلى قيودًا متزايدة على الأذونات). لمزيد من المعلومات عن هذا السلوك، يُرجى الاطّلاع على القسم المعنيّبأذونات النظام التلقائية.
  • لا تتم مطابقة عنصر <intent-filter> مطلقًا بين بيانات البيان. ويتم التعامل مع كل ملف على أنّه فريد ويتم إضافته إلى العنصر الرئيسي المشترك في البيان المدمج.

بالنسبة إلى جميع التعارضات الأخرى بين السمات، ستظهر لك رسالة خطأ وعليك توجيه أداة الدمج إلى كيفية حلّها من خلال إضافة سمة خاصة في ملف البيان الذي يتمتع بأولوية أعلى. راجِع القسم التالي عن علامات قواعد الدمج.

لا تعتمد على قيم السمات التلقائية. وبما أنّه يتم دمج كل السمات الفريدة في العنصر نفسه، قد يؤدي ذلك إلى اختلاف النتائج غير المتوقّعة إذا كان البيان الأعلى أولوية يعتمد في الواقع على القيمة التلقائية لسمة معيّنة بدون تحديدها. على سبيل المثال، إذا لم يُعلن ملف البيان الذي يتمتع بأولوية أعلى عن سمة android:launchMode ، يتم استخدام القيمة التلقائية "standard"، ولكن إذا أعلن ملف البيان الذي يتمتع بأولوية أقل عن هذه السمة بقيمة مختلفة، يتم تطبيق هذه القيمة على ملف البيان المدمج، ما يؤدي إلى إلغاء القيمة التلقائية. عليك تحديد كل سمة على النحو الذي تريده. يتم توثيق القيم التلقائية لكل سمة في مرجع البيان.

دمج علامات القواعد

علامة قاعدة الدمج هي سمة XML يمكنك استخدامها للتعبير عن تفضيلك بشأن كيفية حلّ تعارضات الدمج أو إزالة العناصر والسمات غير المرغوب فيها. يمكنك تطبيق علامة على عنصر كامل أو على سمات معيّنة فقط في عنصر.

عند دمج ملفي بيان، تبحث أداة الدمج عن هذه العلامات في ملف البيان الأعلى أولوية.

تنتمي جميع العلامات إلى مساحة الاسم tools في Android، لذا عليك أولاً تعريف مساحة الاسم هذه في عنصر <manifest>، كما هو موضّح هنا:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapp"
    xmlns:tools="http://schemas.android.com/tools">

علامات العقد

لتطبيق قاعدة دمج على عنصر XML كامل (على جميع السمات في عنصر بيان معيّن وعلى جميع علاماته الفرعية)، استخدِم السمات التالية:

tools:node="merge"
دمج جميع السمات في هذه العلامة وجميع العناصر المضمّنة في حال عدم حدوث تعارض باستخدام الاستدلالات heuristics الخاصة بدمج التعارض هذا هو السلوك التلقائي للعناصر.

بيان التطبيقات ذات الأولوية المنخفضة:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

بيان ذو أولوية عالية:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:node="merge">
</activity>

نتيجة ملف البيان المدمج:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>
tools:node="merge-only-attributes"
ادمج السمات في هذه العلامة فقط، ولا تدمج العناصر المُدمجة.

بيان التطبيقات ذات الأولوية المنخفضة:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <data android:type="image/*" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

بيان ذو أولوية عالية:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:node="merge-only-attributes">
</activity>

نتيجة البيان المدمج:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
</activity>
tools:node="remove"
أزِل هذا العنصر من بيان التطبيق المدمج. يُستخدَم عند اكتشاف عنصر في البيان المدمج لا تحتاج إليه تم توفيره من خلال ملف بيان ذو أولوية أقل خارج نطاق تحكّمك (مثل مكتبة مستورَدة).

بيان التطبيقات ذات الأولوية المنخفضة:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      android:value="@string/moo"/>
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>

بيان ذو أولوية عالية:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      tools:node="remove"/>
</activity-alias>

نتيجة ملف البيان المدمج:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>
tools:node="removeAll"
يشبه tools:node="remove"، ولكنه يزيل كل العناصر التي تتطابق مع نوع العنصر هذا (ضمن العنصر الرئيسي نفسه).

بيان التطبيقات ذات الأولوية المنخفضة:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      android:value="@string/moo"/>
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>

بيان ذو أولوية عالية:

<activity-alias android:name="com.example.alias">
  <meta-data tools:node="removeAll"/>
</activity-alias>

نتيجة البيان المدمج:

<activity-alias android:name="com.example.alias">
</activity-alias>
tools:node="replace"
استبدِل العنصر الأقلّ أولوية بالكامل. وهذا يعني أنّه إذا كان هناك عنصر مطابق في بيان الأولوية الأقل، عليك تجاهله واستخدام هذا العنصر تمامًا كما يظهر في هذا البيان.

بيان التطبيقات ذات الأولوية المنخفضة:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="cow"
      android:value="@string/moo"/>
  <meta-data android:name="duck"
      android:value="@string/quack"/>
</activity-alias>

بيان ذو أولوية عالية:

<activity-alias android:name="com.example.alias"
    tools:node="replace">
  <meta-data android:name="fox"
      android:value="@string/dingeringeding"/>
</activity-alias>

نتيجة البيان المدمج:

<activity-alias android:name="com.example.alias">
  <meta-data android:name="fox"
      android:value="@string/dingeringeding"/>
</activity-alias>
tools:node="strict"
إنشاء خطأ في عملية الإنشاء في أي وقت لا يتطابق فيه هذا العنصر في بيان الالتفاف الأقلّ أولويةً مع العنصر في بيان الالتفاف الأعلى أولويةً (ما لم يتم حلّه بواسطة علامات قواعد الدمج الأخرى). يؤدي ذلك إلى إلغاء القواعد المستندة إلى التجربة والخطأ في حل تعارض الدمج. على سبيل المثال، إذا كان البيان الأقلّ أولوية يتضمّن سمة إضافية، لن يتمكّن الإصدار من الإنشاء (في حين أنّ السلوك التلقائي يضيف السمة الإضافية إلى البيان المدمج).

بيان التطبيقات ذات الأولوية المنخفضة:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">
    <intent-filter>
        <action android:name="android.intent.action.SEND" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

بيان ذو أولوية عالية:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:node="strict">
</activity>

يؤدي ذلك إلى حدوث خطأ في دمج البيان. لا يمكن أن يختلف عنصرَا البيان أبدًا في الوضع الصارم. يجب تطبيق علامات قواعد الدمج الأخرى لحلّ هذه الاختلافات. (بدون tools:node="strict"، يمكن دمج هذين الملفَّين معًا بدون أخطاء، كما هو موضّح في مثال tools:node="merge").

علامات السمات

لتطبيق قاعدة دمج على سمات معيّنة فقط في علامة بيان التطبيق بدلاً من ذلك، استخدِم السمات التالية: تقبل كل سمة اسم سمة واحدًا أو أكثر (بما في ذلك مساحة اسم السمة)، مع الفصل بينها بفواصل.

tools:remove="attr, ..."
أزِل السمات المحدّدة من البيان المدمج. يُستخدَم هذا الخيار عندما يتضمّن ملف البيان الأقلّ أولوية هذه السمات وتريد التأكّد من عدم إدراجها في ملف البيان المدمج.

بيان التطبيقات ذات الأولوية المنخفضة:

<activity android:name="com.example.ActivityOne"
    android:windowSoftInputMode="stateUnchanged">

بيان ذو أولوية عالية:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:remove="android:windowSoftInputMode">

نتيجة البيان المدمج:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait">
tools:replace="attr, ..."
استبدِل السمات المحدّدة في البيان الأقلّ أولوية بتلك الواردة في هذا البيان. بعبارة أخرى، احتفِظ دائمًا بملف البيان الذي يضم القيم ذات الأولوية الأعلى.

بيان التطبيقات ذات الأولوية المنخفضة:

<activity android:name="com.example.ActivityOne"
    android:theme="@oldtheme"
    android:exported="false"
    android:windowSoftInputMode="stateUnchanged">

بيان ذو أولوية عالية:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    tools:replace="android:theme,android:exported">

نتيجة البيان المدمج:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    android:windowSoftInputMode="stateUnchanged">
tools:strict="attr, ..."
تؤدي هذه السمات في ملف البيان الذي يتمتع بأولوية أقل إلى حدوث خطأ في عملية الإنشاء في حال عدم تطابقها تمامًا مع السمات في ملف البيان الذي يتمتع بأولوية أعلى. هذا هو السلوك التلقائي لجميع السمات، باستثناء السمات التي لها سلوكيات خاصة كما هو موضّح في القواعد الاستقرائية لصراع الدمج.

بيان التطبيقات ذات الأولوية المنخفضة:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="landscape">
</activity>

بيان ذو أولوية عالية:

<activity android:name="com.example.ActivityOne"
    android:screenOrientation="portrait"
    tools:strict="android:screenOrientation">
</activity>

يؤدي ذلك إلى حدوث خطأ في دمج البيان. يجب تطبيق علامات أخرى لقاعدة الدمج لحلّ التعارض. وهذا هو السلوك التلقائي، لذا تظهر النتيجة نفسها عند إضافة tools:strict="screenOrientation" بشكل صريح.

يمكنك أيضًا تطبيق علامات متعدّدة على عنصر واحد، كما هو موضّح في المثال التالي:

بيان التطبيقات ذات الأولوية المنخفضة:

<activity android:name="com.example.ActivityOne"
    android:theme="@oldtheme"
    android:exported="false"
    android:allowTaskReparenting="true"
    android:windowSoftInputMode="stateUnchanged">

بيان ذو أولوية عالية:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:screenOrientation="portrait"
    tools:replace="android:theme,android:exported"
    tools:remove="android:windowSoftInputMode">

نتيجة البيان المدمج:

<activity android:name="com.example.ActivityOne"
    android:theme="@newtheme"
    android:exported="true"
    android:allowTaskReparenting="true"
    android:screenOrientation="portrait">

أداة اختيار محدِّد الموقع الجغرافي

إذا كنت تريد تطبيق علامات قاعدة الدمج على مكتبة مستورَدة معيّنة فقط، أضِف سمة tools:selector مع اسم حزمة المكتبة.

على سبيل المثال، في البيان التالي، لا يتم تطبيق قاعدة الدمج remove إلا عندما يكون ملف البيان الأقلّ أولوية من مكتبة com.example.lib1:

<permission android:name="permissionOne"
    tools:node="remove"
    tools:selector="com.example.lib1">

إذا كان البيان ذو الأولوية الأقلّ مصدره أي مصدر آخر، يتم تجاهل قاعدة دمج remove.

ملاحظة: إذا استخدمت هذا الإجراء مع أحد علامات السمات، ينطبق ذلك على جميع السمات المحدّدة في العلامة.

إلغاء القيمة <uses-sdk> للمكتبات المستورَدة

بشكلٍ تلقائي، عند استيراد مكتبة ذات قيمة minSdk أكبر من قيمة ملف البيان الرئيسي، يحدث خطأ ولا يمكن استيراد المكتبة.

لجعل أداة الدمج تتجاهل هذا التعارض و تستورِد المكتبة مع الاحتفاظ بالقيمة الأقل لسمة minSdk في تطبيقك، أضِف سمة overrideLibrary إلى علامة <uses-sdk>. يمكن أن تكون قيمة السمة اسم حزمة مكتبة واحدًا أو أكثر (مفصولة بفواصل)، ما يشير إلى المكتبات التي يمكنها إلغاء minSdk في البيان الرئيسي.

على سبيل المثال، إذا كان ملف البيان الرئيسي لتطبيقك يطبّق overrideLibrary على النحو التالي:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.app"
          xmlns:tools="http://schemas.android.com/tools">
  <uses-sdk tools:overrideLibrary="com.example.lib1, com.example.lib2"/>
...

بعد ذلك، يمكن دمج البيان التالي بدون خطأ بشأن علامة <uses-sdk>، ويحتفظ البيان المدمج بعلامة minSdk="2" من بيان التطبيق.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.example.lib1">
   <uses-sdk android:minSdk="4" />
...

أذونات النظام الضمنية

في الإصدارات الحديثة من Android، تم حظر بعض واجهات برمجة تطبيقات Android التي كانت التطبيقات تحصل على إذن الوصول إليها مجانًا من خلال أذونات النظام.

لتجنُّب إيقاف التطبيقات التي تتوقّع الوصول إلى واجهات برمجة التطبيقات هذه، تسمح الإصدارات الحديثة من Android للتطبيقات بمواصلة الوصول إلى واجهات برمجة التطبيقات هذه بدون الإذن إذا تم ضبط targetSdkVersion على قيمة أقل من الإصدار الذي تمت فيه إضافة القيود. يمنح هذا السلوك التطبيق إذنًا ضمنيًا للسماح بالوصول إلى واجهات برمجة التطبيقات. يمكن أن تتأثر ملفات البيان المُدمَجة التي تحتوي على قيم مختلفة لtargetSdkVersion.

إذا كان ملف البيان ذو الأولوية الأقل يحتوي على قيمة أقل لملف البيان targetSdkVersion تمنح الإذن الضمني، ولا يحتوي ملف البيان ذي الأولوية الأعلى على الإذن الضمني نفسه (لأنّ targetSdkVersion يساوي أو يتجاوز الإصدار الذي تمت فيه إضافة القيود)، تُضيف أداة الدمج بوضوح إذن النظام إلى ملف البيان المدمج.

على سبيل المثال، إذا ضبط تطبيقك القيمة targetSdkVersion على 4 أو أعلى وأستورَد مكتبة تم ضبط القيمة targetSdkVersion فيها على 3 أو أقل، تُضيف أداة الدمج الإذن WRITE_EXTERNAL_STORAGE إلى البيان المدمج.

يسرد الجدول 2 جميع الأذونات المحتملة التي يمكن إضافتها إلى البيان المدمج:

الجدول 2: قائمة الأذونات التي قد تضيفها أداة الدمج إلى البيان المدمج

بيانات البيان ذات الأولوية المنخفضة الأذونات التي تمت إضافتها إلى البيان المدمج
targetSdkVersion هي 3 أو أقل "WRITE_EXTERNAL_STORAGE" و"READ_PHONE_STATE"
إصدار targetSdkVersion هو 15 أو إصدار أقدم ويستخدم READ_CONTACTS READ_CALL_LOG
إصدار targetSdkVersion هو 15 أو إصدار أقدم ويستخدم WRITE_CONTACTS WRITE_CALL_LOG

فحص البيان المدمج والعثور على التعارضات

حتى قبل إنشاء تطبيقك، يمكنك الاطّلاع على معاينة لشكل البيان المُدمَج. للاطّلاع على معاينة، اتّبِع الخطوات التالية:

  1. في Android Studio، افتح ملف AndroidManifest.xml.
  2. انقر على علامة التبويب بيان الدمج في أسفل المحرِّر.

تعرِض طريقة عرض "بيان مُدمَج" نتائج البيان المُدمَج على يمين الشاشة، ومعلومات عن كل ملف بيان مُدمَج على يسار الشاشة، كما هو موضّح في الشكل 2.

يتم تمييز العناصر التي تم دمجها من ملفات البيان ذات الأولوية الأقل بألوان مختلفة على يمين الصفحة. يتم تحديد مفتاح كل لون ضمن مصادر البيان.

الشكل 2: عرض "ملف البيان المدمج"

يتم إدراج ملفات البيان التي كانت جزءًا من الحزمة ولكنّها لم تساهم في إضافة عناصر أو سمات ضمن ملفات البيان الأخرى.

للاطّلاع على معلومات عن مصدر عنصر معيّن، انقر عليه في اللوحة اليسرى، وستظهر التفاصيل ضمن سجلّ الدمج.

في حال حدوث أي تعارضات، ستظهر ضمن أخطاء الدمج مع اقتراح حول كيفية حلّ التعارض باستخدام علامات قواعد الدمج.

تتم أيضًا طباعة الأخطاء في نافذة سجلّ الأحداث. لعرضها، اختَر عرض > نوافذ الأدوات > سجلّ الأحداث.

للاطّلاع على سجلّ كامل لشجرة القرارات الخاصة بالدمج، يمكنك العثور علىملف السجلّ في دليل build/outputs/logs/ الخاص بالوحدة، والذي يحمل الاسم manifest-merger-buildVariant-report.txt.

دمج السياسات

يمكن لأداة دمج ملفات البيان مطابقة كل عنصر XML من ملف بيان واحد مع عنصر مقابل في ملف آخر بشكل منطقي. تطابق عملية الدمج كل عنصر باستخدام مفتاح مطابقة، إما قيمة سمة فريدة (مثل android:name) أو الفريدة الطبيعية للعلامة نفسها (على سبيل المثال، لا يمكن أن يكون هناك سوى عنصر <supports-screen> واحد).

إذا كان هناك بيانان يتضمّنان عنصر XML نفسه، تدمج الأدوات العنصرَين معًا باستخدام إحدى سياسات الدمج الثلاث التالية:

دمج
ادمج كل السمات غير المتعارضة في العلامة نفسها وادمج العناصر الفرعية وفقًا لسياسة الدمج الخاصة بها. إذا تعارضت أيّ سمات مع بعضها، يمكنك دمجها معًا باستخدام علامات قاعدة الدمج.
دمج العناصر الثانوية فقط
لا تُدمج السمات أو تجرِّبها (احتفظ فقط بالسمات التي يقدّمهاملف البيان الذي يتمتع بأعلى أولوية) ودمج العناصر الفرعية وفقًا لسياسة الدمج.
Keep
اترك العنصر كما هو وأضفه إلى العنصر الرئيسي المشترَك في الملف المجمّع. لا يتم استخدام هذا العنصر إلا عندما يكون من المقبول أن يكون هناك عدة تعريفات للعنصر نفسه.

يسرد الجدول 3 كل نوع عنصر ونوع سياسة الدمج المستخدَمة ومفتاح المستخدَم لتحديد تطابق عنصر بين بيانَين:

الجدول 3: سياسات دمج عناصر البيان ومفاتيح المطابقة

العنصر سياسة الدمج مفتاح المطابقة
<action> دمج سمة android:name
<activity> دمج سمة android:name
<application> دمج يمكن إضافة علامة واحدة فقط لكل <manifest>.
<category> دمج سمة android:name
<data> دمج يمكن إضافة علامة واحدة فقط لكل <intent-filter>.
<grant-uri-permission> دمج يمكن إضافة علامة واحدة فقط لكل <provider>.
<instrumentation> دمج سمة android:name
<intent-filter> Keep لا تتطابق العناصر، ويُسمح بالعديد من التصريحات ضمن العنصر الرئيسي.
<manifest> دمج العناصر الثانوية فقط هناك علامة واحدة فقط لكل ملف.
<meta-data> دمج سمة android:name
<path-permission> دمج يمكن إضافة علامة واحدة فقط لكل <provider>.
<permission-group> دمج سمة android:name
<permission> دمج سمة android:name
<permission-tree> دمج سمة android:name
<provider> دمج سمة android:name
<receiver> دمج سمة android:name
<screen> دمج سمة android:screenSize
<service> دمج سمة android:name
<supports-gl-texture> دمج سمة android:name
<supports-screen> دمج يمكن إضافة علامة واحدة فقط لكل <manifest>.
<uses-configuration> دمج يمكن إضافة علامة واحدة فقط لكل <manifest>.
<uses-feature> دمج سمة android:name (إذا لم تكن متوفّرة، سمة android:glEsVersion)
<uses-library> دمج سمة android:name
<uses-permission> دمج سمة android:name
<uses-sdk> دمج يمكن إضافة علامة واحدة فقط لكل <manifest>.
العناصر المخصّصة دمج لا تتطابق مع أي بيانات في أداة الدمج، ويتم تضمينها دائمًا في البيان المدمج.

إدراج متغيّرات الإنشاء في ملف البيان

إذا كنت بحاجة إلى إدراج متغيّرات في ملف AndroidManifest.xml تم تحديدها في ملف build.gradle، يمكنك إجراء ذلك باستخدام السمة manifestPlaceholders. يأخذ هذا السمة خريطة لأزواج المفاتيح والقيم، كما هو موضّح هنا:

رائعKotlin
android {
    defaultConfig {
        manifestPlaceholders = [hostName:"www.example.com"]
    }
    ...
}
android {
    defaultConfig {
        manifestPlaceholders["hostName"] = "www.example.com"
    }
    ...
}

يمكنك بعد ذلك إدراج أحد العناصر النائبة في ملف البيان على أنّه قيمة سمة:

<intent-filter ... >
    <data android:scheme="https" android:host="${hostName}" ... />
    ...
</intent-filter>

توفّر أدوات الإنشاء تلقائيًا أيضًا معرّف التطبيق لتطبيقك في العنصر النائب ${applicationId}. تتطابق القيمة دائمًا مع معرّف التطبيق النهائي للإصدار الحالي، بما في ذلك التغييرات حسب أنواع الإصدار. يكون ذلك مفيدًا عندما تريد استخدام مساحة اسم فريدة للمعرّفات، مثل إجراء نية، حتى بين صيغ الإصدار.

على سبيل المثال، إذا كان ملف build.gradle يبدو على النحو التالي:

رائعKotlin
android {
    defaultConfig {
        applicationId "com.example.myapp"
    }
    flavorDimensions "type"
    productFlavors {
        free {
            applicationIdSuffix ".free"
            dimension "type"
        }
        pro {
            applicationIdSuffix ".pro"
            dimension "type"
        }
    }
}
android {
    defaultConfig {
        applicationId = "com.example.myapp"
    }
    flavorDimensions += "type"
    productFlavors {
        create("free") {
            applicationIdSuffix = ".free"
            dimension = "type"
        }
        create("pro") {
            applicationIdSuffix = ".pro"
            dimension = "type"
        }
    }
}

يمكنك بعد ذلك إدراج معرّف التطبيق في ملف البيان على النحو التالي:

<intent-filter ... >
    <action android:name="${applicationId}.TRANSMOGRIFY" />
    ...
</intent-filter>

في ما يلي نتيجة البيان عند إنشاء إصدار المنتج "المجاني":

<intent-filter ... >
   <action android:name="com.example.myapp.free.TRANSMOGRIFY" />
    ...
</intent-filter>

لمزيد من المعلومات، يُرجى الاطّلاع على مقالة ضبط رقم تعريف التطبيق.