Answered Dec 29, 2022 · 435 votes
You need to specify android:exported="false" or android:exported="true"
<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 the 'android:exported' value.
Answered Feb 03, 2022 · 74 votes
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></manifest>
Set the 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
Answered Aug 19, 2022 · 59 votes
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 third-party tools:
File build.gradle (: app):
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.7'//anddebugImplementation "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">
<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 third-party dependency and it's not going to be updated soon, I just added a <activity> 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:
<?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.