مدیریت فایل‌های مانیفست

این صفحه نحوه عملکرد ادغام مانیفست و نحوه اعمال اولویت‌های ادغام برای حل تعارض‌های ادغام را شرح می‌دهد. برای آشنایی با فایل مانیفست برنامه، نمای کلی مانیفست برنامه را ببینید.

ادغام کردن چند فایل مانیفست

فایل APK یا «بسته ترکیبی برنامه Android» شما می‌تواند فقط حاوی یک فایل AndroidManifest.xml باشد، اما پروژه Android Studio شما ممکن است حاوی چندین فایل مانیفست ارائه‌شده توسط مجموعه منبع اصلی، تنوع‌های ساخت، و کتابخانه‌های واردشده باشد. هنگام ساختن برنامه، Gradle build همه فایل‌های مانیفست را در یک فایل مانیفست واحد ادغام می‌کند که در برنامه شما بسته‌بندی می‌شود.

ابزار ادغام مانیفست همه عناصر XML را از هر فایل با دنبال کردن اکتشافات ادغام و پیروی از اولویت‌های ادغامی که با مشخصه‌های XML خاص تعریف کرده‌اید ترکیب می‌کند.

نکته: از نمای مانیفست ادغام‌شده که در بخش بعدی شرح داده شده است برای پیش‌دید کردن نتایج مانیفست ادغام‌شده و پیدا کردن خطاهای تداخل استفاده کنید.

ادغام اولویت‌ها

ابزار ادغام همه فایل‌های مانیفست را به‌صورت متوالی و براساس اولویت هر فایل مانیفست در یک فایل ترکیب می‌کند. برای مثال، اگر سه فایل مانیفست داشته باشید، مانیفست با کمترین اولویت در مانیفست با اولویت بالاتر بعدی ادغام می‌شود و سپس آن مانیفست در مانیفست با بالاترین اولویت ادغام می‌شود، همان‌طور که در شکل ۱ نشان داده شده است.

شکل ۱. فرایند ادغام سه فایل مانیفست، از کمترین اولویت به بیشترین اولویت.

سه نوع اصلی فایل مانیفست وجود دارد که ممکن است در یکدیگر ادغام شوند و اولویت‌های ادغام آن‌ها به‌صورت زیر است (بالاترین اولویت در ابتدا):

  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 را از یک مانیفست با عنصر متناظر در مانیفست دیگر مطابقت دهد. برای جزئیات درباره نحوه عملکرد مطابقت، به اولویت‌های ادغام در بخش قبلی مراجعه کنید.

اگر عنصری از مانیفست با اولویت پایین‌تر با هیچ عنصری در مانیفست با اولویت بالاتر مطابقت نداشته باشد، به مانیفست ادغام‌شده اضافه می‌شود. بااین‌حال، اگر عنصر منطبقی وجود داشته باشد، ابزار ادغام تلاش می‌کند همه مشخصه‌های هرکدام را در همان عنصر ترکیب کند. اگر ابزار متوجه شود که هر دو مانیفست حاوی یک ویژگی با مقادیر متفاوت هستند، تداخل ادغام رخ می‌دهد.

جدول ۱ نتایج احتمالی را زمانی نشان می‌دهد که ابزار ادغام تلاش می‌کند همه مشخصه‌ها را در یک عنصر ترکیب کند.

جدول ۱. رفتار ادغام پیش‌فرض برای مقادیر مشخصه

مشخصه با اولویت بالا مشخصه با اولویت پایین نتیجه ادغام‌شده مشخصه
بی‌ارزش بی‌ارزش بدون مقدار (استفاده از مقدار پیش‌فرض)
مقدار ب مقدار ب
مقدار الف بی‌ارزش مقدار الف
مقدار الف مقدار الف
مقدار ب خطای تداخل—باید نشانگر قانون ادغام اضافه کنید.

