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

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

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

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

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

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

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

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

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

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

  1. ملف البيان لصيغة الإصدار

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

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

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

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

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

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

ملاحظة مهمّة: يؤدي إنشاء الإعدادات من ملف 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"
ادمج جميع السمات في هذه العلامة وجميع العناصر المدمجة في حال عدم وجود تعارض باستخدام الاستدلالات حول تعارُض الدمج. هذا هو السلوك التلقائي للعناصر.

بيان الأولوية المنخفضة:

<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"، افتح ملف AndroidManifest.xml.
  2. انقر على علامة التبويب البيان المدمج في أسفل المحرِّر.

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

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

الشكل 2. عرض البيان المدمج

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

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

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

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

للاطّلاع على سجل كامل لشجرة قرارات الدمج، يمكنك العثور على ملف السجل في دليل 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. تأخذ هذه الخاصية خريطة لأزواج المفتاح/القيمة، كما هو موضّح هنا:

رائع

android {
    defaultConfig {
        manifestPlaceholders = [hostName:"www.example.com"]
    }
    ...
}

Kotlin

android {
    defaultConfig {
        manifestPlaceholders["hostName"] = "www.example.com"
    }
    ...
}

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

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

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

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

رائع

android {
    defaultConfig {
        applicationId "com.example.myapp"
    }
    flavorDimensions "type"
    productFlavors {
        free {
            applicationIdSuffix ".free"
            dimension "type"
        }
        pro {
            applicationIdSuffix ".pro"
            dimension "type"
        }
    }
}

Kotlin

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>

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