资料
优先级
清单文件在合并时,会按优先级进行合并。会按 优先级从低向高合并,优先级最低的清单文件会合并到优先级倒数第二低的文件中,然后今次向下合并。
优先级按高到低如下:
主清单文件。
各库中的文件。如果有多个库,其清单优先级与依赖顺序(库出现在 Gradle dependencies 块中的顺序)匹配。
合并规则
如果优先级较低的清单中的元素与优先级较高的清单中的任何元素均不匹配,则该元素将被添加至合并清单。
如果有匹配元素,则合并工具会尝试将其中的所有属性合并到相同元素中。如果工具发现两个清单包含相同属性,但值不相同,则会出现合并冲突。
但如下几个标签不会出现另外:
<manifest> 元素中的属性绝不合并 — 仅使用优先级最高的清单中的属性。
-
<uses-sdk>元素始终使用优先级较高的清单中的值,但以下情况除外:
如果低优先级清单的
minSdkVersion
值较高,除非您应用overrideLibrary
合并规则如果低优先级清单的
targetSdkVersion
值 较低,合并工具将使用高优先级清单中的值,但也会添加任何必要的系统权限,以确保所导入的库继续正常工作(适用于较高的 Android 版本具有更多权限限制的情况)。
<intent-filter> 每个元素都被视为唯一元素,并添加至合并清单中的常用父元素。也就是说,<intent-filter> 不会被合并。
合并规则标记
合并规则标记是一个 XML 属性,可用于表达您对关于如何解决合并冲突或删除不需要的元素和属性的首选项。 您可以对整个元素或只对元素中的特定属性应用标记。
合并两个清单文件时,合并工具会在高优先级清单文件中寻找这些标记。
所有的标识分为两种类型,一种作用于节点,一种作用于属性。
节点标记
作用于整个 xml 元素。其对应的属性名为 node。值如下:
属性值 | 含义 |
---|---|
merge | 合并此标记中的所有属性以及所有嵌套元素 |
merge-only-attributes | 只合并属性,不合并子元素 |
remove | 删除匹配的元素 |
removeAll | 删除所有匹配的标签 |
replace | 忽略低优先级内容,完全使用高优先级内容 |
strict | 只要两个清单文件不一样,无论是否能合并,都会出现冲突 |
在比对元素是否相同时,只比例标签名以及其中的 name 属性值。如果都相同,则认为相同;否则不相同。
merge
默认行为。合并此标记中的所有属性以及所有嵌套元素。如
低版本为:
<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" />
则合并后的清单文件中不会含有该 meta-data。
removeAll
删除所有标配的标签。使用该属性值时,标签中不能含有任何其他属性,也就是说该标签中除了 tools:node="removeAll"
外,不能配置任何其他属性。
<meta-data
android:name="test"
tools:node="removeAll" />
上述配置会删除同一父元素内的所有 <meta-data> 标签。
replace
完全替换低优先级元素。 也就是说,如果低优先级清单中有匹配元素,请将其忽略并完全按照其在此清单中显示样子来使用该元素。
标签匹配不单指标签名相同,其 name 元素的值也要相同。
<meta-data
android:name="test"
tools:node="replace" />
strict
当此元素在低优先级清单中的情况与在高优先级清单中的情况不完全匹配时生成构建故障。如:
<!---高优先级-->
<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>
<!--低优先级-->
<activity
android:name="com.example.ActivityOne"
android:screenOrientation="portrait" />
上述两个文件在合并时,会产生冲突;但如果将 strict 换成 merge 会合并成功。
属性标记
属性标记只会影响某个 xml 标签中的某个属性,不会影响整个标签。
每个属性接受一个或多个属性名称(包括属性命名空间),并以逗号分隔。
replace
将低优先级清单中的指定属性替换为此清单中的属性。 换言之,始终保持高优先级清单的值
<!--高版本-->
<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
。也就是说:在 配置属性名时,需要带名称空间。
其次,replace 可以配置多个属性,属性之间通过逗号分隔。
上述文件合并后,得到的依旧是高版本的配置。
remove
从合并清单中删除指定属性。
<!--高版本-->
<meta-data
android:name="test"
android:value="main"
tools:remove="android:resource" />
<!--低版本-->
<meta-data
android:name="test"
android:resource="@string/app_name" />
<!--合并结果-->
<meta-data
android:name="test"
android:value="main" />
因为在高优先级中使用了 remove,则合并后不会出现 android:resource
属性。
strict
当这些属性在低优先级清单中的情况与在高优先级 清单中的不完全匹配时生成构建故障。 默认行为。
选择器
仅对某个特定的导入库应用合并规则标记,需要使用 tools:selector
属性。
例如,对于下面的清单,仅在低优先级清单文件来自 com.example.lib1 库时应用 remove 合并规则。
<permission android:name="permissionOne"
tools:node="remove"
tools:selector="com.example.lib1">
如果低优先级清单来自其他源,系统将会忽略 remove 合并规则。
<uses-sdk>
默认时,如果库的 minSdk 高于主工程的,则会出错,无法导入该库。可以将 overrideLibrary
添加至 <uses-sdk>
标签中。
overrideLibrary
属性值可以是一个或多个库的包名(以逗号分隔),指明可能替换主清单的 minSdkVersion 的库。
如主工程设置 minSdk 为 21, library 设置为 22。则合并时会出现错误。可以在主工程的清单文件中添加如下配置:
<uses-sdk tools:overrideLibrary="com.library.package" />
其中 com.library.package
替换为库的包名。