بااین‌حال، چند موقعیت وجود دارد که ابزار ادغام در آن‌ها به‌طور متفاوتی عمل می‌کند تا از تعارض‌های ادغام جلوگیری کند:

  • مشخصه‌های موجود در عنصر <manifest> هرگز باهم ادغام نمی‌شوند؛ فقط از مشخصه‌های مانیفست با بالاترین اولویت استفاده می‌شود.
  • مشخصه android:required در عناصر <uses-feature> و <uses-library> از ادغام OR استفاده می‌کند. اگر تداخلی وجود داشته باشد، "true" اعمال می‌شود و ویژگی یا کتابخانه موردنیاز یک مانیفست همیشه گنجانده می‌شود.
  • مشخصه‌های موجود در عنصر <uses-sdk> همیشه از مقدار مانیفست با اولویت بالاتر استفاده می‌کنند، به‌جز در شرایط زیر:
    • وقتی مانیفست با اولویت پایین‌تر مقدار minSdk بالاتری داشته باشد، خطا رخ می‌دهد مگراینکه قانون ادغام overrideLibrary را اعمال کنید.
    • وقتی مانیفست با اولویت پایین‌تر مقدار targetSdkVersion پایین‌تری داشته باشد، ابزار ادغام از مقدار مانیفست با اولویت بالاتر استفاده می‌کند و همچنین هرگونه اجازه سیستم را که برای اطمینان از ادامه عملکرد صحیح کتابخانه واردشده لازم است اضافه می‌کند (برای مواردی که نسخه بالاتر Android محدودیت‌های اجازه را افزایش داده است). برای اطلاعات بیشتر درباره این رفتار، بخش مربوط به اجازه‌های ضمنی سیستم را ببینید.
  • عنصر <intent-filter> هرگز بین مانیفست‌ها مطابقت داده نمی‌شود. هرکدام به‌عنوان یک عنصر منحصربه‌فرد درنظر گرفته می‌شود و به عنصر والد مشترک در مانیفست ادغام‌شده اضافه می‌شود.

برای همه تعارض‌های دیگر بین مشخصه‌ها، خطایی دریافت می‌کنید و باید با افزودن مشخصه‌ای ویژه در فایل مانیفست با اولویت بالاتر، به ابزار ادغام دستور دهید که چگونه آن را حل کند. بخش زیر را درباره نشانگرهای قانون ادغام ببینید.

به مقادیر مشخصه پیش‌فرض وابسته نباشید. چون همه مشخصه‌های منحصربه‌فرد در یک عنصر ترکیب می‌شوند، اگر مانیفست با اولویت بالاتر واقعاً به مقدار پیش‌فرض مشخصه‌ای وابسته باشد بدون اینکه آن را اعلام کند، ممکن است نتایج غیرمنتظره‌ای ایجاد شود. برای مثال، اگر مانیفست با اولویت بالاتر مشخصه android:launchMode را اعلام نکند، از مقدار پیش‌فرض "standard" استفاده می‌کند—اما اگر مانیفست با اولویت پایین‌تر این مشخصه را با مقدار دیگری اعلام کند، آن مقدار در مانیفست ادغام‌شده اعمال می‌شود و مقدار پیش‌فرض را لغو می‌کند. باید هر مشخصه را به‌طور صریح همان‌طور که می‌خواهید باشد تعریف کنید. مقادیر پیش‌فرض برای هر مشخصه در مرجع مانیفست مستند شده است.

ادغام کردن نشانگرهای قانون

نشانگر قانون ادغام یک مشخصه XML است که می‌توانید از آن برای بیان اولویت خود درباره نحوه حل تداخل‌های ادغام یا حذف عناصر و مشخصه‌های ناخواسته استفاده کنید. می‌توانید نشانگر را روی کل عنصر یا فقط روی مشخصه‌های خاصی در عنصر اعمال کنید.

هنگام ادغام دو فایل مانیفست، ابزار ادغام به‌دنبال این نشانگرها در فایل مانیفست با اولویت بالاتر می‌گردد.

همه نشانگرها به فضای نام Android tools تعلق دارند، بنابراین ابتدا باید این فضای نام را در عنصر <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="mergeOnlyAttributes"
مشخصه‌ها را فقط در این برچسب ادغام کنید؛ عناصر تودرتو را ادغام نکنید.

مانیفست با اولویت پایین:

<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="mergeOnlyAttributes">
</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 را روی ۴ یا بالاتر تنظیم کند و کتابخانه‌ای را وارد کند که targetSdkVersion آن روی ۳ یا پایین‌تر تنظیم شده باشد، ابزار ادغام اجازه WRITE_EXTERNAL_STORAGE را به مانیفست ادغام‌شده اضافه می‌کند.

جدول ۲ همه اجازه‌های احتمالی را که می‌توان به مانیفست ادغام‌شده شما اضافه کرد فهرست می‌کند:

جدول ۲. فهرست اجازه‌هایی که ابزار ادغام ممکن است به مانیفست ادغام‌شده اضافه کند

مانیفست با اولویت پایین‌تر اعلام می‌کند اجازه‌ها به مانیفست ادغام‌شده اضافه شد
targetSdkVersion ۳ یا کمتر باشد WRITE_EXTERNAL_STORAGE، READ_PHONE_STATE
targetSdkVersion ۱۵ سال یا کمتر دارد و از READ_CONTACTS استفاده می‌کند READ_CALL_LOG
targetSdkVersion ۱۵ سال یا کمتر دارد و از WRITE_CONTACTS استفاده می‌کند WRITE_CALL_LOG

