Règle Broken Functionality : pourquoi Google refuse une app qui marche très bien sur votre téléphone
Google vous envoie une ligne : votre app ne respecte pas la règle Broken Functionality. Pas de trace d'appel, pas de capture, aucune étape pour reproduire. Vous installez le même build de production sur votre propre téléphone et tout fonctionne. Alors qu'est-ce que vous changez avant de renvoyer ? En général rien dans votre code — le testeur n'est jamais allé jusque-là.
Mis à jour en juillet 2026
Ce que dit vraiment la règle Broken Functionality
Broken Functionality est une section de la règle Google Play « Fonctionnalités, contenu et expérience utilisateur ». La règle tient en une phrase : les applications qui plantent, se ferment brutalement, se figent ou fonctionnent anormalement ne sont pas autorisées. Google donne exactement trois exemples — les applications qui ne s'installent pas, celles qui s'installent mais ne se chargent pas, et celles qui se chargent mais ne répondent pas.
Relisez et regardez ce qui n'y est PAS. Rien sur votre architecture, votre couverture de tests, votre framework ou la qualité de votre code. C'est une règle de comportement. Elle décrit ce qui s'est passé sur un appareil, dans une session, sur un réseau, pendant un examen qui dure quelques minutes. Cette distinction fait tout : on ne corrige pas ça en écrivant du meilleur code, mais en faisant survivre l'app aux cinq premières minutes avec un inconnu.
Règle Google Play : fonctionnalités, contenu et expérience utilisateur
Retrouvez votre ligne de refus exacte
Le corps du mail est un modèle envoyé à des milliers de développeurs. La ligne du problème en dessous, non — c'est ce qui ressemble le plus à un rapport de bug que vous obtiendrez. Cherchez la vôtre dans la première colonne.
| La ligne que Google vous a donnée | Ce que le testeur a vu | La cause réellement la plus probable | À faire avant de renvoyer |
|---|---|---|---|
App doesn't install | L'artefact n'est jamais devenu une installation fonctionnelle sur l'appareil de test. | Un échec à l'installation, pas un bug d'exécution : un minSdkVersion supérieur à l'appareil de test, un split d'ABI ou de densité manquant, ou une signature qui ne correspond pas. | Installez l'artefact que Google a réellement — téléchargez-le depuis votre canal de test interne, pas depuis Android Studio — sur un appareil conforme au minSdk que vous déclarez. |
App installs, but doesn't load | Elle s'est lancée, puis est restée sur un écran qui n'est jamais devenu utilisable. | Le splash attend quelque chose que la session du testeur n'a pas : un jeton d'authentification, un premier appel d'API, une config distante, un jeton FCM. | Démarrez l'app à froid en mode avion, sans session en cache. Si elle se fige au lieu d'afficher une erreur, vous venez de reproduire votre refus. |
App loads, but crashes | Un plantage dans les premières minutes de la session. | Un chemin de première utilisation que vous ne croisez jamais en local. Votre appareil a des données, celui du testeur n'en a pas : une liste vide ou un profil nul fait tomber l'écran. | Rapport préalable au lancement → onglet Stabilité. La trace d'appel y est déjà, depuis un appareil réel, côté Google. |
App loads, but is not responsive | Les appuis ne faisaient rien, ou l'interface s'est figée. | Du travail sur le thread principal au démarrage : un appel réseau synchrone, un gros parsing JSON, une migration de base. | Sortez-le du thread principal. Android déclenche un ANR au bout de 5 secondes sans traitement d'un événement d'entrée — un testeur abandonne bien avant le système. |
App contains icon(s) or button(s) that are not responsive | Certains contrôles ne faisaient rien à l'appui. | Des contrôles morts : une tuile « Bientôt disponible », un bouton derrière un feature flag éteint, une ligne de menu branchée sur rien, un lien qui tombe en 404. | Sur une installation neuve et sans compte, appuyez sur tous les contrôles de l'app. Tout ce qui ne répond pas est branché ou retiré — il n'y a pas de troisième option. |
Broken Functionality n'est pas Limited Functionality
Ce sont deux sections différentes de la même page de règles, et leurs corrections sont opposées. Broken Functionality veut dire que votre app échoue. Limited Functionality and Content veut dire que votre app fonctionne parfaitement et ne mérite quand même pas d'être installée — une WebView autour de votre site, un unique écran statique, une visionneuse pour un seul PDF. Confondre les deux vous envoie construire des fonctionnalités alors qu'il faut corriger un blocage.
| Broken Functionality | Limited Functionality and Content | |
|---|---|---|
| La règle | « Nous n'autorisons pas les applications qui plantent, se ferment brutalement, se figent ou fonctionnent anormalement. » | « Nous n'autorisons pas les applications dont les fonctionnalités et le contenu sont limités. » |
| Ce qui a raté | Votre app n'a pas fait ce qu'elle annonce. | Votre app a fait exactement ce qu'elle annonce. C'est bien le problème. |
| Déclencheur typique | Splash figé, plantage au premier lancement, bouton mort, serveur injoignable. | Un site dans une WebView, un écran de texte, une coquille sans valeur native. |
| La correction | Faire marcher le parcours existant sur un appareil vierge. | Construire ce qu'un onglet de navigateur ne sait pas faire — ou ne pas publier. |
| Le mauvais réflexe | Ajouter des fonctionnalités. | Corriger des bugs. |
Notre propre guide des refus Google Play mélangeait les deux en un seul point. C'était faux, et c'est une bonne partie de la raison d'être de cette page. Why Google Play rejects apps
Votre app fonctionne. Le testeur n'a quand même pas pu entrer.
C'est là que vivent réellement la plupart de ces refus, et presque personne n'en parle. Votre build est bon. Votre machine n'est pas celle du testeur. Faites cette liste avant de toucher une ligne de code.
- Un écran de connexion sans identifiants de test valides. Le testeur ouvre votre app, voit un formulaire, n'a rien à taper, et referme. Vu de l'extérieur, c'est indiscernable d'une app qui « s'installe mais ne se charge pas ».
- Un code à usage unique par SMS ou e-mail. Vous avez fourni un compte de démo, mais le code part sur un téléphone posé sur votre bureau. Google est explicite : si votre app exige normalement une validation en deux étapes ou un mot de passe à usage unique, vous devez fournir des identifiants réutilisables qui la contournent.
- Un serveur géo-bloqué ou filtré par liste d'IP. L'examen ne se fait pas depuis vos bureaux. Si votre API n'autorise que le CIDR du bureau, ou si l'app bloque des pays où vous ne vendez pas, le testeur atterrit sur votre écran d'erreur. La formulation de Google : les identifiants doivent être valides « quelle que soit la position de l'utilisateur », et un géo-blocage impose des identifiants maîtres.
- Une URL de préproduction ou localhost dans le build de production. Ça a l'air trop bête pour arriver et ça arrive tout le temps — une variante de build mal réglée, un .env non remplacé, une URL de debug qui survit à une fusion. Votre portable résout cet hôte via le VPN du bureau ou une ligne de /etc/hosts. L'appareil de test, non.
- Un serveur qui dort. Le scale-to-zero et les hébergements gratuits démarrent à froid en 5 à 30 secondes. Votre première requête du matin est lente et vous ne le remarquez plus. Chaque requête du testeur est une première requête du matin.
- Un feature flag resté éteint. Vous avez publié avec le drapeau distant désactivé, en prévoyant de l'allumer après validation. Le testeur teste ce qu'il a devant lui, trouve un écran vide, et refuse.
- Une clé d'API expirée, ou une clé Maps/Firebase restreinte à votre certificat de signature de debug. Play App Signing resigne votre release avec un SHA-1 différent de votre clé de debug. Toutes les tuiles et tous les appels échouent alors — en production seulement, jamais sur votre machine.
Chacun de ces cas produit une app impeccable sur votre bureau et cassée en examen. Et aucun n'apparaîtra jamais dans vos rapports de plantage, puisque rien n'a planté.
Comment donner un compte de test aux testeurs Google Play ?
Dans la Play Console, allez dans Règles et programmes → Contenu de l'application → Identifiants de connexion → Commencer (ou Gérer), cliquez sur « + Ajouter des instructions » et renseignez les accès. Vous pouvez en enregistrer jusqu'à cinq jeux. Ouvrez ensuite la page Aperçu de la publication et cliquez sur « Envoyer pour examen ». Si vous n'avez changé que les identifiants, inutile d'envoyer un nouveau .aab.
Les exigences de Google pour ces informations, dans leurs termes :
- Accessibles à tout moment, réutilisables et valides quelle que soit la position de l'utilisateur.
- Maintenues à tout moment et sans erreur.
- Fournies en anglais.
- Si la connexion n'est ni numérique ni alphanumérique — un QR code ou un code-barres — générez une URL statique et déposez-la dans la Play Console.
- Si l'utilisateur définit lui-même un code PIN ou un mot de passe pour accéder au contenu, donnez des instructions claires.
- Si vous vous appuyez sur la connexion Google, Facebook ou équivalent, fournissez toutes les informations du compte plus des instructions détaillées.
Le mode de panne dont personne ne vous prévient : votre compte de démo marche, puis ne marche plus. Un essai de 30 jours expire. Un limiteur de débit le bloque au troisième examen. Quelqu'un dans l'équipe réinitialise la base de test un vendredi. « Accessible à tout moment » travaille beaucoup dans cette phrase — traitez le compte d'examen comme de la donnée de production.
Un seul compte ne suffit pas non plus. Le testeur doit atteindre toutes les fonctionnalités que votre fiche Store annonce. Si l'onglet premium exige un abonnement payant, le compte de démo doit déjà avoir ce droit.
Google Play : conditions à respecter pour fournir des identifiants de connexion
Le rapport préalable au lancement vous ment si vous avez un écran de connexion
Le test Robo ne sait taper vos identifiants de test que dans les widgets Android standard et dans Compose. Il ne sait pas se connecter à travers un parcours d'authentification en WebView, ni piloter des contrôles rendus en OpenGL. Une app React Native ou Flutter avec une connexion en WebView obtient donc un rapport propre, sans plantage, qui couvre exactement un écran : celui de connexion. Rapport vert, app refusée.
Ajoutez un compte de test jetable dans Tests et versions → Tests → Rapport préalable au lancement → Paramètres. Jamais un vrai compte. Lisez ensuite l'onglet Captures d'écran avant l'onglet Stabilité — si les 20 captures sont votre écran de connexion, vous avez trouvé votre refus, et ce n'était jamais un plantage.
Google Play : utiliser un rapport préalable au lancement pour identifier les problèmes
À partir de quand « lent » compte comme « figé » ?
Android déclenche un ANR quand votre app ne répond pas à un événement d'entrée en 5 secondes. La même limite de 5 secondes s'applique à un receveur de diffusion au premier plan, et à l'appel de startForeground() après startForegroundService(). Ce sont les limites du système. La patience d'un testeur est bien plus courte, et on ne fait pas appel de l'ennui.
Pour situer les chiffres que Google juge lui-même inacceptables : les seuils de mauvais comportement d'Android vitals sont de 1,09 % de taux de plantage perçu par l'utilisateur et 0,47 % de taux d'ANR perçu, tous appareils confondus, ou 8 % sur un seul modèle. Les franchir vaut un avertissement sur votre fiche — mais vous pouvez rester très en dessous et être refusé quand même, parce qu'un examen est une session, pas une distribution.
Voilà ce que ça donne en pratique. Un développeur a posté la chaîne exacte « App installs, but doesn't load » sur le forum Android Builder, en assurant que rien n'était cassé ; relancé sur les détails, il a mentionné que « parfois l'écran 1 marque une pause de quelques secondes ». Pas de plantage. Pas d'ANR. Sous la limite système de 5 secondes. Refusé quand même.
Ce qui nous amène au moyen le plus efficace de décrocher ce refus : l'écran de splash qui masque un serveur mort. Il a exactement la même tête que votre API ait répondu en 200 ms ou jamais. Donnez-lui un délai d'expiration — 3 secondes, puis un vrai écran d'erreur avec un bouton Réessayer. Une app qui dit « Serveur injoignable » est une app qui marche et qui passe une mauvaise journée. Une app qui tourne indéfiniment, c'est « installs, but doesn't load ».
Android developers : les ANR · Seuils Android vitals
Reproduire en 30 minutes
- Placez-vous dans l'état du testeur. Un émulateur remis à zéro ou un appareil de rechange : aucun compte connecté, aucune session en cache, pas de VPN, pas de ligne dans /etc/hosts, données mobiles au lieu du wifi du bureau. Installez l'artefact que Google possède — téléchargez le .aab depuis votre canal de test interne plutôt que de compiler en local. Cette étape à elle seule trouve la majorité des cas.
- Ouvrez le rapport préalable au lancement (Tests et versions → Rapport préalable au lancement). L'onglet Captures d'écran d'abord : le robot a-t-il passé votre connexion ? Puis Stabilité pour la trace d'appel, et Performances pour le temps de démarrage.
- Lancez adb logcat pendant un démarrage à froid, filtré sur votre processus : adb logcat --pid=$(adb shell pidof -s com.your.package). Guettez la requête qui ne revient jamais. C'est votre splash figé.
- Vérifiez Crashlytics, et Play Console → Qualité → Android vitals → Plantages et ANR, filtrés sur le code de version que vous avez envoyé. Si les deux sont vides, votre problème n'a jamais été un plantage — retournez à la liste sur l'environnement du testeur, plus haut.
- Parcourez votre propre fiche Store. Ouvrez chaque capture, lisez chaque phrase de fonctionnalité, et faites exactement ça dans l'app, sur l'appareil vierge, dans l'ordre.
Votre fiche Store est le scénario de test
Les testeurs ne devinent pas ce que votre app est censée faire. Ils lisent votre fiche et vos captures, puis ils vérifient. Votre propre texte marketing devient donc le cahier des charges sur lequel on vous note. La capture d'une fonctionnalité qui sort le mois prochain est une fonctionnalité cassée aujourd'hui. Idem pour une tuile « Bientôt disponible », une ligne de Réglages qui n'ouvre rien, et un lien d'assistance qui pointe vers un 404. Coupez la capture ou livrez la fonctionnalité.
Renvoyer, ou contester ?
Renvoyez si vous avez trouvé une cause concrète et l'avez corrigée : nouveau code de version, Contenu de l'application à jour, Envoyer pour examen. Ne contestez que si vous êtes sûr que rien n'est cassé et que vous pouvez le montrer — vous avez un recours par mesure d'application, et la réponse arrive en général sous 2 jours ouvrés.
Conseil sans détour : la plupart des fils « il n'y a rien de cassé dans mon app !!! » sur la communauté Play se terminent par un développeur qui découvre un mur de connexion ou un serveur endormi. Faites d'abord la passe de 30 minutes. Si vous contestez et que vous avez tort, vous avez dépensé votre unique recours et une semaine de chiffre d'affaires.
Dans tous les cas, dites ce qui a changé. Les testeurs de Google travaillent avec la même ligne unique que vous. Collez ceci dans le formulaire de recours, ou dans le champ d'instructions des identifiants de connexion quand vous renvoyez :
brokenFunctionality.template
La version Apple du même refus
Apple appelle ça Guideline 2.1 — Performance — App Completeness, et c'est son motif de refus le plus cité. Mêmes causes profondes, autre console : le compte de démo se dépose dans App Store Connect → votre app → Informations pour l'examen de l'app, avec l'interrupteur « Connexion requise » activé, plus le champ Notes pour tout ce qu'un inconnu ne devinerait pas. Une différence compte beaucoup en pratique : Apple vous dit en général quel écran a échoué et joint une capture. Google vous donne une ligne. C'est cette asymétrie qui rend le tableau de décodage ci-dessus nécessaire.
Les motifs de refus App Store les plus fréquents
Ce que nous pouvons vérifier pour vous — et ce que nous ne pouvons pas
Envoyez le .aab ou l'.apk que vous vous apprêtez à soumettre et nous lisons son manifeste. Sur les 24 contrôles Android de l'outil, 10 tournent automatiquement, et quatre d'entre eux pointent directement sur des causes de Broken Functionality :
- usesCleartextTraffic — une URL de base en http:// qui marche sur votre machine et se fait bloquer en silence dans un build de production à partir d'Android 9.
- android:debuggable — un build de debug publié par accident, ce qui vaut de toute façon un refus immédiat à soi seul.
- Activité MAIN/LAUNCHER — aucun point d'entrée lançable, c'est littéralement « app doesn't load ».
- targetSdkVersion et minSdkVersion — l'incohérence derrière « app doesn't install » sur un appareil de test.
Les 14 autres sont les questions qu'aucun analyseur ne peut trancher à votre place, et trois d'entre elles sont exactement cette règle : est-ce que chaque fonctionnalité marche sans espace réservé ni lien mort, avez-vous testé sur de vrais appareils et regardé Android vitals, et l'app fait-elle quelque chose de réel au-delà d'une coquille autour d'un site.
Ce que nous ne pouvons pas faire, sans détour : nous n'exécutons pas votre app. Nous ne pouvons pas vous dire que votre serveur dort, que votre compte de démo a expiré mardi dernier, ou que votre clé Maps est liée au mauvais SHA-1. Aucun outil qui analyse un binaire ne le peut. C'est à ça que sert la passe de 30 minutes.
Questions fréquentes
Que veut dire « Your app contains content that isn't compliant with the Broken Functionality policy » ?
Que le testeur de Google a ouvert votre app et qu'elle a planté, s'est figée, ou n'est jamais devenue utilisable. C'est un verdict sur le comportement, pas une revue de code. La ligne courte qui suit — par exemple « App installs, but doesn't load » — est le seul diagnostic que vous aurez : commencez par là.
Mon app marche parfaitement. Pourquoi Google dit-il qu'elle est cassée ?
Parce que le testeur n'est ni sur votre appareil ni sur votre réseau. Un écran de connexion sans identifiants de test, une API filtrée sur l'IP de vos bureaux, une URL de préproduction dans le build de production ou un serveur endormi produisent tous une app qui échoue chez lui et marche chez vous. Rien de tout ça n'apparaît dans les rapports de plantage.
Dois-je envoyer un nouveau .aab pour corriger un refus Broken Functionality ?
Pas toujours. Si la cause était des identifiants de connexion manquants ou expirés, vous les mettez à jour dans Règles et programmes → Contenu de l'application → Identifiants de connexion et vous cliquez sur Envoyer pour examen depuis la page Aperçu de la publication — le build existant est resoumis. Si la cause est dans l'app, il faut un nouveau code de version.
Le rapport préalable au lancement détecte-t-il les problèmes Broken Functionality ?
En partie. Le test Robo trouve les plantages et les ANR sur de vrais appareils, mais il ne sait pas se connecter via une authentification en WebView ni piloter des contrôles rendus en OpenGL. Si votre app a une connexion en WebView, le rapport aura l'air propre en ne couvrant que l'écran de connexion. Regardez l'onglet Captures d'écran pour voir jusqu'où le robot est réellement allé.
Puis-je contester un refus Broken Functionality ?
Oui — un recours par mesure d'application, avec une réponse en général sous 2 jours ouvrés. Ne contestez que si vous avez reproduit les conditions du testeur sur un appareil vierge et que vous n'avez vraiment rien trouvé. Sinon, corrigez la cause, incrémentez le code de version et renvoyez ; c'est plus rapide que de perdre le recours.
Combien de temps prend la validation après un renvoi ?
Google ne garantit aucun délai, et cela varie d'un jour à deux semaines selon le compte et l'historique d'infractions. Prévoyez que ce renvoi soit le dernier : un deuxième refus Broken Functionality sur la même app coûte bien plus de temps que la passe de diagnostic de 30 minutes.
Sources
- Google Play — Fonctionnalités, contenu et expérience utilisateur (texte de la règle Broken Functionality)
- Google Play — Conditions à respecter pour fournir des identifiants de connexion
- Google Play — Fournir des informations pour l'examen (Contenu de l'application → Identifiants de connexion)
- Google Play — Utiliser un rapport préalable au lancement pour identifier les problèmes
- Android developers — Les ANR (le délai de 5 secondes sur les événements d'entrée)
- Android developers — Seuils de mauvais comportement Android vitals
- Google Play — Gérer les infractions aux règles et les recours
- Communauté Android Builder — « Issue found: Violation of Broken Functionality policy » (le cas de la pause de plusieurs secondes)
Vérifiez votre build avant de soumettre
Passez votre .ipa ou .apk dans App Review Checker et détectez ces problèmes en quelques secondes.
Analyser une app