APK文件只能包含一个AndroidManifest.xml文件,但Android Studio项目可以包含多个文件(通过buildSrc、导入的库引入)。因此,在构建应用时,Gradle构建会将所有清单文件合并到一个封装的APK的清单文件中。

清单文件合并优先级

清单合并工具

  • 可以使用Merged Manifest视图预览合并清单的效果并找出冲突错误。

可以互相合并的基本清单文件,合并优先级如下(优先级由高到低):

  1. 清单文件构建变体

    如果变体有多个源集,其清单优先级由高到低如下:

    a、构建变体清单文件(如 src/demoDebug)

    b、构建类型清单(如 src/debug/)

    c、产品定制清单(如 src/demo/)

    如果使用的是定制纬度,清单优先级与每个维度在 flavorDimensions属性中的列示顺序(优先级高到低)对应。
  2. 应用模块的主清单文件
  3. 所包括库中的清单文件:如果有多个库,清单优先级与依赖顺序(库出现在 Gradle dependencies 块中的顺序)匹配。

重要说明:build.gradle文件中的构建配置将替换合并清单文件中的任何对应属性。如build.gradle文件中的minSdkVersion将替换清单元素中的匹配属性。

合并冲突启发式算法

合并工具行为:

  • 元素中的属性绝不合并,仅使用优先级最高的清单中的属性。
  • android:required属性、、元素使用OR合并,因此如果出现冲突,系统将采用“true”并始终包括某个清单所需的功能或者库。
  • 元素始终使用优先级较高的清单中的值,但以下情况除外:
    • 如果低优先级清单的 minSdkVersion值较高,除非应用 overrideLibrary合并规则。(minSdkVersion使用较大值)
    • 如果低优先级清单的 targetSdkVersion值较低,合并工具将使用高优先级清单中的值,但也会添加任何必要的系统权限。(targetSdkVersion使用较大值)
  • 绝不会在清单之间匹配元素。每个元素都被视为唯一元素并添加到合并清单中。

