diff --git a/docs/html/tools/building/manifest-merge.jd b/docs/html/tools/building/manifest-merge.jd new file mode 100644 index 0000000000000..54166ec963325 --- /dev/null +++ b/docs/html/tools/building/manifest-merge.jd @@ -0,0 +1,510 @@ +page.title=Manifest Merging +@jd:body + +
With Android Studio and Gradle-based builds, each app can
+contain manifest files in multiple locations, such as the 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 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 minSdkVersion higher than the
+version defined in the other higher priority manifests.
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:
+ +buildType manifest settings productFlavor manifest settings src/main/ directory of an app projectManifest merge conflicts are resolved at the XML node and +attribute levels based on the following merge rules.
+ +| 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. | +
Exceptions to the manifest merge rules:
+ +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.
+
+ Note: If not explicitly declared, the 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. Important: After the manifests are merged, the build process
+overrides the final manifest settings with any settings that are also in the
+build.gradle file. For more details, see
+Configuring Gradle Builds.
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 minSdkVersion value than the higher priority
+manifest, or to merge manifests with the same activity but different android:theme
+values.
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:
+ +mergereplacestrictmerge-onlyremoveremove-AllBy default, the manifest merge process applies the merge conflict marker to
+the node level. All declared manifest attributes default to a strict
+merging policy.
To set a merge conflict marker, first declare the namespace in the
+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"> + ... + + + ++ + +
Conflict markers use tools:node and tools:attr attributes to
+restrict merge actions at the XML node or attribute level.
The 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.
The 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.
Without this marker, library manifest merge conflicts from the
+<uses-sdk> values cause the merge process to fail.
This example applies the 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"/> + ... ++ +
Library manifest:
+ ++<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="com.example.lib1"> + ... + <uses-sdk android:minSdkVersion="4" /> + ... + </manifest> ++ +
Note: The default merge process does not allow importing a library
+with a higher minSdkVersion than the app's src/main/ manifest unless
+the overrideLibrary conflict marker is used.
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 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"> + ... ++ + + +
Manifest merging can also be configured to use manifest placeholders to inject
+property values from the build.gradle file into the manifest attributes.
Manifest placeholders use the syntax ${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.
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 ${applicationId} used to inject the
+build.gradle applicationId property value in to android:name
+attribute value.
Note: Android Studio provides a default
+${applicationId} placeholder for the build.gradle
+applicationId value that is not shown in the build file.
Manifest entry:
+ +
+
+<activity
+android:name=".Main">
+ <intent-filter>
+ <action android:name="${applicationId}.foo">
+ </action>
+</intent-filter>
+</activity>
+
+
+
+
+Gradle build file:
+ +
+android {
+ compileSdkVersion 22
+ buildToolsVersion "22.0.1"
+
+ productFlavors {
+ flavor1 {
+ applicationId = "com.mycompany.myapplication.productFlavor1"
+ }
+}
+
+
+
+Merged manifest value:
+ ++<action android:name="com.mycompany.myapplication.productFlavor1.foo"> ++ + +
The manifest placeholder syntax and build file 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.
Gradle build file:
+ +
+android {
+ defaultConfig {
+ manifestPlaceholders = [ activityLabel:"defaultName"]
+ }
+ productFlavors {
+ free {
+ }
+ pro {
+ manifestPlaceholders = [ activityLabel:"proName" ]
+ }
+ }
+
+
+
+Placeholder in the manifest file:
+ +
+<activity android:name=".MainActivity" android:label="${activityLabel}" >
+
+
+Note: The placeholder value supports partial value injection,
+for example android:authority="com.acme.${localApplicationId}.foo".
When using the 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.
For example, if a build variant references the product flavors 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.
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.
+| Product Flavor Group | +Product Flavor | +
|---|---|
| ABI | +x86 | +
| density | +mdpi | +
| API | +22 | +
| prod | +paid | +
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 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.
+
+
Note: More recent Android releases replace implicit +permissions with permission declarations.
+ + +This table lists the importing library versions and the declared permissions. + + +| 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 887ca2fd1bcbf..abfa0304bb096 100644 --- a/docs/html/tools/tools_toc.cs +++ b/docs/html/tools/tools_toc.cs @@ -189,6 +189,8 @@ class="en">Tools Help Configuring Gradle Buildselement at AndroidManifest.xml:1:5 to override +