While I was trying to create a sandbox project to experiment with Android, launching the Android boilerplate to an emulator launched the mentioned failure of the Manifest merger: 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.
After some research, I found the solution, however it wasn't so clear why this was necessary and why the exception appeared with a new project that should automatically work from the beginning in Android Studio. In this article, I will share with you the explanation and solution to this exception.
Adding android:exported attribute to intents and receivers
As mentioned in the official notes about the behaviour changes for Android 12, specifically for the security component, if your app targets Android 12 and contains activities, services, or broadcast receivers that use intent filters, you must explicitly declare the
android:exported attribute for these app components.
This attribute sets whether the activity can be launched by components of other applications:
- If "
true", the activity is accessible to any app, and is launchable by its exact class name.
- If "
false", the activity can be launched only by components of the same application, applications with the same user ID, or privileged system components. This is the default value when there are no intent filters.
If an activity in your app includes intent filters, set this element to "
true" to allow other apps to start it. For example, if the activity is the main activity of the app and includes the
android.intent.category.LAUNCHER". If this element is set to "
false" and an app tries to start the activity, the system throws an
This attribute is not the only way to limit an activity's exposure to other applications. Permissions can also be used to limit the external entities that can invoke the activity (see the
<!-- Either set it to true --> <activity android:name=".MainActivity" android:exported="true"> </activity> <!-- Either set it to false --> <activity android:name=".MainActivity" android:exported="false"> </activity>
According to your needs, this fix in your Android manifest will look like this:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.sandbox"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Sandbox"> <!-- Solution: add the android:exported attribute and set it to true or false to every activity or receiver that you may have --> <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> </application> </manifest>
Happy coding ❤️!