Android Studio error: "Manifest merger failed: Apps targeting Android 12" [duplicate]

You need to specify android:exported="false" or android:exported="true"

Manifest:

<activity
          android:name=".MainActivity"
          android:exported="true"
          android:theme="@style/Theme.MyApplication.NoActionBar">
          <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
    </activity>

as mentioned in the document

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.

Warning: If an activity, service, or broadcast receiver uses intent filters and doesn't have an explicitly-declared value for android:exported, your app can't be installed on a device that runs Android 12.

Also check when to use true/false for 'android:exported' value


In your manifest, add android:exported="true" or android:exported="false " in your default launching activity attribute.

Done!. You are all right to run your apps on Android 12.

<manifest ...

<activity
        android:name=".ui.dashboard.DashboardActivity"
        android:screenOrientation="portrait"
        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>

set android:exported value according to your requirement.

Whether the broadcast receiver can receive messages from non-system sources outside its application — "true" if it can, and "false" if not. If "false", the only messages the broadcast receiver can receive are those sent by the system, components of the same application, or applications with the same user ID.

If unspecified, the default value depends on whether the broadcast receiver contains intent filters. If the receiver contains at least one intent filter, then the default value is "true". Otherwise, the default value is "false".

This attribute is not the only way to limit a broadcast receiver's external exposure. You can also use permission to limit the external entities that can send messages (see the permission attribute).

From Android Documentation


If you didn't find in your manifest the place where there is an activity without the tag "android: exported = false" then it's likely that it is in your dependencies... in order to pinpoint where exactly, first downgrade "compileSdkVersion" to 30 and "targetSdkVersion" to 30 so it builds.

android {
    compileSdkVersion("android-S")
    buildToolsVersion "30.0.3"

    defaultConfig {
        ...
        minSdkVersion 23
        targetSdkVersion("S")
        ...
}

after that in the main manifest.xml window there is a tab with "merged manifest" there you can inspect what activity exactly didn't have the "android: exported = false" attribute. In my case it was because of 3rd party tools: build.gradle (: app):

debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'
//and 
debugImplementation "com.github.markzhai:blockcanary-android:1.5.0"
releaseImplementation "com.github.markzhai:blockcanary-no-op:1.5.0"

also, for services I had to add the attribute

 <service
                android:name=".autofillservice.MyAutofillService"
                android:exported="true"
                android:permission="android.permission.BIND_AUTOFILL">

and

<service
                android:name="com.demo.myApp.my_access.MyAccessService"
                android:enabled="true"
                android:exported="true"
                android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

As my problem was in a 3rd party dependency and it's not going to be updated soon, I just added a declaration with the flag android:exported="true" and exported="false" where needed to override the initial declaration, also as I need this dependency in Debug only I added a new AndroidManifest.xml file in src/debug:

for leak_canary:

<?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"
                android:icon="@mipmap/leak_canary_icon"
                android:label="@string/leak_canary_display_activity_label"
                android:taskAffinity="com.squareup.leakcanary.${applicationId}"
                android:theme="@style/leak_canary_LeakCanary.Base">
            <intent-filter android:label="@string/leak_canary_import_hprof_file">
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="file" />
                <data android:scheme="content" />
                <data android:mimeType="*/*" />
                <data android:host="*" />

                <data android:pathPattern=".*\\.hprof" />
                <data android:pathPattern=".*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\.hprof" />
                <data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\.hprof" />                
            </intent-filter>
        </activity>
        <activity
                android:name="leakcanary.internal.RequestStoragePermissionActivity"
                android:excludeFromRecents="true"
                android:exported="false"
                android:icon="@mipmap/leak_canary_icon"
                android:label="@string/leak_canary_storage_permission_activity_label"
                android:taskAffinity="com.squareup.leakcanary.${applicationId}"
                android:theme="@style/leak_canary_Theme.Transparent" />

        <receiver
                android:name="leakcanary.internal.NotificationReceiver"
                android:exported="false" />
    </application>
</manifest>

you might as well just use the tools:node="merge" attribute and declare the android:exported=true|false as @LeoFarage kindly suggested