Merging an AndroidManifest.xml file is one of those behind-the-scenes tasks that can either make your Android build process painless or completely frustrating when conflicts arise. With the increasing use of code generation tools like Kotlin Symbol Processing (KSP), developers often find themselves needing to merge automatically generated manifests with their main project manifest. Luckily, the Android Manifest Merger — a standard part of the Android Gradle build system — provides an elegant, reliable solution.
In this article, we’ll explore everything you need to know about merging KSP-generated AndroidManifest.xml files using the Android Manifest Merger, including workflow, prioritization, tools namespace, troubleshooting tips, and best practices.
Understanding the Android Manifest Merger
What Is the Manifest Merger Tool?
The Android Manifest Merger is a powerful component of the Android Gradle build process. Its role is to automatically combine multiple manifest files from various sources — your main application, libraries, product flavors, and generated outputs (like those from KSP or annotation processors).
Instead of requiring developers to manually edit or combine manifests, the manifest merger automates this process following a set of well-defined merge rules, ensuring consistency across builds.
When Does the Merge Happen?
The merge occurs during the Gradle build phase, before the app is packaged into an APK or AAB.
Developers don’t need to manually invoke the merger — it’s triggered automatically when Gradle compiles the project. If your build and plugins are configured properly, the tool picks up generated manifests without additional setup.
The Core Workflow of Manifest Merging
Understanding how the merge process works is crucial to managing and debugging Android builds effectively.
Manifest Merge Workflow
- Start with the main app module’s
AndroidManifest.xml
as the base. - Merge in manifests from:
- Libraries and dependencies.
- Product flavors and build variants.
- Automatically generated manifests (including from KSP).
- Apply merge rules based on priority.
- Output a final merged manifest placed in the build intermediates directory (
build/intermediates/merged_manifests/
).
Merge Order and Prioritization
The priority of manifests determines how conflicts are resolved:
- Highest Priority: The main module’s manifest.
- Next: Product flavors and build variants.
- Lowest: Library and generated manifests (e.g., from KSP).
This means any settings, metadata, or attributes defined in your app’s main manifest override those from libraries or generated files. Understanding this hierarchy prevents accidental overrides and unexpected runtime behavior.
Merge Rules, Conflicts, and Resolution
How the Merger Matches Elements
The merger aligns manifest elements using unique identifiers. For instance:
- Components like
<activity>
,<service>
, or<receiver>
are matched using theandroid:name
attribute. - Permissions, features, or metadata often use
name
attributes as keys.
How the Merger Resolves Differences
The merger applies specific policies based on the element type and merge context:
Policy | Description | Example |
---|---|---|
Merge | Combines compatible attributes and child elements. | Multiple <uses-permission> entries. |
Override | Replaces a lower-priority declaration with a higher one. | Application label or uses-sdk . |
Keep | Keeps multiple valid declarations when allowed. | Several uses-feature items. |
Handling Merge Conflicts
Conflicts arise when two manifests define the same element differently in ways that cannot be automatically resolved. For example, two manifests declaring different android:label
attributes for the <application>
tag.
In such cases, the merger throws a build-time error, requiring manual correction. This ensures the final manifest is always explicit and predictable.
Customizing Merge Behavior with the Tools Namespace
Common Attributes in the Tools Namespace
The tools
XML namespace offers attributes that give you granular control over the manifest merge outcome. These attributes are defined in the http://schemas.android.com/tools
namespace.
Attribute | Purpose | Example |
---|---|---|
tools:node="merge" | Merge the element (default). | <activity ... tools:node="merge" /> |
tools:node="replace" | Completely replace an element. | <activity ... tools:node="replace" /> |
tools:node="remove" | Remove an element. | <uses-permission ... tools:node="remove" /> |
tools:replace="attr1,attr2" | Replace specific attributes. | <application tools:replace="android:label" /> |
How to Apply Merge Markers
You must place merge markers in higher-priority manifests (typically the main module’s) to ensure they effectively override or remove elements from lower-priority manifests such as those generated by KSP or included from libraries.
Proper use of these tools attributes prevents unwanted permissions, duplicate definitions, and metadata conflicts — especially important in projects with multiple dependencies and generated content.
Working with KSP-Generated Manifests
How KSP Generates Manifests
Kotlin Symbol Processing (KSP) is a code generation tool that allows annotation processors to create additional classes, files, and sometimes manifest entries during the build. These generated AndroidManifest.xml
files are typically located under:
build/generated/ksp/intermediates/
When properly registered, Gradle automatically includes these manifests during the merge phase.
Do You Need to Merge Manually?
In most cases, no. The manifest generated by KSP is automatically picked up and merged by the Android build system. Manual merging is necessary only if your plugin or build configuration hasn’t properly registered the generated manifest source.
Common KSP Manifest Integration Pitfalls
Issue | Likely Cause | Recommended Fix |
---|---|---|
Generated manifest not merged | File not registered in the sourceSets. | Update sourceSets in build.gradle . |
Duplicate elements or permissions | Conflicts between main and generated manifests. | Use tools:node="remove" or tools:replace . |
Build failures from unresolved conflicts | Attribute mismatch or incompatible entries. | Use the Merged Manifest Viewer and adjust manually. |
Debugging and Verifying Manifest Merges
Using the Merged Manifest Viewer
Android Studio includes a Merged Manifest Viewer (accessible via Build → Analyze APK
or the Manifest tab). It shows you exactly how your manifests are merged:
- The final combined manifest view.
- The source of each element (library, generated, or main).
- Highlighted conflicts or overridden values.
Enable Verbose Merge Logging
You can also enable verbose logging in Gradle to analyze the merge process:
./gradlew assembleDebug --info
This command prints detailed merge steps to the console, which helps in identifying conflicting files, missing attributes, or redundant entries.
Example: Resolving Conflicts with Merge Markers
Here’s a common scenario: A KSP plugin automatically adds a permission to the manifest that your app doesn’t need. To remove it from the final merged output, add a tools:node="remove"
directive in your main manifest.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp"
xmlns:tools="http://schemas.android.com/tools">
<!-- Remove unwanted permission added by generated manifest -->
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE"
tools:node="remove" />
<!-- Override the application label -->
<application
android:label="@string/app_name"
tools:replace="android:label">
...
</application>
</manifest>
Using these merge markers explicitly tells the merger to remove or override specific elements, avoiding runtime issues and unexpected permissions from third-party libraries or KSP processors.
Best Practices for Manifest Merging
Keeping large Android projects maintainable requires consistent and predictable manifest merging.
- Always check the Merged Manifest Viewer. Confirm changes are correctly reflected before release.
- Use tools namespace markers for fine-grained control of merges.
- Ensure proper registration of generated manifests in Gradle.
- Keep product flavors organized to avoid overlapping manifest logic.
- Avoid unnecessary duplication of permissions or activities.
- Version control your main manifest carefully—avoid automatic overwriting by code generation tools.
Following these best practices ensures that your build system remains robust across new dependencies and evolving code generation mechanisms like KSP.
FAQs About Merging KSP-Generated AndroidManifest.xml Files
Do I ever need to manually merge a KSP-generated manifest?
Usually, no. The Android Manifest Merger automatically includes the generated manifests if registered properly. Only manual intervention is required if you’ve misconfigured the Gradle source sets or disabled automatic manifest merging.
How can I find which manifest added a certain permission or activity?
Open the Merged Manifest Viewer in Android Studio. Each line in the viewer shows where an element came from — whether the main app, a library, or a KSP-generated manifest.
My generated manifest doesn’t appear in the final app. What should I check?
Ensure that the plugin you’re using correctly outputs the manifest to a recognized build directory, such as build/intermediates/
. You might also need to review your build.gradle
and add sourceSets entries if the file isn’t automatically included.
What happens if two manifests define conflicting uses-sdk
values?
The Manifest Merger uses the same priority rules — the main module’s manifest takes precedence. However, incompatible settings can still trigger a conflict error, requiring manual resolution through merge markers.
Can I disable the Manifest Merger?
You could, but it’s highly discouraged. The merger ensures consistency among dependencies and plugins. Disabling it can lead to build instability and missing critical declarations required by libraries.
How do I debug persistent merge errors?
- Run
./gradlew assembleDebug --info
for verbose output. - Use the Merge Log Report generated in
build/outputs/logs/
. - Analyze the final merged manifest with Android Studio’s viewer to understand where conflicts originate.
Conclusion
The Android Manifest Merger is the officially supported method for combining multiple manifest files in modern Android builds. When used correctly, it automatically includes KSP-generated manifests and resolves conflicts based on logical, configurable rules.
By applying tools-based merge markers, understanding merge priorities, and using Android Studio’s built-in merge viewer, developers can ensure stable, streamlined builds without tedious manual manifest edits.
For anyone adopting KSP or other code generation tools, mastering the manifest merger is a key step toward building robust, automated Android applications.
Key takeaway: Rely on the Android Manifest Merger — not manual merging — to seamlessly integrate KSP-generated manifests while maintaining full control over your app’s final configuration.
External reference: