Aller au contenu
Narvy

android:exported manquant : composants avec intent-filter sur Android 12+

Si votre application cible l'API 31 ou plus, chaque <activity>, <service> et <receiver> qui déclare un <intent-filter> doit indiquer android:exported="true" ou "false". Sans cet attribut, l'application ne peut pas être installée sur Android 12 ou plus, et Google Play la refuse. Ajoutez l'attribut, y compris sur les composants issus de bibliothèques, dans le manifeste fusionné.

Gradle, manifest merger
Apps targeting Android 12 and higher are required to specify an explicit value for `android:exported` when the corresponding component has an intent filter defined.
Play Console, à l'envoi
You uploaded an APK or Android App Bundle which has an activity, activity alias, service or broadcast receiver with intent filter, but without 'android:exported' property set. This file can't be installed on Android 12 or higher.
adb install
INSTALL_PARSE_FAILED_MANIFEST_MALFORMED: Failed parse during installPackageLI: /data/app/<tmp>/base.apk (at Binary XML file line #<N>): <component>: Targeting S+ (version 31 and above) requires that an explicit value for android:exported be defined when intent filters are present

Ce que cela signifie

Avant Android 12, un composant doté d'un intent-filter était exporté par défaut : n'importe quelle autre application pouvait le lancer. Depuis Android 12, la documentation d'Android indique qu'une application ciblant Android 12 ou plus qui contient des activités, services ou broadcast receivers utilisant des intent-filters doit déclarer explicitement android:exported ; sinon, elle ne peut pas être installée sur un appareil sous Android 12 ou plus.

Le contrôle lit le manifeste du fichier compilé, c'est-à-dire le manifeste fusionné : les composants déclarés par vos bibliothèques comptent aussi.

Échéance

Pas de date propre au store : c'est une règle de la plateforme, qui s'applique dès que votre targetSdkVersion vaut 31 ou plus. Comme Google Play exige un niveau d'API cible récent, toutes les applications du store sont concernées.

Corriger

1. Définir l'attribut sur vos propres composants

AndroidManifest.xml
<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>

<receiver
    android:name=".BootReceiver"
    android:exported="false">
    <intent-filter>
        <action android:name="android.intent.action.BOOT_COMPLETED" />
    </intent-filter>
</receiver>

Utilisez true uniquement lorsque d'autres applications ou le système doivent atteindre le composant (activité de lancement, activités de liens profonds, cible de partage). Utilisez false pour tout ce qui est interne.

2. Surcharger les composants issus de bibliothèques

Quand le composant appartient à une dépendance, la mettre à jour est la correction propre. Sinon, redéclarez-le dans votre manifeste avec l'attribut et laissez la fusion des manifestes combiner les deux :

AndroidManifest.xml (module app)
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    <application>
        <receiver
            android:name="com.example.sdk.SomeReceiver"
            android:exported="false"
            tools:node="merge" />
    </application>
</manifest>

3. Lire le manifeste fusionné

L'onglet Merged Manifest d'Android Studio montre quelle bibliothèque a apporté chaque composant. Le contrôle liste chaque composant fautif par son nom.

Vérifier avant de soumettre

Déposez l'APK, AAB ou lot d'APK fractionnés (XAPK, APKS, APKM) sur la page de contrôle des stores. Elle exécute PLAY-EXPORTED avec les dates de cette page, puis supprime le fichier : rien de l'application n'est conservé. Le même moteur tourne hors ligne dans la CLI Narvy et renvoie le code 1 quand un point bloquant est trouvé, ce qui permet de bloquer un job de CI.

Hors ligne, depuis un terminal (narvy-cli 1.2.0 ou plus)
narvy store-check app-release.aab --lang fr

Contrôler un build dans le navigateur

Questions fréquentes

L'attribut doit-il valoir true ou false ?

true rend le composant accessible aux autres applications, false le garde privé à votre application (et aux applications partageant le même identifiant utilisateur). Exporter un composant qui n'en a pas besoin élargit la surface d'attaque : partez de false.

Mon targetSdk est inférieur à 31. La règle s'applique-t-elle ?

Pas celle-ci : le contrôle la marque comme non applicable. Mais l'exigence de niveau d'API cible de Google Play vous obligera à relever la cible, et la règle s'appliquera dès que vous le ferez.

Les composants sans intent-filter sont-ils concernés ?

Non. Sans intent-filter, la valeur par défaut est déjà false, et le contrôle ne regarde que les activités, services et receivers qui en déclarent un.