Android Developer:合并清单文件

使用Android Studio而且基于Gradle构建。每一个App能在多个位置包括清单文件,比如在src/main文件夹下productFlavor、库、Android ARchive(AAR) bundles of Android Library项目,和第三方依赖。在构建过程中。包括在你的app中的多个AndroidMainfest.xml设置合并成一个,生成APK清单文件用于app的打包和公布。

清单文件的设置基于清单优先级来合并。取决于清单文件的位置。从制定build variant清单文件的元素,属性,和子元素构建合并你的app清单文件。 

 

合并冲突规则 

------------------------------------------------------------------ 

合并的冲突发生在清单文件包括同样的清单元素,而且有不同的属性值,无法使用默认的合并规则解决的时候。Conflict markers和selectors也能定义自己定义的合并规则。比如同意一个导入的库有一个minSdkVersion大于在其他更高优先级清单中定义的版本号。 

 

清单合并优先级决定了哪个清单设置在合并冲突中保留。使用高优先级订单文件设置覆盖低优先级清单。以下的列表具体描写叙述了在合并过程中。哪个清单设置的优先级最高: 

  • 最高优先级:buildType清单设置 

  • 高优先级:productFlavor清单设置 

  • 中优先级:app项目在src/main/文件夹下清单 

  • 低优先级:依赖和库清单设置 

清单冲突合并基于以下的合并规则在XML节点和属性级别被解决: 


清单合并规则例外: 

  • uses-feature android:required;和use-library android:required元素默认值为true。而且使用一个或者合并。这样不论什么要求的功能和库在成成的APK都被包括。 

  • 假设没有声明,<uses-sdk>元素,minSdkVersion和targetSdkVersion。默认的值为1。当合并冲突发生,更高优先级的清单文件值被使用; 

  • 导入一个包括minSdkVersion值高于app的src/main/清单文件。清单产生一个错误。除非overrideLibrary冲突记号被使用; 

注意:假设没有明白的声明,targetSdkVersion默觉得minSdkVersion值。当没有元素在不论什么清单文件或者build.gradle文件里出现的时候,minSdkVersion默觉得1。

 

  • 当导入一个包括targetSdkVersion值低于app的src/main清单文件的库,清单合并过程明白授予权限并。并确保正确的导入库库函数。 

  • manifest元素只合并孩子清单元素。 

  • intent-filter元素从不改变而且总是加入到合并的清单同样的父节点下。 

重要:在清单文件被合并后,构建过程使用build.gradle文件里的不论什么设置覆盖终于的清单设置。很多其他详情,请阅读Configure Gradle Builds。

 

 

合并冲突标记和选择器 

------------------------------------------------------------------ 

清单标记和选择器通过制定冲突解决的方法覆盖默认的规则。比如,使用冲突标识来合并一个库清单的minSdkVersion高于更高优先级清单,或者合并清单同样的Activity,可是不同的android:theme值。 

 

合并冲突标识 

一个合并冲突标识是一个在Android工具空间的指定元素。它定义了一个指定的冲突合并方案。创建一个冲突标识是为了避免使用默认合并规则没有解决的合并冲突错误。支持的合并冲突标识包括: 

merge 

    当没有合并规则冲突的时候合并属性。

默认的合并动作。

 

replace 

    使用高优先级的清单替代低优先级清单中的属性; 

strict 

merge-only 

    同意指定低优先级属性的合并动作。 

remove 

    删除合并后的清单指定的低级别元素; 

remove-All 

    删除合并后清单的同样节点类型的全部低优先级元素。  

     

默认情况下。清单的合并过程在节点级别应用merge冲突标识。

全部声明的清单属性默认是strict合并策略。 

 

为了设置一个合并冲突标识,首先在AndroidManifest.xml文件里声明命名空间。

然后在清单中输入合并冲突标识的一个指定的合并冲突动作。这个样例插入了replace标识来设置一个replace动作,来解决在android:icon和android:lable清单元素的冲突。 

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
   package="com.android.tests.flavorlib.app" 
   xmlns:tools="http://schemas.android.com/tools"> 
 
   <application 
       android:icon="@drawable/icon" 
       android:label="@string/app_name" 
       tools:replace="icon, label"> 
       ...  

标记属性 

冲突标识使用tools:node和tools:attr属性来在XML节点或者属性级别的冲突动作。 

 

tools:attr标识只使用restrict,remove,和replace合并动作。多个tools:attr标识的值能够被应用到一个指定的元素。比如,使用tools:replace="icon,lable,theme"来提来更低的优先级icon。lable和theme属性。 

 

向清单文件里注入构建值 

----------------------------------------------------------------- 

清单文件合并也能使用清单占位符。从build.gradle文件向清单属性注入属性值。 

 

清单占位符使用这个语法${name}设置属性值,name是注入build.gradle属性,build.gradle文件使用manifestPlaceholders属性来定义占位符的值。

 

注意:在app中未解析的占位符名称会导致构建失败。

在库中未解析的占位符生成警告。而且将这个库导入一个app的时候必须解决。 

 

这个样例展示了清单占位符${applcationId}用于映射build.gradle的applicationID属性值到android:name属性值。 

