Skip to content

Android 12 android:exported Property Requirement

Problem

Starting with Android 12 (API level 31), Google requires all app components with intent filters to explicitly declare the android:exported attribute. This security measure prevents unauthorized apps from accessing your app's components without proper configuration.

The error occurs when you upload an APK or Android App Bundle that contains activities, services, broadcast receivers, or activity aliases with intent filters but without the android:exported property explicitly set to either true or false.

Solution

1. Basic Fix: Add android:exported to Your Components

For each component in your AndroidManifest.xml that contains an <intent-filter>, add the android:exported attribute:

xml
<!-- For activities -->
<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>

<!-- For services -->
<service
    android:name=".MyService"
    android:exported="false">
    <intent-filter>
        <action android:name="com.example.app.ACTION_START" />
    </intent-filter>
</service>

<!-- For broadcast receivers -->
<receiver
    android:name=".MyReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

TIP

  • Set android:exported="true" for components that should be accessible from other apps
  • Set android:exported="false" for components that should only be used within your app
  • Components with the LAUNCHER category should typically have exported="true"

2. Identify Problematic Components Using Merged Manifest

Many issues come from third-party libraries that haven't been updated for Android 12 compliance. Use Android Studio's Merged Manifest view to identify all components:

  1. Open your project in Android Studio
  2. Navigate to app/src/main/AndroidManifest.xml
  3. Click the "Merged Manifest" tab at the bottom
  4. Look for components with intent filters missing the exported attribute

WARNING

If you don't see the Merged Manifest tab, ensure your build.gradle has compileSdkVersion and targetSdkVersion set to at least 30, then sync your project.

3. Fixing Third-Party Library Components

When you identify problematic components from libraries, override them in your main manifest:

xml
<!-- Example for Razorpay components -->
<activity
    android:name="com.razorpay.CheckoutActivity"
    android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
    android:theme="@style/CheckoutTheme"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <data
            android:host="rzp.io"
            android:scheme="io.rzp" />
    </intent-filter>
</activity>

<receiver 
    android:name="com.razorpay.RzpTokenReceiver"
    android:exported="true"
    android:permission="android.permission.INTERNET">
    <intent-filter>
        <action android:name="rzp.device_token.share" />
    </intent-filter>
</receiver>

4. Common Library Fixes

For specific libraries, here are common fixes:

Flutter Local Notifications:

xml
<receiver android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED"/>
        <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
    </intent-filter>
</receiver>

Firebase Messaging:

xml
<service
    android:name="com.google.firebase.messaging.FirebaseMessagingService"
    android:exported="true">
    <intent-filter android:priority="-500">
        <action android:name="com.google.firebase.MESSAGING_EVENT" />
    </intent-filter>
</service>

5. Alternative: Manual Merged Manifest Inspection

If you can't use Android Studio's Merged Manifest view:

  1. Build your project
  2. Locate the merged manifest file at: app/build/intermediates/merged_manifests/release/AndroidManifest.xml
  3. Search for components with <intent-filter> but without android:exported
  4. Copy these components to your main manifest and add the exported attribute

6. Framework-Specific Solutions

React Native: Update all third-party libraries to their latest versions, as many have been updated for Android 12 compliance.

Flutter: Ensure you're using updated versions of plugins, particularly:

  • flutter_local_notifications: ^15.1.1 or higher
  • Other plugins that use background services or receivers

Unity:

  1. Export your project as an Android project
  2. Open in Android Studio to use the Merged Manifest tool
  3. Copy problematic components to Assets/Plugin/Android/AndroidManifest.xml

Ionic/Cordova: Add to your config.xml:

xml
<platform name="android">
    <edit-config file="app/src/main/AndroidManifest.xml" mode="merge" 
                 target="/manifest/application/activity" 
                 xmlns:android="http://schemas.android.com/apk/res/android">
        <activity android:exported="true" />
    </edit-config>
</platform>

Best Practices

  1. Always explicitly declare android:exported for components with intent filters
  2. Keep libraries updated to avoid manual fixes
  3. Use the minimum necessary exposure - don't set exported="true" unless required
  4. Test thoroughly after making changes to ensure functionality isn't broken

DANGER

Avoid downgrading your targetSdkVersion to bypass this requirement, as this is a temporary fix that will eventually stop working and may cause other compatibility issues.

By following these steps, you should be able to resolve the Android 12 exported property requirement and successfully publish your app to the Google Play Store.