Android 12 Manifest Merger Failed: Fixing the android:exported Error
Problem Overview
Starting with Android 12 (API level 31), Google introduced a critical security change requiring explicit declaration of the android:exported
attribute for components that use intent filters. This change affects activities, services, and broadcast receivers in your Android application.
When targeting Android 12 or higher, you'll encounter the build error:
Manifest merger failed: Apps targeting Android 12 and higher are required to specify an explicit value for
android:exported
when the corresponding component has an intent filter defined.
This error prevents your app from building and installing on Android 12+ devices until you address all missing android:exported
declarations.
Understanding the android:exported Attribute
The android:exported
attribute determines whether a component (activity, service, or broadcast receiver) can be accessed by components outside your application:
true
: Any app can access the component using its exact class namefalse
: Only components within the same application, applications with the same user ID, or privileged system components can access it
Historical Context
In earlier Android versions, the default value for android:exported
varied by component type and API level. For example, activities had exported="true"
by default on API level 16 and lower. This inconsistency created security risks across different devices.
Primary Solution: Add Explicit android:exported Declarations
For Launcher Activities
Your main/launcher activity must have android:exported="true"
:
<activity
android:name=".MainActivity"
android:exported="true"
android:theme="@style/AppTheme.Launcher">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
For Other Activities
Non-launcher activities should typically use android:exported="false"
:
<activity
android:name=".SecondaryActivity"
android:exported="false" />
For Broadcast Receivers
Receivers that need to respond to system events (like boot completion) require android:exported="true"
:
<receiver
android:name=".BootReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
For Services
Services with intent filters need explicit exported declarations:
<service
android:name=".MyService"
android:exported="true"
android:enabled="true" />
Security Consideration
Don't blindly set android:exported="true"
for all components. Evaluate each component's purpose and only export those that genuinely need to be accessible from outside your app.
Identifying Problematic Components
When the error doesn't clearly point to a specific component in your main manifest, follow these steps:
- Temporarily downgrade targetSdkVersion to 30 in your build.gradle:
android {
compileSdkVersion 31
targetSdkVersion 30 // Temporary downgrade
// ...
}
Use Android Studio's Merged Manifest Viewer:
- Open your
AndroidManifest.xml
file - Click the "Merged Manifest" tab at the bottom
- Look for components with intent filters but missing
android:exported
attributes
- Open your
Check third-party dependencies - often the problematic components come from libraries that haven't been updated for Android 12 compliance.
Handling Third-Party Dependencies
If the issue comes from external libraries, you have several options:
Option 1: Override in Your Manifest
Add the component declaration to your manifest with the correct android:exported
value:
<activity
android:name="com.some.library.SomeActivity"
android:exported="false"
tools:node="merge" />
Option 2: Create Debug-Specific Manifest
For debug-only dependencies, create a separate manifest in src/debug/AndroidManifest.xml
:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="leakcanary.internal.activity.LeakActivity"
android:exported="true"
tools:node="merge">
<!-- intent filters if needed -->
</activity>
</application>
</manifest>
Option 3: Update or Replace Libraries
Check for updated versions of your dependencies that support Android 12. If a library is abandoned, consider replacing it with a maintained alternative.
Outdated Dependencies
Some popular libraries that initially caused issues include:
- LeakCanary versions before 2.7
- Older analytics libraries (Flurry, StartApp)
- Various push notification libraries
Complete Example Manifest
Here's a complete example showing proper android:exported
usage:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application>
<!-- Launcher activity - exported true -->
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Internal activity - exported false -->
<activity
android:name=".InternalActivity"
android:exported="false" />
<!-- Boot receiver - exported true -->
<receiver
android:name=".BootReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<!-- Internal service - exported false -->
<service
android:name=".InternalService"
android:exported="false" />
</application>
</manifest>
Common Pitfalls and Solutions
DON'T: Downgrade targetSdkVersion Permanently
While setting targetSdkVersion
to 30 temporarily helps diagnose the issue, keeping it at 30 permanently avoids the requirement but prevents you from using Android 12 features and may cause compatibility issues in the future.
DO: Update All Test Dependencies
Ensure your test dependencies are also updated. For example:
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
Conclusion
The Android 12 android:exported
requirement is a security enhancement that prevents unintended component exposure. By:
- Explicitly declaring
android:exported
for all components with intent filters - Carefully setting appropriate values (
true
for launcher activities and receivers needing system access,false
for internal components) - Addressing third-party library issues through overrides or updates
You can ensure your app complies with Android 12 requirements while maintaining security best practices.