清單文件的合并

資料

官網(wǎng)

優(yōu)先級(jí)

清單文件在合并時(shí),會(huì)按優(yōu)先級(jí)進(jìn)行合并。會(huì)按 優(yōu)先級(jí)從低向高合并,優(yōu)先級(jí)最低的清單文件會(huì)合并到優(yōu)先級(jí)倒數(shù)第二低的文件中,然后今次向下合并。

優(yōu)先級(jí)按高到低如下:

  1. 主清單文件。

  2. 各庫(kù)中的文件。如果有多個(gè)庫(kù),其清單優(yōu)先級(jí)與依賴順序(庫(kù)出現(xiàn)在 Gradle dependencies 塊中的順序)匹配。

合并規(guī)則

  1. 如果優(yōu)先級(jí)較低的清單中的元素與優(yōu)先級(jí)較高的清單中的任何元素均不匹配,則該元素將被添加至合并清單。

  2. 如果有匹配元素,則合并工具會(huì)嘗試將其中的所有屬性合并到相同元素中。如果工具發(fā)現(xiàn)兩個(gè)清單包含相同屬性,但值不相同,則會(huì)出現(xiàn)合并沖突。

匹配規(guī)則

但如下幾個(gè)標(biāo)簽不會(huì)出現(xiàn)另外:

  1. <manifest> 元素中的屬性絕不合并 — 僅使用優(yōu)先級(jí)最高的清單中的屬性。

  2. <uses-sdk>元素始終使用優(yōu)先級(jí)較高的清單中的值,但以下情況除外:

    • 如果低優(yōu)先級(jí)清單的 minSdkVersion較高,除非您應(yīng)用 overrideLibrary 合并規(guī)則

    • 如果低優(yōu)先級(jí)清單的 targetSdkVersion較低,合并工具將使用高優(yōu)先級(jí)清單中的值,但也會(huì)添加任何必要的系統(tǒng)權(quán)限,以確保所導(dǎo)入的庫(kù)繼續(xù)正常工作(適用于較高的 Android 版本具有更多權(quán)限限制的情況)。

  3. <intent-filter> 每個(gè)元素都被視為唯一元素,并添加至合并清單中的常用父元素。也就是說(shuō),<intent-filter> 不會(huì)被合并。

合并規(guī)則標(biāo)記

合并規(guī)則標(biāo)記是一個(gè) XML 屬性,可用于表達(dá)您對(duì)關(guān)于如何解決合并沖突或刪除不需要的元素和屬性的首選項(xiàng)。 您可以對(duì)整個(gè)元素或只對(duì)元素中的特定屬性應(yīng)用標(biāo)記。

合并兩個(gè)清單文件時(shí),合并工具會(huì)在高優(yōu)先級(jí)清單文件中尋找這些標(biāo)記。

所有的標(biāo)識(shí)分為兩種類型,一種作用于節(jié)點(diǎn),一種作用于屬性。


節(jié)點(diǎn)標(biāo)記

作用于整個(gè) xml 元素。其對(duì)應(yīng)的屬性名為 node。值如下:

屬性值 含義
merge 合并此標(biāo)記中的所有屬性以及所有嵌套元素
merge-only-attributes 只合并屬性,不合并子元素
remove 刪除匹配的元素
removeAll 刪除所有匹配的標(biāo)簽
replace 忽略低優(yōu)先級(jí)內(nèi)容,完全使用高優(yōu)先級(jí)內(nèi)容
strict 只要兩個(gè)清單文件不一樣,無(wú)論是否能合并,都會(huì)出現(xiàn)沖突

在比對(duì)元素是否相同時(shí),只比例標(biāo)簽名以及其中的 name 屬性值。如果都相同,則認(rèn)為相同;否則不相同。

merge

默認(rèn)行為。合并此標(biāo)記中的所有屬性以及所有嵌套元素。如

低版本為:

       <activity android:name="com.demo.MainActivity"
            android:hardwareAccelerated="false" >
            <meta-data
                android:name="test"
                android:value="test" />
        </activity>

高版本為

        <activity
            android:name="com.demo.MainActivity"
            android:screenOrientation="portrait"
            tools:node="merge">

        </activity>

則合并后為:

 <activity
    android:name="com.demo.MainActivity"
    android:screenOrientation="portrait"
    android:hardwareAccelerated="false">
            <meta-data
                android:name="test"
                android:value="test" />
</activity>

merge-only-attributes

僅合并元素的屬性,不合并子元素。

remove

刪除滿足條件的元素。

如高版本配置如下:

      <meta-data android:name="test"
            android:value="main"
            tools:node="remove" />

則合并后的清單文件中不會(huì)含有該 meta-data。

