Does omitting android:exported with intent filters cause install-time failures on API 31+
0 reputation · 18 Jan 2021, 19:00 UTC
0 reputation · 18 Jan 2021, 19:00 UTC
Android components such as activities, services, and broadcast receivers determine their accessibility to other applications based on the android:exported attribute. Historically, the platform assigned a default value based on whether the component contained an intent filter.
Starting with Android 12 (API 31), the platform shifted toward mandatory explicit declarations to prevent accidental public access. There is uncertainty regarding how the build system and the package manager handle legacy manifests that rely on implicit defaults when targeting these newer API levels.
What is the specific behavior when a component contains an intent filter but lacks an explicit android:exported declaration on API 31 and later? Does the application fail to install, or does the system apply a default value based on the presence of the filter?
35275 reputation · 18 Jan 2021, 20:30 UTC
If the effective targetSdkVersion of the APK is 31 or higher, an activity, service, or broadcast receiver that declares an <intent-filter> but omits android:exported is rejected during package parsing and the install fails. If the effective targetSdkVersion is 30 or lower, the legacy default (android:exported="true" when an intent filter is present) still applies, so the component is considered exported and the APK installs.
android:exported; the system no longer infers a default.adb install returns an error such as INSTALL_FAILED_INVALID_APK: Missing exported attribute.When targetSdkVersion ≥ 31, the package manager treats a missing android:exported as an error for any component with an intent filter, enforcing the new privacy‑by‑default policy. For lower targetSdkVersions the platform retains the historic behavior for compatibility.
defaultConfig { targetSdkVersion } in Gradle or inspect the merged manifest’s manifest tag for targetSdkVersion.app/build/intermediates/merged_manifests/debug/AndroidManifest.xml or equivalent) and locate every <activity>, <service>, or <receiver> that contains an <intent-filter> child but lacks an android:exported attribute../gradlew assembleDebug) and install it on an Android 12+ emulator or device:
adb install -r app/build/outputs/apk/debug/app-debug.apkINSTALL_FAILED_INVALID_APK: Missing exported attribute in ....android:exported.To give a definitive recommendation, I need to know the effective targetSdkVersion of the variant you are installing. If it is 31 or higher, you must add android:exported (true or false as appropriate) to every component with an intent filter; if it is 30 or lower, the existing manifest will continue to work on Android 12+ devices.
Use comments to ask for clarification. Post a solution as an answer.
35,275 reputation · 19 Jan 2021, 06:20 UTC
To clarify the specific failure mechanism: when targeting API 31 or higher, the package manager performs a strict validation check during the installation phase. If a component (Activity, Service, or Broadcast Receiver) contains an intent filter but lacks the android:exported attribute, the system will throw an INSTALL_FAILED_BAD_MANIFEST error.
It is important to note that this is not a runtime crash, but a complete installation failure. For developers troubleshooting this in complex projects, the issue may not be immediately obvious in the source manifest due to the manifest merger. Verification can be performed by:
adb logcat during the installation attempt to confirm the specific manifest error code.