An important change is coming to Android 12 that improves both app and platform security. This change affects all apps that target Android 12.
Activities, services, and broadcast receivers with declared intent-filters now must explicitly declare whether they should be exported or not.
❗️If your app fails with one of these error messages, it’s most likely related to this change.
Installation did not succeed.
The application could not be installed: INSTALL_FAILED_VERIFICATION_FAILURE
List of apks:
Installation failed due to: ‘null’
Failed parse during installPackageLI:
/data/app/vmdl538800143.tmp/base.apk (at Binary XML file line #…):
com.example.package.ActivityName: Targeting S+ (version 10000 and above)
requires that an explicit value for android:exported be defined when
intent filters are present”
The fix for these errors is to add the attribute
android:exported to any
<receiver> components that have
<intent-filter>s declared in the app’s
⚠️ Do not just add
android:exported=”true” to all of these components! Examine each component that includes an
<intent-filter> definition and ask yourself, “Do I want any app installed on someone’s device to be able to start this component?”
The answer to this depends on what the app does, how other apps interact with it, and other app specific considerations. Here are a few common examples of common intent-filters with a suggested value and explanation of why it was chosen:
<category android:name=”android.intent.category.LAUNCHER” />:
This is probably your app’s
MainActivity, and since the launcher on Android could be a regular application, this activity has to be exported or the launcher won’t be able to start it.
<action android:name=”android.intent.action.VIEW” />:
This activity is responsible for handling the “open with” action from other apps.
<action android:name=”android.intent.action.SEND” /> or
This activity is responsible for handling the content that other apps share with it. See Receiving simple data from other apps.
<action android:name=”android.media.browse.MediaBrowserService” />:
If this is a service that exposes the app’s media library to other apps, then it should be exported to allow other apps to connect and browse that library. The service likely extends, either directly or indirectly,
MediaBrowserServiceCompat. If it does not, then it may not be necessary to export it.
<action android:name=”com.google.firebase.MESSAGING_EVENT” />:
This is the service that Firebase Cloud Messaging will invoke and should extend
FirebaseMessagingService. This service should not be exported, as Firebase will be able to start the component whether it’s exported or not. For more information, see Set up a Firebase Cloud Messaging client app on Android.
<action android:name=”android.intent.action.BOOT_COMPLETED” />:
Because the system is delivering this action to the broadcast receiver it can do so whether it is exported or not.
Prior to Android 12, components (activites, services, and broadcast receivers only) with an intent-filter declared were automatically exported
This activity is exported by default:
<activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" </intent-filter> </activity>
This activity is not exported:
<activity android:name=".MainActivity" />
While this may seem like a reasonable default, mistakes here can leave an app vulnerable. For example, let’s say our app had an activity to playback videos:
<activity android:name=”.PlayVideoActivity” />
Later we find that we’re linking to this activity explicitly from many places, and so, in order to have our app be more loosely-coupled, we change our activity to include an intent-filter to allow the system to select the activity:
<activity android:name=”.PlayVideoActivity”> <intent-filter> <action android:name=”android.intent.action.VIEW” /> <data android:mimeType=”video/*” android:scheme=”content” /> </intent-filter> </activity>
Suddenly we have a problem. Our activity, which was only designed to be used internally by our app, is now exported!
Once we target Android 12, the system will prevent this by requiring us to be explicit about the value for android:exported. In this case we don’t want it to be exported, so we can set that attribute and keep our app safe.
<activity android:name=”.PlayVideoActivity” android:exported=”false”> <intent-filter> <action android:name=”android.intent.action.VIEW” /> <data android:mimeType=”video/*” android:scheme=”content” /> </intent-filter> </activity>
An important change is coming in Android 12 to improve security. Apps that target that version will need to explicitly declare a value for the
android:exported attribute of any
service, or broadcast
receiver that includes an intent-filter in its
AndroidManifest.xml file. If it does not, the app will fail to be installed.
Carefully consider what value to set this attribute to, and when in doubt, favor setting
For more information about intents and intent-filters, see Receiving an implicit intent.
For more information on other updates for security and privacy, see this page.
For more information on all of the changes coming in Android 12, check out the blog post for Developer Preview 1!