removeAll

刪除所有標(biāo)配的標(biāo)簽。使用該屬性值時(shí),標(biāo)簽中不能含有任何其他屬性,也就是說(shuō)該標(biāo)簽中除了 tools:node="removeAll" 外,不能配置任何其他屬性。

        <meta-data
            android:name="test"
            tools:node="removeAll" />

上述配置會(huì)刪除同一父元素內(nèi)的所有 <meta-data> 標(biāo)簽。

replace

完全替換低優(yōu)先級(jí)元素。 也就是說(shuō),如果低優(yōu)先級(jí)清單中有匹配元素,請(qǐng)將其忽略并完全按照其在此清單中顯示樣子來(lái)使用該元素。

標(biāo)簽匹配不單指標(biāo)簽名相同,其 name 元素的值也要相同。

<meta-data
      android:name="test"
      tools:node="replace" />

strict

當(dāng)此元素在低優(yōu)先級(jí)清單中的情況與在高優(yōu)先級(jí)清單中的情況不完全匹配時(shí)生成構(gòu)建故障。如:

<!---高優(yōu)先級(jí)-->
<activity
    tools:node="strict"
    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>

<!--低優(yōu)先級(jí)-->
<activity
    android:name="com.example.ActivityOne"
    android:screenOrientation="portrait" />

上述兩個(gè)文件在合并時(shí),會(huì)產(chǎn)生沖突;但如果將 strict 換成 merge 會(huì)合并成功。


屬性標(biāo)記

屬性標(biāo)記只會(huì)影響某個(gè) xml 標(biāo)簽中的某個(gè)屬性,不會(huì)影響整個(gè)標(biāo)簽。

每個(gè)屬性接受一個(gè)或多個(gè)屬性名稱(包括屬性命名空間),并以逗號(hào)分隔。

replace

將低優(yōu)先級(jí)清單中的指定屬性替換為此清單中的屬性。 換言之,始終保持高優(yōu)先級(jí)清單的值

<!--高版本-->
<meta-data
     android:name="test"
     android:resource="@string/test"
     android:value="main"
     tools:replace="android:value,android:resource" />
<!--低版本-->
<meta-data
     android:name="test"
     android:resource="@string/app_name"
     android:value="test" />

首先,replace 的值是 android:value,而不是 value。也就是說(shuō):在 配置屬性名時(shí),需要帶名稱空間。

其次,replace 可以配置多個(gè)屬性,屬性之間通過(guò)逗號(hào)分隔。

上述文件合并后,得到的依舊是高版本的配置。

remove

從合并清單中刪除指定屬性。

<!--高版本-->
<meta-data
    android:name="test"
    android:value="main"
    tools:remove="android:resource" />
<!--低版本-->
<meta-data
    android:name="test"
    android:resource="@string/app_name" />
<!--合并結(jié)果-->
<meta-data
    android:name="test"
    android:value="main" />

因?yàn)樵诟邇?yōu)先級(jí)中使用了 remove,則合并后不會(huì)出現(xiàn) android:resource 屬性。

strict

當(dāng)這些屬性在低優(yōu)先級(jí)清單中的情況與在高優(yōu)先級(jí) 清單中的不完全匹配時(shí)生成構(gòu)建故障。 默認(rèn)行為。


選擇器

僅對(duì)某個(gè)特定的導(dǎo)入庫(kù)應(yīng)用合并規(guī)則標(biāo)記,需要使用 tools:selector 屬性。

例如,對(duì)于下面的清單,僅在低優(yōu)先級(jí)清單文件來(lái)自 com.example.lib1 庫(kù)時(shí)應(yīng)用 remove 合并規(guī)則。

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

如果低優(yōu)先級(jí)清單來(lái)自其他源,系統(tǒng)將會(huì)忽略 remove 合并規(guī)則。


<uses-sdk>

默認(rèn)時(shí),如果庫(kù)的 minSdk 高于主工程的,則會(huì)出錯(cuò),無(wú)法導(dǎo)入該庫(kù)。可以將 overrideLibrary 添加至 <uses-sdk> 標(biāo)簽中。

overrideLibrary 屬性值可以是一個(gè)或多個(gè)庫(kù)的包名(以逗號(hào)分隔),指明可能替換主清單的 minSdkVersion 的庫(kù)。

如主工程設(shè)置 minSdk 為 21, library 設(shè)置為 22。則合并時(shí)會(huì)出現(xiàn)錯(cuò)誤??梢栽谥鞴こ痰那鍐挝募刑砑尤缦屡渲茫?/p>

    <uses-sdk tools:overrideLibrary="com.library.package" />

其中 com.library.package 替換為庫(kù)的包名。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容