注意:Android Studio为build.gradle applicationID值提供了一个默认的${applicationId}占位符,它不显示在构建文件里。当为库模块构建一个AAR(Android ARchive)包时。不须要在清单合并设置中提供一个自己主动的@{applicationID}占位符。相反,使用一个不同的占位符,比如@{libApplicationID}。并为假设你想包括归档库的appliction Id,为它提供一个值。 

清单实体: 

<activity 
android:name=".Main"> 
     <intent-filter> 
     <action android:name="${applicationId}.foo"> 
         </action> 
</intent-filter> 
</activity> 
构建文件: 

android { 
   compileSdkVersion 22 
   buildToolsVersion "22.0.1" 
 
   productFlavors { 
       flavor1 { 
           applicationId = "com.mycompany.myapplication.productFlavor1" 
       } 
} 
合并清单值: 

<action android:name="com.mycompany.myapplication.productFlavor1.foo"> 
清单文件占位符和构建文件manifestPlaceholders属性能被用于注入其他清单文件值。

对于applicationId依赖的属性。manifestPlaceholders属性明白的在build.gradle文件里声明。

这个样例展示了清单占位符注入activityLabel值。 

Gradle build 文件: 

android { 
    defaultConfig { 
        manifestPlaceholders = [ activityLabel:"defaultName"] 
    } 
    productFlavors { 
        free { 
        } 
        pro { 
            manifestPlaceholders = [ activityLabel:"proName" ] 
        } 
    } 
构建文件: 

android { 
    defaultConfig { 
        manifestPlaceholders = [ activityLabel:"defaultName"] 
    } 
    productFlavors { 
        free { 
        } 
        pro { 
            manifestPlaceholders = [ activityLabel:"proName" ] 
        } 
    } 

在清单文件里的占位符: 

<activity android:name=".MainActivity" android:label="${activityLabel}" > 
注意:占位符的值支持部分值注入,比如android:authority="com.acme.${localApplicationId}.foo". 

 

通过Product Flavor组合并清单文件 

----------------------------------------------------------------- 

当使用GroupbleProductFlavor属性。不论什么在Product flavor组的清单文件的合并优先级取决于在构建文件里的排列顺序。清单文件合并的过程基于build variant的构建配置,为product flavor组创建一个单独合并清单文件。

 

 

比如,假设一个build varian从各自的product flavor组ABI,Density,API和Prod參考了product flavors x86,mdpi,21,和paid,在build.gradle文件里以该顺序排列。然后清单文件以product flavors在构建文件里排列的顺序为优先级合并。 

 

为了说明这个样例,以下的标识展示了每一个product flavor组列举了什么product flavor。

这个product flavors和组的组合定义了build variant。 

Product Flavor Group 

Product Flavor 

ABI 

x86 

density 

mdpi 

API 

22 

prod 

paid 

清单合并顺序: 

  • prod-paid AndroidManifest.xml(低优先级)合并到API-22 AndroidManifest.xml 

  • API-22 AndroidManifest.xml合并到density-mpi AndroidManifest.xml 

  • density-mpi AndroidManifest.xml合并到ABI-x86 AndroidManifest.xml(高优先级) 

 

隐式权限 

----------------------------------------------------------------- 

导入一个支持隐式授予权限的Android执行的库,可能会自己主动往合并清单中加入这个权限。比如,假设一个targetSdkVersion为16的应用程序,导入一个targetSdkVersion为2的库。Andorid Studio加入WRITE_EXTERNAL_STORAGE权限,以确保跨SDK版本号的兼容性。

 

注意:很多其他如今的Android版本号代替隐式的权限声明。 

Importing this library version 

Declares this permission in the manifest 

targetSdkVersion < 2 

WRITE_EXTERNAL_STORAGE 

targetSdkVersion < 4 

WRITE_EXTERNAL_STORAGE,READ_PHONE_STATE 

Declared WRITE_EXTERNAL_STORAGE 

READ_EXTERNAL_STORAGE 

targetSdkVersion < 16 and using the READ_CONTACTS permission 

READ_CALL_LOG 

targetSdkVersion < 16 and using WRITE_CONTACTS permission 

WRITE_CALL_LOG 

 

处理清单合并构建错误 

------------------------------------------------------------------ 

在构建过中,清单合并过程在模块的build/outputs/logs文件夹下mainfest-merge-<productFlavor>-report.txt文件里记录了每一个合并事务。

每一个模块的build variants生成不同的日志文件。 

 

当一个清单合并构建发生错误的时候,构建过程在日志文件里记录了描写叙述合并冲突错误消息。比如,在以下的清单之间导致了一个构建错误android:screenOrientation合并冲突。 

 

高优先级的清单声明: 

<activity 
   android:name="com.foo.bar.ActivityOne" 
   android:screenOrientation="portrait" 
   android:theme="@theme1"/> 
低优先级的清单声明: 

<activity 
   android:name="com.foo.bar.ActivityOne" 
   android:screenOrientation="landscape"/> 
错误日志: 

/project/app/src/main/AndroidManifest.xml:3:9 Error: 
 Attribute activity@screenOrientation value=(portrait) from AndroidManifest.xml:3:9 
 is also present at flavorlib:lib1:unspecified:3:18 value=(landscape) 
 Suggestion: add 'tools:replace="icon"' to  element at AndroidManifest.xml:1:5 to override 

【推广】 免费学中医,健康全家人
原文地址:https://www.cnblogs.com/llguanli/p/8660082.html