From 66502afb0faa49c6c310196f7e238b2566720713 Mon Sep 17 00:00:00 2001 From: Rich Slogar Date: Wed, 4 Feb 2015 10:56:46 -0800 Subject: docs: manifest merger updates Change-Id: I0a1c311ba08077b15ee1823146773b7d07162dd4 --- docs/html/tools/building/manifest-merge.jd | 510 +++++++++++++++++++++++++++++ docs/html/tools/tools_toc.cs | 2 + 2 files changed, 512 insertions(+) create mode 100644 docs/html/tools/building/manifest-merge.jd (limited to 'docs') diff --git a/docs/html/tools/building/manifest-merge.jd b/docs/html/tools/building/manifest-merge.jd new file mode 100644 index 0000000..54166ec --- /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 Conflict Rules

+

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:

+ + + +

Manifest merge conflicts are resolved at the XML node and +attribute levels based on the following merge rules.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
High Priority ElementLow Priority ElementManifest Merge Result
no attributeno attributeno attribute
attribute set to defaultdefault attribute
attribute set to non-default low priority attribute
attribute set to defaultno attributedefault attribute
attribute set to non-default high priority attribute
attribute set to defaultattribute set to defaultdefault attribute
attribute set to defaultattribute set to non-default low priority attribute
attribute set to non-defaultattribute set to defaulthigh priority attribute
attribute set to non-defaultattribute set to non-default Merge if settings match, otherwise causes conflict error.
+ + + +

Exceptions to the manifest merge rules:

+ + + +

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.

+ + + +

Merge Conflict Markers and Selectors

+

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.

+ +

Merge Conflict Markers

+

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:

+ +
+
merge
+
Merges attributes when there are no conflicts with the merge rules. The default merge + action.
+
replace
+
Replaces attributes in the lower priority manifest with those from the higher priority + manifest.
+
strict
+
Sets the merge policy level so that merged elements with same attributes, but different + values generate a build failure, unless resolved through the conflict rules.
+
merge-only
+
Allows merge actions for only lower priority attributes.
+
remove
+
Removes the specified lower priority element from the merged manifest.
+
remove-All
+
Removes all lower priority elements of the same node type from the merged manifest.
+
+ + +

By 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">
+       ...
+
+
+
+
+ + +

Marker attributes

+

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.

+ + +

Merge conflict marker for imported libraries

+

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

+

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">
+   ...
+
+ + + +

Injecting Build Values into a Manifest

+

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".

+ + + +

Manifest Merging Across Product Flavor Groups

+ +

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 GroupProduct Flavor
ABIx86
densitymdpi
API22
prodpaid
+ +

Manifest merge order:

+ + + + +

Implicit Permissions

+

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 versionDeclares this permission in the manifest
targetSdkVersion < 2 WRITE_EXTERNAL_STORAGE
targetSdkVersion < 4 WRITE_EXTERNAL_STORAGE, READ_PHONE_STATE
Declared WRITE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGE
targetSdkVersion < 16 and using the READ_CONTACTS + permissionREAD_CALL_LOG
targetSdkVersion < 16 and using the WRITE_CONTACTS + permissionWRITE_CALL_LOG
+ + + +

Handling Manifest Merge Build Errors

+

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  element at AndroidManifest.xml:1:5 to override
+
+ + diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs index 9ba7a22..7fbb0eb 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 Builds
  • Android Plugin for Gradle
  • +
  • + Manifest Merging
  • Apps Over 65K Methods
  • -- cgit v1.1