What's the correct way to merge generated AndroidManifest.xml by KSP?

What’s the correct way to merge generated AndroidManifest.xml by KSP?

Table of Contents

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

  1. Start with the main app module’s AndroidManifest.xml as the base.
  2. Merge in manifests from:
    • Libraries and dependencies.
    • Product flavors and build variants.
    • Automatically generated manifests (including from KSP).
  3. Apply merge rules based on priority.
  4. 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 the android: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:

PolicyDescriptionExample
MergeCombines compatible attributes and child elements.Multiple <uses-permission> entries.
OverrideReplaces a lower-priority declaration with a higher one.Application label or uses-sdk.
KeepKeeps 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.

AttributePurposeExample
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

IssueLikely CauseRecommended Fix
Generated manifest not mergedFile not registered in the sourceSets.Update sourceSets in build.gradle.
Duplicate elements or permissionsConflicts between main and generated manifests.Use tools:node="remove" or tools:replace.
Build failures from unresolved conflictsAttribute 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.

  1. Always check the Merged Manifest Viewer. Confirm changes are correctly reflected before release.
  2. Use tools namespace markers for fine-grained control of merges.
  3. Ensure proper registration of generated manifests in Gradle.
  4. Keep product flavors organized to avoid overlapping manifest logic.
  5. Avoid unnecessary duplication of permissions or activities.
  6. 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?

  1. Run ./gradlew assembleDebug --info for verbose output.
  2. Use the Merge Log Report generated in build/outputs/logs/.
  3. 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:

Table of Contents

Hire top 1% global talent now

Related blogs

Introduction Modern applications rely heavily on dynamic data feeds — user lists, product catalogs, and activity streams. To make these

Running Kotlin code with root privileges can unlock powerful system‑level capabilities for developers building automation tools, desktop utilities, or advanced

Introduction Integrating Kafka with FastAPI has become a common need in modern microservice ecosystems. Both tools are built for scalability

Modern C++ developers strive for maximum performance, often fine‑tuning every instruction for speed. With C++20 introducing the [[likely]] and [[unlikely]]