Android 基础 AndroidManifest.xml 合并规则
APK
文件只能包含一个
AndroidManifest.xml文件,但项目可以包含多个文件(通过主App和导入的库等)。因此构建应用时,Gradle构建会将所有清单文件合并到一个清单文件中
合并规则
官网介绍
:合并多个清单文件
合并工具根据每个清单文件的优先级将所有清单文件按顺序合并到一个文件中。 例如,如果您有 3 个清单文件,则会先将优先级最低的清单合并到优先级第 2 高的清单中,然后再将合并后的清单合并到优先级最高的清单中
重要说明
: build.gradle 文件中的构建配置将替换合并清单文件中的任何对应属性。 例如,build.gradle 文件中的minSdkVersion 将替换<uses-sdk
> 清单元素中的匹配属性。 为了避免混淆,您只需省去<uses-sdk
>元素并在build.gradle
文件中定义这些属性。
合并冲突启发式算法
如果优先级较低的清单中的元素与优先级较高的清单中的任何元素均不匹配,则该元素将被添加至合并清单。 但是,如果有匹配元素,则合并工具会尝试将其中的所有属性合并到相同元素中。如果工具发现两个清单包含相同属性,但值不相同,则会出现合并冲突
但是,在某些情况下,合并工具会采取其他行为方式以避免合并冲突
- <
manifest
> 元素中的属性绝不合并—仅使用优先级最高的清单中的属性 - 绝不会在清单之间匹配 <
intent-filter
> 元素。 每个元素都被视为唯一元素,并添加至合并清单中的常用父元素
等等
不依赖于默认属性值
。由于所有唯一属性都合并到相同元素中,如果高优先级清单实际上依赖于属性的默认值而不需要声明,则可能会导致意外结果。例如,如果高优先级清单不声明android:launchMode 属性,则会使用 “standard” 的默认值;但如果低优先级清单声明此属性具有其他值,该值将应用于合并清单(替代默认值)。因此,您应该按期望明确定义每个属性。(每个属性的默认值都会记录在 Manifest reference 中)
合并规则标记
合并规则标记是一个 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="replace"
属性,具体详情查看文章开头官网SDK链接
属性标记
要改为仅向清单标记中的特定属性应用合并规则,请使用以下属性。每个属性接受一个或多个属性名称(包括属性命名空间),并以逗号分隔
例如:tools:replace="attr, ..."
将低优先级清单中的指定属性替换为 此清单中的属性。 换言之,始终保持 高优先级清单的值
Low priority manifest:
<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, ..."
等
会检查合并清单并查找冲突
即使在构建 APK 之前,也可以预览合并清单,具体方法是:在 Android Studio 中打开您的 AndroidManifest.xml 文件,然后单击编辑器底部的Merged Manifest
选项卡
Merged Manifest 视图在左侧显示合并清单的结果
,在右侧显示每个合并清单文件的相关信息
,如图所示。从低优先级文件中合并的元素在左侧以不同颜色突出显示。 每种颜色的关键字在右侧的 Manifest Sources 下方指定