From 66502afb0faa49c6c310196f7e238b2566720713 Mon Sep 17 00:00:00 2001
From: Rich Slogar With Android Studio and Gradle-based builds, each app can
+contain manifest files in multiple locations, such as the Merge conflicts occur when merged manifests contain the same manifest element but with a
+different attribute value that does not resolve based on the default merge conflict rules.
+Conflict markers and selectors can also define custom merge rules,
+such as allowing an imported library to have a The manifest merge priority determines which manifest settings are retained in merge conflicts,
+with the settings in higher priority manifest overwriting those in lower priority manifests.
+The following list details which manifest settings are are the highest priority during the merge
+process: Manifest merge conflicts are resolved at the XML node and
+attribute levels based on the following merge rules. Exceptions to the manifest merge rules: Note: If not explicitly declared, the Important: After the manifests are merged, the build process
+overrides the final manifest settings with any settings that are also in the
+ Manifest markers and selectors override the default merge rules through
+specific conflict resolutions. For example, use a conflict marker to
+merge a library manifest with a higher A merge conflict marker is a special attribute in the Android tools namespace that defines a
+specific merge conflict resolution. Create a conflict marker to avoid a merge conflict error for
+conflicts not resolved by the default merge rules. Supported merge conflict markers include: By default, the manifest merge process applies the To set a merge conflict marker, first declare the namespace in the
+ Conflict markers use The The Without this marker, library manifest merge conflicts from the
+ This example applies the Library manifest: Note: The default merge process does not allow importing a library
+with a higher Marker selectors limit a merge action to a specific lower priority manifest. For example, a
+marker selector can be used to remove a permission from only one library, while allowing the
+same permission from other libraries. This example uses the Manifest merging can also be configured to use manifest placeholders to inject
+property values from the Manifest placeholders use the syntax Note: Unresolved placeholder names in apps cause build failures.
+Unresolved placeholder names in libraries generate warnings and need to be resolved when importing
+the library into an app. This example shows the manifest placeholder Note: Android Studio provides a default
+ Manifest entry: Gradle build file: Merged manifest value: The manifest placeholder syntax and build file Gradle build file: Placeholder in the manifest file: Note: The placeholder value supports partial value injection,
+for example When using the For example, if a build variant references the product flavors To illustrate this example, the following table shows how the product flavors are listed for
+each product flavor group. This combination of product flavors and groups defines the
+build variant. Manifest merge order: Importing a library that targets an Android runtime with implicitly
+granted permissions may automatically add the permissions to the resulting merged manifest.
+For example, if an application with a Note: More recent Android releases replace implicit
+permissions with permission declarations.In this document
+
+
+
+ See also
+
+
+src/main/ folder for
+the productFlavor, libraries, Android ARchive (AAR) bundles of Android Library
+projects, and dependencies. During the build process, manifest merging combines the settings from
+the various AndroidManifest.xml files included in your app into a single, generated APK
+manifest file for app packaging and distribution. Manifest settings are merged based on the manifest
+priority, determined by the manifest's file location. Building your app merges the
+manifest elements, attributes, and sub-elements from these manifests for the specified
+build variant.Merge Conflict Rules
+minSdkVersion higher than the
+version defined in the other higher priority manifests.
+
+
+buildType manifest settings productFlavor manifest settings src/main/ directory of an app project
+
+
+
+
+
+
+ High Priority Element
+ Low Priority Element
+ Manifest Merge Result
+
+
+ no attribute
+ no attribute
+ no attribute
+
+
+
+ attribute set to default
+ default attribute
+
+
+
+ attribute set to non-default
+ low priority attribute
+
+
+ attribute set to default
+ no attribute
+ default attribute
+
+
+ attribute set to non-default
+
+ high priority attribute
+
+
+ attribute set to default
+ attribute set to default
+ default attribute
+
+
+ attribute set to default
+ attribute set to non-default
+ low priority attribute
+
+
+ attribute set to non-default
+ attribute set to default
+ high priority attribute
+
+
+ attribute set to non-default
+ attribute set to non-default
+ Merge if settings match, otherwise causes conflict error.
+
+
+
+uses-feature android:required; and
+ uses-library android:required elements default to true and use
+ an OR merge so that any required feature or library is included in the generated APK. <uses-sdk>
+ elements, minSdkVersion and
+ targetSdkVersion, default to a value of 1. When
+ merge conflicts occur, the value in the higher priority manifest version is used.minSdkVersion value higher than the app's
+ src/main/ manifest manifest generates an error unless
+ the overrideLibrary conflict marker is used.
+
+ targetSdkVersion
+ defaults to the minSdkVersion value. When no element is
+ present in any manifest or the build.gradle file, the
+ minSdkVersion defaults to 1.targetSdkVersion value lower than the app's
+ src/main/ manifest, the manifest merge
+ process explicitly grants permissions and ensures that the imported library functions properly. manifest element only merges with child manifest elements. intent-filter element is never changed and is always added to the common
+ parent node in the merged manifest. build.gradle file. For more details, see
+Configuring Gradle Builds. Merge Conflict Markers and Selectors
+minSdkVersion value than the higher priority
+manifest, or to merge manifests with the same activity but different android:theme
+values. Merge Conflict Markers
+
+
+
+
+mergereplacestrictmerge-onlyremoveremove-Allmerge conflict marker to
+the node level. All declared manifest attributes default to a strict
+merging policy. AndroidManifest.xml file. Then, enter the merge conflict marker in the manifest to
+specify a custom merge conflict action. This example inserts the replace marker to
+set a replace action to resolve conflicts between the android:icon and
+android:label manifest elements.
+
+<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">
+ ...
+
+
+
+
+
+
+Marker attributes
+tools:node and tools:attr attributes to
+restrict merge actions at the XML node or attribute level. tools:attr markers use only the restrict, remove, and
+replace merge actions. Multiple tools:attr marker values can be applied
+to a specific element. For example, use tools:replace="icon, label, theme" to replace
+lower priority icon, label, and theme attributes. Merge conflict marker for imported libraries
+overrideLibrary conflict marker applies to the <uses-sdk>
+manifest declaration and is used to import a library even though the library's
+<uses-sdk> values, such as minSdkVersion
+are set to different values than those in the other higher priority manifests. <uses-sdk> values cause the merge process to fail.overrideLibrary conflict marker to resolve the merge
+conflict between minSdkVersion values in the src/main/ manifest and an
+imported library manifest.
+
+
+src/main/ manifest:
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.example.app"
+ xmlns:tools="http://schemas.android.com/tools">
+ ...
+ <uses-sdk android:targetSdkVersion="22" android:minSdkVersion="2"
+ tools:overrideLibrary="com.example.lib1, com.example.lib2"/>
+ ...
+
+
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.example.lib1">
+ ...
+ <uses-sdk android:minSdkVersion="4" />
+ ...
+ </manifest>
+
+
+minSdkVersion than the app's src/main/ manifest unless
+the overrideLibrary conflict marker is used. Marker Selectors
+tools:node marker to remove the permisionOne
+attribute, while the tools:selector selector specifies the specific library as
+com.example.lib1. The permisionOne permission is filtered from only the
+lib1 library manifests.
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.example.app"
+ xmlns:tools="http://schemas.android.com/tools">
+ ...
+ <permission
+ android:name="permissionOne"
+ tools:node="remove"
+ tools:selector="com.example.lib1">
+ ...
+
+
+
+
+Injecting Build Values into a Manifest
+build.gradle file into the manifest attributes. ${name} for attribute values, where
+name is the injected build.gradle property. The build.gradle
+file uses the manifestPlaceholders property to define the placeholder values. ${applicationId} used to inject the
+build.gradle applicationId property value in to android:name
+attribute value. ${applicationId} placeholder for the build.gradle
+applicationId value that is not shown in the build file.
+
+<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
+property can be used to inject other manifest values. For properties other than the
+applicationId, the manifestPlaceholders property is explicitly declared
+in the build.gradle file. This example shows the manifest placeholder for injecting
+activityLabel values.
+android {
+ defaultConfig {
+ manifestPlaceholders = [ activityLabel:"defaultName"]
+ }
+ productFlavors {
+ free {
+ }
+ pro {
+ manifestPlaceholders = [ activityLabel:"proName" ]
+ }
+ }
+
+
+
+
+<activity android:name=".MainActivity" android:label="${activityLabel}" >
+
+
+android:authority="com.acme.${localApplicationId}.foo". Manifest Merging Across Product Flavor Groups
+
+GroupableProductFlavor property, the manifest merge
+priority of any manifests in the product flavor groups follows the order in which the
+product flavor groups are listed in the build file. The manifest merge process creates a single
+merged manifest for the product flavor groups based on the configured build variant. x86,
+mdpi, 21, and paid from the respective product flavor
+groups ABI, Density, API, and Prod, listed
+in this order in the build.gradle file, then the manifest merge process merges the
+manifests in this priority order, which follows how the product flavors are listed in the build
+file.
+
+
+
+ Product Flavor Group
+ Product Flavor
+
+
+ ABI
+ x86
+
+
+ density
+ mdpi
+
+
+ API
+ 22
+
+
+prod
+ paid
+
+
+
+
+Implicit Permissions
+targetSdkVersion of 16 imports a library with a
+targetSdkVersion of 2, Android Studio adds the WRITE_EXTERNAL_STORAGE
+permission to ensure permission compatibility across the SDK versions.
+
+
| 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 the WRITE_CONTACTS
+ permission |
+ WRITE_CALL_LOG |
+
During the build process, the manifest merge process stores a record of each merge transaction
+in the manifest-merger-<productFlavor>-report.txt file in the module
+build/outputs/logs folder. A different log file is generated for each of the
+module's build variants.
When a manifest merge build error occurs, the merge process records the error message
+describing the merge conflict in the log file. For example, the
+android:screenOrientation merge conflict between the following manifests causes
+a build error.
Higher priority manifest declaration:
+ ++<activity + android:name="com.foo.bar.ActivityOne" + android:screenOrientation="portrait" + android:theme="@theme1"/> ++ +
Lower priority manifest declaration:
+ ++<activity + android:name="com.foo.bar.ActivityOne" + android:screenOrientation="landscape"/> ++ +
Error log:
+ ++/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+ + diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs index 9ba7a22506518..7fbb0eb5ae70f 100644 --- a/docs/html/tools/tools_toc.cs +++ b/docs/html/tools/tools_toc.cs @@ -188,6 +188,8 @@ class="en">Tools Help Configuring Gradle Buildselement at AndroidManifest.xml:1:5 to override +