重点:清单合并不依赖默认属性值。因此,应该按照期望明确定义每个属性。(每个属性的默认值都会记录在Manifest reference:https://developer.android.com/guide/topics/manifest/manifest-intro)

合并规则标记

可以针对整个元素或者只对元素中的特定属性应用标记。

所以标记都属于Android tools命名空间,因此必须现在元素中声明此命名空间:

  1. <manifest xmlns:android="http://schemas.android.com/apk/res/android"
  2. package="com.example.myapp"
  3. xmlns:tools="http://schemas.android.com/tools">

节点标记:

  • tools:node="merge" ——默认行为,合并此标记中的所有属性以及所有嵌套元素。
  • tools:node="merge-only-attributes" ——仅合并此标记中的属性,不合并嵌套元素
  • tools:node="remove" ——从合并清单中删除此元素,可以删除低优先级清单的元素
  • tools:node="removeAll" ——会删除与此元素类型相匹配的所有元素(同一父元素内)
  • tools:node="replace" ——完全替换低优先级元素
  • tools:node="strict" ——标记元素在低优先级清单中的配置与高优先级清单不完全匹配,会触发构建失败。(默认行为会向合并清单添加额外属性)

属性标记:

  • tools:remove="attr1,attr2,..." ——删除指定属性
  • tools:replace="attr1,attr2,..." ——替换低优先级清单指定属性为当前清单中的属性
  • tools:strict="attr1,attr2,..." ——当指定属性在低优先级清单与当前清单中不完全一致,触发清单合并错误。是属性合并的默认行为。
  • 支持对同一个元素使用多个标记

标记选择器:

  • tools:selector="lib1,lib2,..." ——针对某个特定的导入库应用合并规则标记
  • tools:overrideLibrary="lib1,lib2,..." ——替换指定导入库的
    • 默认情况下,导入 minSdkVersion值高于主清单文件的库时会出错,而且无法导入该库。
    • 使用 overrideLibrary,可以保持应用的低 minSdkVersion。

隐式系统权限

隐式权限:允许应用在无权限的情况下继续访问特定API,前提是应用的targetSdkVersion设置为低于添加限制的SDK版本的值。

原则:

  • 如果低优先级清单文件提供隐式权限的 targetSdkVersion值较低,而且高优先级清单没有相同的隐式权限,合并工具将向合并清单显示添加系统权限。

合并工具可以添加至合并清单的权限列表:

低优先级清单声明 添加至合并清单的权限
targetSdkVersion是3或者更低 WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
targetSdkVersion是15或者更低,并且使用READ_CONTACTS READ_CALL_LOG
targetSdkVersion是15或者更低,并且使用WRITER_CONTACTS WRITE_CALL_LOG

具体合并策略:

  • 合并:将所有非冲突属性合并到同一标记中,然后按其各自的合并策略合并子元素。冲突的属性使用合并规则标记进行合并。
  • 仅合并子项:不整合或合并属性(仅保留高优先级清单文件提供的属性)
  • 保留

总结

检查清单合并冲突:在Android Studio中打开AndroidManifest.xml文件,单机编辑器底部的 Merged Manifest选项卡。

合并策略:通过合并规则标记设置。

Android清单文件合并的那些事的更多相关文章

  1. Android多版本flavor配置之资源文件和清单文件合并介绍

    知识背景 Android studio升级到3.0之后,gradle增加了多维度管理配置,便于同一个项目中创建应用的不同版本,分别管理依赖项并签署配置.创建产品风味与创建构建类型类似:只需将它们添加到 ...

  2. [android]清单文件中MAIN与LAUNCHER的区别

    原文:[android]清单文件中MAIN与LAUNCHER的区别 MAIN 和 LAUNCHER,之前一直不注意这两个有区别,写程序的时候都放到一个filter中,前两天面试问到了,总结一下: MA ...

  3. Android清单文件详解(三)----应用程序的根节点<application>

    <application>节点是AndroidManifest.xml文件中必须持有的一个节点,它包含在<manifest>节点下.通过<application>节 ...

  4. Android清单文件具体解释(三)----应用程序的根节点&lt;application&gt;

    <application>节点是AndroidManifest.xml文件里必须持有的一个节点,它包括在<manifest>节点下.通过<application>节 ...

  5. Android清单文件AndroidMenifest.xml

    1.AndroidMenifes.xml清单文主要结构件结构 所谓主要结构就是每一个清单文件中都必不可少的结构主要是下面三层 第一层.menifest 第二层.application,use-sdk ...

  6. Android清单文件具体解释(二) ---- 应用程序权限声明

    我们知道,Android系统的各个模块提供了很强大的功能(比方电话,电源和设置等),通过使用这些功能.应用程序能够表现的更强大.更灵活.只是,使用这些功能并非无条件的.而是须要拥有一些权限.接下来,我 ...

  7. Android清单文件具体解释(四) ---- backupAgent的使用方法

    在<application>节点中有一个很重要的属性,那就是backupAgent.这里我们将它单独列出来,从基本含义,使用方法及其相关属性等方面来具体介绍一下. 1.backupAgen ...

  8. Android清单文件具体解释(六) ---- &lt;activity&gt;节点的属性

    1.android:allowTaskReparenting android:allowTaskReparenting是一个任务调整属性,它表明当这个任务又一次被送到前台时,该应用程序所定义的Acti ...

  9. (备忘)android清单文件中<meta-data>标签,以及<intent-filter>下的<data>标签及其他标签

    1.metadata可以写在application下也可以写在activity下,作为全局或activity内共享的数据 以键值对形式保存 <meta-data android:name=&qu ...

随机推荐

  1. python(33)——【re模块】

    re模块(正则表达式) 就其本质而言,正则表达式是一种小型的.高度专业化的编程语言 在Python中(它内嵌在python中),并通过re模块来实现,正则表达式被编译成一系列的字节码,然后由C编写的匹 ...

  2. Python模块——PrettyTable 模块

    简介 PrettyTable 是python中的一个第三方库,可用来生成美观的ASCII格式的表格,十分实用. 安装 pip install prettytable 示例 从已有文件创建 CSV fr ...

  3. 【xsy1596】旅行 期望+状压DP

    题目大意:有$m$个人要从城市$1$开始,依次游览城市$1$到$n$. 每一天,每一个游客有$p_i$的概率去下一个城市,和$1-p_i$的概率结束游览. 当游客到达城市$j$,他会得到$(1+\fr ...

  4. jenkins内部分享ppt

    持续集成Continuous integration简介(持续集成是什么)    .持续集成源于极限编程(XP),是一种软件实践,软件开发过程中集成步骤是一个漫长并且无法预测的过程.集成过程中可能会爆 ...

  5. 关于 Nginx 配置 WebSocket 400 问题

    今天把项目升级了 asp.net core 到 2.1 的版本,使用了 signalr  的功能,由于阿里云不支持 websocket 协议,所以使用了 nginx 代理方式来解决,后续就报了一个登陆 ...

  6. MVC笔记--特性路由

    物性路由:将路由和控制器放在一起,这样更简单方便,还可以处理复杂的路由场景 传统路由:集中.强制.基于代码风格来定义的. 每个MVC应用程序都需要路由来定义自己的处理请求方式,路由是MVC是应用程序的 ...

  7. Redis 哨兵

    作用 Redis Sentinel,即Redis哨兵,在Redis 2.8版本开始引入. 主要提供了配置提供者,通知,哨兵的监控和自动故障转移功能.哨兵的核心功能是主节点的自动故障转移. 下面是Red ...

  8. docker push 出现:x509: certificate signed by unknown authority

    今天,部署生产的程序的时候,出现一个问题:编译正常,但是,docker 把编译好的image 推送到生产环境上去的时候,出现:x509: certificate signed by unknown a ...

  9. Baffle.js – 用于实现文本模糊效果的 JavaScript 库

    Baffle.js 是一个 JavaScript 库,设计用来模糊和揭开DOM元素的文本. 这些元素可以是一个 CSS 选择器的形式.一个节点列表或者一个单节点. 你也可以传递一个选择对象给插件. 在 ...

  10. Ocelot中文文档-Not Supported

    Not Supported Ocelot不支持以下几种情况 块级编码(Chunked Encoding ) - Ocelot始终会获取消息体的大小并返回内容长度(Content-Length).这种情 ...