Broken Functionality-beleid: waarom Google een app afwijst die op jouw telefoon prima werkt
Google stuurt je één regel: je app voldoet niet aan het Broken Functionality-beleid. Geen stacktrace, geen screenshot, geen stappen om het na te bootsen. Je installeert dezelfde releasebuild op je eigen telefoon en het werkt. Wat verander je dan vóór je opnieuw indient? Meestal niets in je code — de beoordelaar is nooit zo ver gekomen.
Laatst bijgewerkt: juli 2026
Wat er echt in het Broken Functionality-beleid staat
Broken Functionality is een onderdeel van het Google Play-beleid «Functionaliteit, content en gebruikerservaring». De regel is één zin: apps die crashen, geforceerd afsluiten, vastlopen of anderszins abnormaal werken zijn niet toegestaan. Google geeft precies drie voorbeelden: apps die niet installeren, apps die installeren maar niet laden, en apps die laden maar niet reageren.
Lees dat nog eens en let op wat er NIET staat. Niets over je architectuur, je testdekking, je framework of je codekwaliteit. Het is een gedragsbeleid. Het beschrijft wat er gebeurde op één toestel, in één sessie, op één netwerk, tijdens een beoordeling van enkele minuten. Dat onderscheid is het hele spel: je lost het niet op door betere code te schrijven, maar door de app de eerste vijf minuten met een vreemde te laten overleven.
Google Play-beleid: functionaliteit, content en gebruikerservaring
Zoek je exacte afwijzingsregel
De tekst van de e-mail is een sjabloon dat naar duizenden ontwikkelaars gaat. De regel met het probleem eronder niet — dat is het dichtste bij een bugrapport dat je gaat krijgen. Zoek die van jou in de eerste kolom.
| De regel die Google je gaf | Wat de beoordelaar zag | De oorzaak die het waarschijnlijkst is | Doe dit vóór je opnieuw indient |
|---|---|---|---|
App doesn't install | Het artefact is op het beoordelingstoestel nooit een werkende installatie geworden. | Een fout bij het installeren, geen runtimebug: een minSdkVersion boven het testtoestel, een ontbrekende ABI- of density-split, of een niet-kloppende ondertekening. | Installeer het artefact dat Google echt heeft — download het uit je interne testtrack, niet uit Android Studio — op een toestel dat past bij de minSdk die je opgeeft. |
App installs, but doesn't load | Hij startte en bleef daarna op een scherm staan dat nooit bruikbaar werd. | De splash wacht op iets wat de sessie van de beoordelaar niet heeft: een authenticatietoken, een eerste API-aanroep, het ophalen van remote config, een FCM-token. | Start de app koud op in vliegtuigmodus, zonder sessie in de cache. Blijft hij hangen in plaats van een foutmelding te tonen, dan heb je je afwijzing net nagebootst. |
App loads, but crashes | Een crash in de eerste minuten van de sessie. | Een pad bij eerste gebruik dat je lokaal nooit raakt. Jouw toestel heeft data, dat van de beoordelaar niet: een lege lijst of een leeg profiel legt het scherm plat. | Pre-launchrapport → tabblad Stabiliteit. De stacktrace ligt er al, van een echt toestel, aan de kant van Google. |
App loads, but is not responsive | Tikken deed niets, of de interface liep vast. | Werk op de hoofdthread tijdens het opstarten: een synchrone netwerkaanroep, een grote JSON-parsing, een databasemigratie. | Haal dat van de hoofdthread af. Android geeft een ANR na 5 seconden zonder afgehandelde invoergebeurtenis — een beoordelaar haakt ruim vóór het systeem af. |
App contains icon(s) or button(s) that are not responsive | Bepaalde knoppen deden niets bij aanraking. | Dode bedieningselementen: een tegel «Binnenkort», een CTA achter een uitgeschakelde feature flag, een menuregel die nergens heen gaat, een link die 404 geeft. | Tik op een schone installatie zonder account op elk bedieningselement in de app. Alles wat niet reageert wordt aangesloten of verwijderd — een derde optie is er niet. |
Broken Functionality is niet Limited Functionality
Dit zijn twee verschillende onderdelen van dezelfde beleidspagina, en hun oplossingen zijn tegengesteld. Broken Functionality betekent dat je app faalt. Limited Functionality and Content betekent dat je app prima werkt en tóch niet de moeite van installeren waard is: een WebView om je website, één statisch scherm, een viewer voor één pdf. Wie die twee verwart, gaat functies bouwen terwijl hij een vastloper moet oplossen.
| Broken Functionality | Limited Functionality and Content | |
|---|---|---|
| De regel | «We staan geen apps toe die crashen, geforceerd afsluiten, vastlopen of anderszins abnormaal werken.» | «We staan geen apps toe met slechts beperkte functionaliteit en content.» |
| Wat er misging | Je app deed niet wat hij belooft. | Je app deed precies wat hij belooft. Dat is nu juist het probleem. |
| Typische aanleiding | Vastgelopen splash, crash bij eerste start, dode knop, onbereikbare backend. | Een website in een WebView, één tekstscherm, een omhulsel zonder native meerwaarde. |
| De oplossing | De bestaande flow laten werken op een schoon toestel. | Iets bouwen wat een browsertabblad niet kan — of niet publiceren. |
| De verkeerde reflex | Functies toevoegen. | Bugs oplossen. |
Onze eigen gids over Google Play-afwijzingen gooide die twee in één opsommingspunt. Dat was fout, en het is een flink deel van de reden dat deze pagina bestaat. Why Google Play rejects apps
Je app werkt. De beoordelaar kwam er tóch niet in.
Hier zitten de meeste van deze afwijzingen echt, en bijna niemand schrijft erover. Je build is in orde. Jouw machine is niet die van de beoordelaar. Loop deze lijst af vóór je één regel code aanraakt.
- Een inlogscherm zonder werkende testgegevens. De beoordelaar opent je app, ziet een inlogformulier, heeft niets in te tikken en sluit hem weer. Van buitenaf is dat niet te onderscheiden van een app die «installeert maar niet laadt».
- Een eenmalige code per sms of e-mail. Je leverde een demo-account, maar de code gaat naar een telefoon op jouw bureau. Google is expliciet: vereist je app normaal gesproken tweestapsverificatie of een eenmalig wachtwoord, dan moet je herbruikbare gegevens leveren die dat omzeilen.
- Een geoblokkeerde backend of een backend met IP-allowlist. De beoordeling gebeurt niet vanaf jouw kantoor. Laat je API alleen de CIDR van kantoor toe, of blokkeert de app landen waar je niet verkoopt, dan landt de beoordelaar op je foutscherm. Googles eigen formulering: de inloggegevens moeten geldig zijn «ongeacht de locatie van de gebruiker», en een geoblokkade vraagt om mastergegevens.
- Een staging- of localhost-basis-URL in de releasebuild. Het klinkt te dom om waar te zijn en het gebeurt voortdurend: een verkeerd ingestelde buildvariant, een .env die niet is omgewisseld, een debug-URL die een merge overleefde. Jouw laptop lost die host op via de kantoor-VPN of een regel in /etc/hosts. Het beoordelingstoestel niet.
- Een backend die slaapt. Scale-to-zero en gratis hosting starten koud op in 5 tot 30 seconden. Je eerste verzoek van de ochtend is traag en dat merk je allang niet meer. Elk verzoek van de beoordelaar is een eerste verzoek van de ochtend.
- Een feature flag die uit bleef staan. Je publiceerde met de remote flag uit, met het plan hem na goedkeuring om te zetten. De beoordelaar test wat er voor hem staat, vindt een leeg scherm en wijst af.
- Een verlopen API-sleutel, of een Maps-/Firebase-sleutel die beperkt is tot je debug-ondertekeningscertificaat. Play App Signing ondertekent je release opnieuw met een andere SHA-1 dan je debugsleutel. Daarna falen alle tegels en alle aanroepen — alleen in productie, nooit op jouw machine.
Elk van deze gevallen levert een app op die op je bureau vlekkeloos is en in de beoordeling kapot. En geen enkele duikt ooit op in je crashrapporten, want er is niets gecrasht.
Hoe geef ik Google Play-beoordelaars een testaccount?
Ga in de Play Console naar Beleid en programma's → App-inhoud → Inloggegevens → Starten (of Beheren), klik op «+ Nieuwe instructies toevoegen» en vul de toegangsgegevens in. Je kunt tot vijf sets toevoegen. Open daarna de pagina Overzicht van publicatie en klik op «Indienen voor beoordeling». Heb je alleen de inloggegevens veranderd, dan hoef je geen nieuwe .aab te uploaden.
Googles eisen aan die gegevens, in hun eigen woorden:
- Altijd bereikbaar, herbruikbaar en geldig ongeacht de locatie van de gebruiker.
- Op elk moment onderhouden en zonder fouten.
- Aangeleverd in het Engels.
- Is het inloggen niet numeriek of alfanumeriek — een QR-code of streepjescode — genereer dan een statische URL en upload die naar de Play Console.
- Stelt de gebruiker zelf een pincode of wachtwoord in om bij content in de app te komen, geef dan duidelijke instructies.
- Leun je op Inloggen met Google, Facebook of vergelijkbaar, lever dan alle accountinformatie plus gedetailleerde instructies.
De faalwijze waar niemand je voor waarschuwt: je demo-account werkt, en dan ineens niet meer. Een proefperiode van 30 dagen loopt af. Een rate limiter blokkeert het bij de derde beoordeling. Iemand in het team reset op vrijdag de testdatabase. «Altijd bereikbaar» doet in die zin veel werk — behandel het beoordelingsaccount als productiedata.
Eén account is trouwens ook niet genoeg. De beoordelaar moet elke functie kunnen bereiken die je storevermelding aanprijst. Vereist het premiumtabblad een betaald abonnement, dan moet het demo-account dat recht al hebben.
Google Play: vereisten voor het aanleveren van inloggegevens voor beoordeling
Het pre-launchrapport liegt tegen je als je een inlogscherm hebt
De Robo-test kan je testgegevens alleen intikken in standaard Android-widgets en in Compose. Hij kan niet inloggen via een authenticatieflow op basis van WebView en kan geen bedieningselementen aansturen die je app in OpenGL tekent. Een React Native- of Flutter-app met een WebView-login krijgt dus een schoon, crashvrij pre-launchrapport over precies één scherm: het inlogscherm. Groen rapport, afgewezen app.
Voeg een wegwerp-testaccount toe onder Testen en uitrollen → Testen → Pre-launchrapport → Instellingen. Nooit een echt account. Lees daarna het tabblad Screenshots vóór het tabblad Stabiliteit: zijn alle 20 screenshots je inlogscherm, dan heb je je afwijzing gevonden en was het nooit een crash.
Google Play: een pre-launchrapport gebruiken om problemen op te sporen
Vanaf wanneer telt traag als vastgelopen?
Android geeft een ANR als je app niet binnen 5 seconden op een invoergebeurtenis reageert. Dezelfde grens van 5 seconden geldt voor een broadcast receiver op de voorgrond en voor het aanroepen van startForeground() na startForegroundService(). Dat zijn de grenzen van het systeem. Het geduld van een beoordelaar is veel korter, en tegen verveling is geen bezwaar mogelijk.
Om de getallen te plaatsen die Google zelf onacceptabel vindt: de drempels voor slecht gedrag in Android vitals liggen op een door gebruikers waargenomen crashpercentage van 1,09 % en een waargenomen ANR-percentage van 0,47 % over alle toestellen, of 8 % op één model. Ga je erover, dan krijgt je storevermelding een waarschuwing — maar je kunt er ruim onder zitten en toch worden afgewezen, want een beoordeling is één sessie, geen verdeling.
Zo ziet dat er in de praktijk uit. Een ontwikkelaar plaatste precies de tekst «App installs, but doesn't load» op het Android Builder-forum en hield vol dat er niets mis was; doorgevraagd noemde hij dat «scherm 1 soms een paar seconden blijft staan». Geen crash. Geen ANR. Onder de systeemgrens van 5 seconden. Toch afgewezen.
Wat ons bij de efficiëntste manier brengt om deze afwijzing te verdienen: het splashscherm dat een dode backend verbergt. Het ziet er identiek uit of je API nu in 200 ms antwoordde of helemaal nooit. Geef het een time-out — 3 seconden, dan een echt foutscherm met een knop Opnieuw proberen. Een app die zegt «Kan de server niet bereiken» is een werkende app met een slechte dag. Een app die eindeloos draait, is «installs, but doesn't load».
Android developers: ANR's · Drempels van Android vitals
Nabootsen in 30 minuten
- Breng jezelf in de toestand van de beoordelaar. Een gewiste emulator of een reservetoestel: geen ingelogd account, geen sessie in de cache, geen VPN, geen regel in /etc/hosts, mobiele data in plaats van kantoorwifi. Installeer het artefact dat Google heeft: download de .aab uit je interne testtrack in plaats van lokaal te bouwen. Alleen deze stap vindt de meeste gevallen.
- Open het pre-launchrapport (Testen en uitrollen → Pre-launchrapport). Eerst het tabblad Screenshots: is de crawler voorbij je login gekomen? Daarna Stabiliteit voor de stacktrace en Prestaties voor de opstarttijd.
- Draai adb logcat tijdens een koude start, gefilterd op je proces: adb logcat --pid=$(adb shell pidof -s com.your.package). Let op het verzoek dat nooit terugkomt. Dat is je vastgelopen splash.
- Bekijk Crashlytics en Play Console → Kwaliteit → Android vitals → Crashes en ANR's, gefilterd op de versiecode die je hebt ingediend. Zijn beide leeg, dan was je probleem nooit een crash: terug naar de lijst over de omgeving van de beoordelaar hierboven.
- Loop je eigen storevermelding door. Open elke screenshot, lees elke functiezin en doe precies dat in de app, op het schone toestel, op volgorde.
Je storevermelding is het testscript
Beoordelaars raden niet wat je app hoort te doen. Ze lezen je vermelding en je screenshots, en controleren dat vervolgens. Daarmee wordt je eigen marketingtekst de specificatie waarop je wordt beoordeeld. De screenshot van een functie die volgende maand komt, is vandaag een kapotte functie. Dat geldt ook voor een tegel «Binnenkort», een regel in Instellingen die niets opent en een supportlink die naar een 404 wijst. Schrap de screenshot of lever de functie.
Opnieuw indienen of bezwaar maken?
Dien opnieuw in als je een concrete oorzaak hebt gevonden en opgelost: nieuwe versiecode, App-inhoud bijgewerkt, Indienen voor beoordeling. Maak alleen bezwaar als je zeker weet dat er niets kapot is en je dat kunt laten zien — je krijgt één bezwaar per handhavingsmaatregel, en het antwoord komt doorgaans binnen zo'n 2 werkdagen.
Onomwonden advies: de meeste «er is niets kapot aan mijn app!!!»-draadjes in de Play-community eindigen ermee dat de ontwikkelaar een inlogmuur of een slapende backend vindt. Doe eerst de ronde van 30 minuten. Maak je bezwaar en heb je het mis, dan ben je je enige bezwaar én een week omzet kwijt.
Zeg hoe dan ook wat er is veranderd. De beoordelaars van Google werken met dezelfde ene regel als jij. Plak dit in het bezwaarformulier, of in het instructieveld van de inloggegevens als je opnieuw indient:
brokenFunctionality.template
De Apple-versie van dezelfde afwijzing
Apple noemt dit Guideline 2.1 — Performance — App Completeness, en het is hun meest genoemde afwijzingsreden. Dezelfde onderliggende oorzaken, andere console: het demo-account gaat in App Store Connect → je app → App Review-informatie, met de schakelaar «Inloggen vereist» aan, plus het veld Notities voor alles wat een vreemde niet kan raden. Eén verschil telt in de praktijk zwaar: Apple vertelt je meestal welk scherm faalde en voegt een screenshot bij. Google geeft je één regel. Die scheefheid is de reden dat de decodeertabel hierboven moest bestaan.
De meest voorkomende afwijzingsredenen in de App Store
Wat we voor je kunnen controleren — en wat niet
Upload de .aab of .apk die je op het punt staat in te dienen en wij lezen het manifest. Van de 24 Android-controles in de tool draaien er 10 automatisch, en vier daarvan wijzen rechtstreeks naar Broken Functionality-oorzaken:
- usesCleartextTraffic — een http://-basis-URL die op jouw machine werkt en in een releasebuild vanaf Android 9 stilzwijgend wordt geblokkeerd.
- android:debuggable — een per ongeluk gepubliceerde debugbuild, wat op zichzelf al meteen een afwijzing oplevert.
- MAIN/LAUNCHER-activity — geen startbaar toegangspunt is letterlijk «app doesn't load».
- targetSdkVersion en minSdkVersion — de mismatch achter «app doesn't install» op een beoordelingstoestel.
De andere 14 zijn de vragen die geen parser voor je kan beantwoorden, en drie ervan zijn precies dit beleid: werkt elke functie zonder placeholders of dode links, heb je op echte toestellen getest en Android vitals bekeken, en doet de app iets echts voorbij een omhulsel om een website.
Wat we ronduit niet kunnen: we voeren je app niet uit. We kunnen je niet vertellen dat je backend slaapt, dat je demo-account afgelopen dinsdag is verlopen of dat je Maps-sleutel aan de verkeerde SHA-1 hangt. Geen enkele tool die een binary uitleest kan dat. Daarvoor is de ronde van 30 minuten.
Veelgestelde vragen
Wat betekent «Your app contains content that isn't compliant with the Broken Functionality policy»?
Het betekent dat de beoordelaar van Google je app opende en dat die crashte, vastliep of nooit bruikbaar werd. Het is een oordeel over gedrag, geen codereview. De korte regel eronder — bijvoorbeeld «App installs, but doesn't load» — is de enige diagnose die je krijgt, dus begin daar.
Mijn app werkt prima. Waarom zegt Google dat hij kapot is?
Omdat de beoordelaar niet op jouw toestel of jouw netwerk zit. Een inlogscherm zonder testgegevens, een API met een allowlist op het IP van je kantoor, een staging-URL in de releasebuild of een slapende backend leveren allemaal een app op die bij hem faalt en bij jou werkt. Niets daarvan komt in crashrapporten terecht.
Moet ik een nieuwe .aab uploaden om een Broken Functionality-afwijzing op te lossen?
Niet altijd. Was de oorzaak ontbrekende of verlopen inloggegevens, dan werk je die bij onder Beleid en programma's → App-inhoud → Inloggegevens en klik je op Indienen voor beoordeling op de pagina Overzicht van publicatie — de bestaande build wordt opnieuw ingediend. Zit de oorzaak in de app, dan heb je een nieuwe versiecode nodig.
Vindt het pre-launchrapport Broken Functionality-problemen?
Deels. De Robo-test vindt crashes en ANR's op echte toestellen, maar kan niet inloggen via een WebView-login en geen in OpenGL getekende bedieningselementen aansturen. Heeft je app een WebView-login, dan ziet het rapport er schoon uit terwijl het alleen het inlogscherm dekt. Kijk op het tabblad Screenshots hoe ver de crawler echt kwam.
Kan ik bezwaar maken tegen een Broken Functionality-afwijzing?
Ja — één bezwaar per handhavingsmaatregel, met een antwoord meestal binnen zo'n 2 werkdagen. Maak alleen bezwaar als je de omstandigheden van de beoordelaar op een schoon toestel hebt nagebootst en echt niets hebt gevonden. Los anders de oorzaak op, verhoog de versiecode en dien opnieuw in; dat is sneller dan het bezwaar verliezen.
Hoe lang duurt goedkeuring nadat ik opnieuw heb ingediend?
Google garandeert geen doorlooptijd, en die varieert van een dag tot een paar weken, afhankelijk van het account en de overtredingsgeschiedenis. Ga ervan uit dat deze indiening je laatste is: een tweede Broken Functionality-afwijzing op dezelfde app kost veel meer tijd dan de diagnoseronde van 30 minuten zou hebben gekost.
Bronnen
- Google Play — Functionaliteit, content en gebruikerservaring (de tekst van het Broken Functionality-beleid)
- Google Play — Vereisten voor het aanleveren van inloggegevens voor beoordeling
- Google Play — Informatie aanleveren voor de app-beoordeling (App-inhoud → Inloggegevens)
- Google Play — Een pre-launchrapport gebruiken om problemen op te sporen
- Android developers — ANR's (de time-out van 5 seconden op invoergebeurtenissen)
- Android developers — Drempels voor slecht gedrag in Android vitals
- Google Play — Beleidsovertredingen en bezwaren beheren
- Android Builder-community — «Issue found: Violation of Broken Functionality policy» (het geval van de pauze van enkele seconden)
Controleer je build voordat je indient
Haal je .ipa of .apk door App Review Checker en vang deze problemen op in seconden.
Controleer een app