مانیفست ادغام‌شده را بازرسی کنید و تداخل‌ها را پیدا کنید

حتی قبل‌از ساختن برنامه‌تان، می‌توانید پیش‌نمایشی از ظاهر مانیفست ادغام‌شده‌تان را ببینید. برای دیدن پیش‌نمایش، کارهای زیر را انجام دهید:

  1. در Android Studio، فایل AndroidManifest.xml را باز کنید.
  2. روی برگه مانیفست ادغام‌شده در پایین ویرایشگر کلیک کنید.

نمای «مانیفست ادغام‌شده» نتایج مانیفست ادغام‌شده را در سمت چپ و اطلاعات مربوط به هر فایل مانیفست ادغام‌شده را در سمت راست نشان می‌دهد، همان‌طور که در شکل ۲ نشان داده شده است.

عناصری که از فایل‌های مانیفست با اولویت پایین‌تر ادغام شده‌اند با رنگ‌های مختلف در سمت راست برجسته شده‌اند. راهنمای هر رنگ در زیر منابع مانیفست مشخص شده است.

شکل ۲. نمای «مانیفست ادغام‌شده».

فایل‌های مانیفستی که بخشی از ساخت بوده‌اند اما عناصر یا مشخصه‌هایی را همیاری نکرده‌اند در بخش سایر فایل‌های مانیفست فهرست شده‌اند.

برای دیدن اطلاعات درباره اینکه عنصر از کجا آمده است، روی آن در قاب سمت راست کلیک کنید، و جزئیات در زیر گزارش ادغام ظاهر می‌شود.

اگر تداخلی رخ دهد، در بخش خطاهای ادغام با توصیه‌ای برای نحوه حل تداخل بااستفاده از نشانگرهای قانون ادغام ظاهر می‌شود.

خطاها در پنجره گزارش رویداد نیز چاپ می‌شود. برای مشاهده آن‌ها، View > Tool Windows > Event Log را انتخاب کنید.

برای دیدن گزارش کامل درخت تصمیم ادغام، می‌توانید فایل گزارش را در فهرست راهنمای build/outputs/logs/ واحدتان با نام manifest-merger-buildVariant-report.txt پیدا کنید.

ادغام کردن خط‌مشی‌ها

ابزار ادغام مانیفست می‌تواند به‌طور منطقی هر عنصر XML را از یک فایل مانیفست با عنصر متناظر در فایل دیگر مطابقت دهد. ادغام‌کننده هر عنصر را بااستفاده از کلید مطابقت، که یا مقدار مشخصه یکتا (مثل android:name) است یا یکتایی طبیعی خود برچسب (برای مثال، فقط یک عنصر <supports-screen> می‌تواند وجود داشته باشد)، مطابقت می‌دهد.

اگر دو مانیفست عنصر XML یکسانی داشته باشند، ابزار دو عنصر را بااستفاده از یکی از سه خط‌مشی ادغام باهم ادغام می‌کند:

ادغام کردن
همه مشخصه‌های غیرمتناقض را در یک برچسب ترکیب کنید و عناصر فرزند را طبق خط‌مشی ادغام مربوطه آن‌ها ادغام کنید. اگر مشخصه‌ای با مشخصه دیگر تداخل دارد، آن‌ها را با نشانگرهای قانون ادغام با یکدیگر ادغام کنید.
فقط ادغام کردن فرزندان
مشخصه‌ها را ترکیب یا ادغام نکنید (فقط مشخصه‌های ارائه‌شده توسط فایل مانیفست با بالاترین اولویت را نگه دارید) و عناصر فرزند را طبق خط‌مشی ادغام آن‌ها ادغام کنید.
Keep
عنصر را همان‌طور که هست رها کنید و آن را به عنصر مادر مشترک در فایل ادغام‌شده اضافه کنید. این مورد فقط زمانی استفاده می‌شود که وجود چند اعلامیه برای یک عنصر قابل‌قبول باشد.

جدول ۳ هر نوع عنصر، نوع خط‌مشی ادغام استفاده‌شده، و کلید استفاده‌شده برای تعیین مطابقت عنصر بین دو مانیفست را فهرست می‌کند:

جدول ۳. خط‌مشی‌های ادغام عنصر مانیفست و کلیدهای مطابقت

عنصر خط‌مشی ادغام کلید مطابقت
<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"]
    }
    ...
}

کاتلین

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"
        }
    }
}

کاتلین

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>

برای اطلاعات بیشتر، تنظیم شناسه برنامه را بخوانید.