Policy Broken Functionality: perché Google rifiuta un'app che sul tuo telefono funziona benissimo

Google ti manda una riga: la tua app non rispetta la policy Broken Functionality. Nessuno stack trace, nessuno screenshot, nessun passo per riprodurre il problema. Installi la stessa build di release sul tuo telefono e funziona. Allora che cosa cambi prima di ripresentarla? Di solito niente nel codice: il revisore non è mai arrivato fin lì.

Ultimo aggiornamento: luglio 2026

Cosa dice davvero la policy Broken Functionality

Broken Functionality è una sezione della policy di Google Play «Funzionalità, contenuti ed esperienza utente». La regola è una frase: non sono ammesse app che vanno in crash, si chiudono in modo forzato, si bloccano o funzionano in modo anomalo. Google porta esattamente tre esempi: app che non si installano, app che si installano ma non si caricano e app che si caricano ma non rispondono.

Rileggila e nota che cosa NON c'è. Niente sulla tua architettura, sulla copertura dei test, sul framework o sulla qualità del codice. È una policy sul comportamento. Descrive che cosa è successo su un dispositivo, in una sessione, su una rete, durante una revisione che dura minuti. Quella distinzione è tutto: non si risolve scrivendo codice migliore, ma facendo sopravvivere l'app ai primi cinque minuti con uno sconosciuto.

Policy di Google Play: funzionalità, contenuti ed esperienza utente

Trova la tua riga di rifiuto esatta

Il corpo dell'email è un modello inviato a migliaia di sviluppatori. La riga del problema sotto no: è la cosa più simile a una segnalazione di bug che riceverai. Cerca la tua nella prima colonna.

La riga che ti ha dato GoogleChe cosa ha visto il revisoreLa causa davvero più probabileFai questo prima di ripresentarla
App doesn't installL'artefatto non è mai diventato un'installazione funzionante sul dispositivo di revisione.Un errore in fase di installazione, non un bug a runtime: un minSdkVersion superiore al dispositivo di test, uno split ABI o di densità mancante, o una firma che non combacia.Installa l'artefatto che Google ha davvero — scaricalo dal tuo canale di test interno, non da Android Studio — su un dispositivo coerente con il minSdk che dichiari.
App installs, but doesn't loadSi è avviata e poi è rimasta su una schermata che non è mai diventata utilizzabile.Lo splash aspetta qualcosa che la sessione del revisore non ha: un token di autenticazione, una prima chiamata API, un recupero di configurazione remota, un token FCM.Avvia l'app a freddo in modalità aereo, senza sessione in cache. Se resta appesa invece di mostrare un errore, hai appena riprodotto il tuo rifiuto.
App loads, but crashesUn crash nei primi minuti della sessione.Un percorso di primo utilizzo che in locale non tocchi mai. Il tuo dispositivo ha dati, quello del revisore no: una lista vuota o un profilo nullo fa cadere la schermata.Rapporto pre-lancio → scheda Stabilità. Lo stack trace è già lì, da un dispositivo reale, dalla parte di Google.
App loads, but is not responsiveI tap non facevano nulla, oppure l'interfaccia si è bloccata.Lavoro sul thread principale all'avvio: una chiamata di rete sincrona, un parsing JSON pesante, una migrazione del database.Spostalo fuori dal thread principale. Android genera un ANR dopo 5 secondi senza gestire un evento di input: un revisore molla molto prima del sistema.
App contains icon(s) or button(s) that are not responsiveAlcuni comandi non facevano nulla al tocco.Comandi morti: un riquadro «Prossimamente», una CTA dietro un feature flag spento, una voce di menu collegata a nulla, un link che dà 404.Su un'installazione pulita e senza account, tocca ogni comando dell'app. Tutto ciò che non risponde va collegato o rimosso: non c'è una terza opzione.
Righe di problema come compaiono sotto il verdetto Broken Functionality nella Play Console. La prima, la terza e la quarta sono esempi pubblicati da Google stessa; le altre sono stringhe ricorrenti segnalate nella community degli sviluppatori Play.

Broken Functionality non è Limited Functionality

Sono due sezioni diverse della stessa pagina di policy, e hanno soluzioni opposte. Broken Functionality significa che la tua app fallisce. Limited Functionality and Content significa che la tua app funziona benissimo e comunque non merita di essere installata: una WebView attorno al tuo sito, una singola schermata statica, un visualizzatore per un solo PDF. Confonderle ti manda a costruire funzioni quando devi risolvere un blocco.

Broken FunctionalityLimited Functionality and Content
La regola«Non sono ammesse app che vanno in crash, si chiudono in modo forzato, si bloccano o funzionano in modo anomalo.»«Non sono ammesse app che offrono solo funzionalità e contenuti limitati.»
Che cosa è andato stortoLa tua app non ha fatto quello che dichiara di fare.La tua app ha fatto esattamente quello che dichiara. È proprio questo il problema.
Innesco tipicoSplash bloccato, crash al primo avvio, pulsante morto, backend irraggiungibile.Un sito dentro una WebView, una schermata di testo, un involucro senza valore nativo.
La soluzioneFar funzionare il flusso esistente su un dispositivo pulito.Costruire qualcosa che una scheda del browser non sa fare, oppure non pubblicarla.
La mossa sbagliataAggiungere funzioni.Correggere bug.

La nostra stessa guida ai rifiuti di Google Play metteva le due cose in un unico punto. Era sbagliato, ed è buona parte del motivo per cui esiste questa pagina. Why Google Play rejects apps

La tua app funziona. Il revisore comunque non è riuscito a entrare.

È qui che vive davvero la maggior parte di questi rifiuti, e quasi nessuno ne scrive. La tua build è a posto. La tua macchina non è quella del revisore. Fai questa lista prima di toccare una riga di codice.

  • Una schermata di login senza credenziali di prova funzionanti. Il revisore apre l'app, vede un modulo di accesso, non ha nulla da digitare e chiude. Da fuori è indistinguibile da un'app che «si installa ma non si carica».
  • OTP via SMS o email. Hai fornito un account demo, ma il codice arriva a un telefono sulla tua scrivania. Google è esplicita: se la tua app richiede normalmente una verifica in due passaggi o una password monouso, devi fornire credenziali riutilizzabili che la aggirino.
  • Un backend geobloccato o con allowlist di IP. La revisione non parte dal tuo ufficio. Se la tua API ammette solo il CIDR dell'ufficio, o l'app blocca Paesi in cui non vendi, il revisore atterra sulla tua schermata di errore. La formulazione di Google è che le credenziali devono essere valide «indipendentemente dalla posizione dell'utente», e che un geoblocco richiede credenziali master.
  • Un URL di staging o localhost nella build di release. Sembra troppo banale per accadere e accade di continuo: una variante di build configurata male, un .env non sostituito, un URL di debug sopravvissuto a un merge. Il tuo portatile risolve quell'host tramite la VPN dell'ufficio o una riga di /etc/hosts. Il dispositivo di revisione no.
  • Un backend che dorme. Lo scale-to-zero e gli hosting gratuiti partono a freddo in 5-30 secondi. La tua prima richiesta della mattina è lenta e hai smesso di farci caso. Ogni richiesta del revisore è una prima richiesta della mattina.
  • Un feature flag rimasto spento. Hai pubblicato con il flag remoto disattivato, contando di accenderlo dopo l'approvazione. Il revisore prova quello che ha davanti, trova una schermata vuota e rifiuta.
  • Una chiave API scaduta, o una chiave Maps/Firebase limitata al tuo certificato di firma di debug. Play App Signing rifirma la tua release con uno SHA-1 diverso da quello della chiave di debug. Da lì ogni riquadro e ogni chiamata falliscono: solo in produzione, mai sulla tua macchina.

Ognuno di questi casi produce un'app impeccabile sulla tua scrivania e rotta in revisione. E nessuno comparirà mai nei tuoi report di crash, perché non è andato in crash nulla.

Come do un account di prova ai revisori di Google Play?

Nella Play Console vai su Norme e programmi → Contenuti dell'app → Dettagli di accesso → Inizia (o Gestisci), clicca su «+ Aggiungi nuove istruzioni» e compila i dati di accesso. Puoi inserirne fino a cinque set. Poi apri la pagina Panoramica della pubblicazione e clicca su «Invia per la revisione». Se hai cambiato solo le credenziali, non serve caricare un nuovo .aab.

I requisiti di Google per quei dati, nelle loro parole:

  • Accessibili in qualsiasi momento, riutilizzabili e validi indipendentemente dalla posizione dell'utente.
  • Mantenuti sempre attivi e privi di errori.
  • Forniti in inglese.
  • Se l'accesso non è numerico né alfanumerico — un codice QR o un codice a barre — genera un URL statico e caricalo nella Play Console.
  • Se l'utente imposta un PIN o una password propri per arrivare ai contenuti dell'app, fornisci istruzioni chiare.
  • Se ti affidi all'accesso con Google, Facebook o simili, fornisci tutte le informazioni dell'account più istruzioni dettagliate.

Il guasto di cui nessuno ti avvisa: il tuo account demo funziona, e poi smette. Scade una prova di 30 giorni. Un rate limiter lo blocca alla terza revisione. Qualcuno in team resetta il database di test di venerdì. «Accessibili in qualsiasi momento» sta lavorando parecchio in quella frase: tratta l'account di revisione come dati di produzione.

Un solo account non basta comunque. Il revisore deve raggiungere ogni funzione che la tua scheda dello store pubblicizza. Se la scheda premium richiede un piano a pagamento, l'account demo deve avere già quel diritto attivo.

Google Play: requisiti per fornire i dettagli di accesso per la revisione

Il rapporto pre-lancio ti mente se hai una schermata di login

Il test Robo sa digitare le tue credenziali di prova solo nei widget Android standard e in Compose. Non sa accedere attraverso un flusso di autenticazione basato su WebView e non sa guidare comandi che la tua app disegna in OpenGL. Così un'app React Native o Flutter con login in WebView ottiene un rapporto pulito e senza crash che copre esattamente una schermata: quella di login. Rapporto verde, app rifiutata.

Aggiungi un account di prova usa e getta in Test e rilascio → Test → Rapporto pre-lancio → Impostazioni. Mai un account vero. Poi leggi la scheda Screenshot prima della scheda Stabilità: se tutti e 20 gli screenshot sono la tua schermata di login, hai trovato il tuo rifiuto e non è mai stato un crash.

Google Play: usare un rapporto pre-lancio per individuare i problemi

Da quando «lento» conta come «bloccato»?

Android genera un ANR quando la tua app non risponde a un evento di input entro 5 secondi. Lo stesso limite di 5 secondi vale per un broadcast receiver in primo piano e per la chiamata a startForeground() dopo startForegroundService(). Questi sono i limiti del sistema. La pazienza di un revisore è molto più corta, e contro la noia non c'è ricorso.

Per inquadrare i numeri che Google stessa considera inaccettabili: le soglie di comportamento anomalo di Android vitals sono l'1,09 % di tasso di crash percepito dall'utente e lo 0,47 % di tasso di ANR percepito su tutti i dispositivi, oppure l'8 % su un singolo modello. Superarle porta un avviso sulla scheda dello store, ma puoi restare ben sotto e venire comunque rifiutato, perché una revisione è una sessione, non una distribuzione.

Ecco come si presenta nella pratica. Uno sviluppatore ha pubblicato la stringa esatta «App installs, but doesn't load» sul forum Android Builder, insistendo che non c'era nulla di rotto; incalzato sui dettagli, ha detto che «a volte la schermata 1 si ferma per qualche secondo». Nessun crash. Nessun ANR. Sotto il limite di sistema di 5 secondi. Rifiutata lo stesso.

Il che ci porta al modo più efficiente di guadagnarsi questo rifiuto: lo splash screen che nasconde un backend morto. È identico sia che la tua API abbia risposto in 200 ms sia che non abbia mai risposto. Dagli un timeout — 3 secondi, poi una vera schermata di errore con un pulsante Riprova. Un'app che dice «Impossibile raggiungere il server» è un'app che funziona in una brutta giornata. Un'app che gira all'infinito è «installs, but doesn't load».

Android developers: gli ANR · Soglie di Android vitals

Riprodurlo in 30 minuti

  1. Mettiti nello stato del revisore. Un emulatore azzerato o un dispositivo di scorta: nessun account collegato, nessuna sessione in cache, niente VPN, nessuna riga in /etc/hosts, dati mobili al posto del wifi dell'ufficio. Installa l'artefatto che ha Google: scarica il .aab dal canale di test interno invece di compilare in locale. Solo questo passaggio trova la maggior parte dei casi.
  2. Apri il rapporto pre-lancio (Test e rilascio → Rapporto pre-lancio). Prima la scheda Screenshot: il crawler ha superato il tuo login? Poi Stabilità per lo stack trace e Prestazioni per il tempo di avvio.
  3. Lancia adb logcat durante un avvio a freddo, filtrato sul tuo processo: adb logcat --pid=$(adb shell pidof -s com.your.package). Cerca la richiesta che non torna mai. Quello è il tuo splash bloccato.
  4. Controlla Crashlytics e Play Console → Qualità → Android vitals → Arresti anomali e ANR, filtrati sul codice di versione che hai inviato. Se sono entrambi vuoti, il tuo problema non è mai stato un crash: torna alla lista sull'ambiente del revisore qui sopra.
  5. Ripercorri la tua scheda dello store. Apri ogni screenshot, leggi ogni frase sulle funzioni e fai esattamente quello nell'app, sul dispositivo pulito, nell'ordine.

La tua scheda dello store è il copione del test

I revisori non indovinano che cosa dovrebbe fare la tua app. Leggono la tua scheda e i tuoi screenshot, e poi verificano. Il tuo testo di marketing diventa così la specifica su cui vieni giudicato. Lo screenshot di una funzione che esce il mese prossimo è oggi una funzione rotta. Lo sono anche un riquadro «Prossimamente», una riga di Impostazioni che non apre nulla e un link di assistenza che punta a un 404. Togli lo screenshot o pubblica la funzione.

Ripresentare o fare ricorso?

Ripresenta se hai trovato una causa concreta e l'hai risolta: nuovo codice di versione, Contenuti dell'app aggiornati, Invia per la revisione. Fai ricorso solo quando sei sicuro che non ci sia nulla di rotto e puoi dimostrarlo: hai un ricorso per ogni provvedimento, e la risposta di solito arriva in circa 2 giorni lavorativi.

Consiglio senza giri di parole: la maggior parte dei thread «nella mia app non c'è niente di rotto!!!» sulla community Play finisce con lo sviluppatore che scopre un muro di login o un backend addormentato. Fai prima il giro da 30 minuti. Se fai ricorso e hai torto, hai speso il tuo unico ricorso e una settimana di fatturato.

In ogni caso, di' che cosa è cambiato. I revisori di Google lavorano sulla stessa unica riga che hai tu. Incolla questo nel modulo di ricorso, o nel campo istruzioni dei dettagli di accesso quando ripresenti:

brokenFunctionality.template

La versione Apple dello stesso rifiuto

Apple lo chiama Guideline 2.1 — Performance — App Completeness, ed è il suo motivo di rifiuto più citato. Stesse cause di fondo, console diversa: l'account demo va in App Store Connect → la tua app → Informazioni per la revisione, con l'interruttore «Accesso richiesto» attivo, più il campo Note per tutto ciò che uno sconosciuto non potrebbe indovinare. Una differenza conta molto nella pratica: Apple di solito ti dice quale schermata ha fallito e allega uno screenshot. Google ti dà una riga. È questa asimmetria che ha reso necessaria la tabella di decodifica qui sopra.

I motivi di rifiuto più comuni sull'App Store

Che cosa possiamo controllare per te — e che cosa no

Carica il .aab o l'.apk che stai per inviare e leggiamo il suo manifest. Dei 24 controlli Android dello strumento, 10 partono in automatico, e quattro puntano dritti a cause di Broken Functionality:

  • usesCleartextTraffic — un URL di base http:// che funziona sulla tua macchina e viene bloccato in silenzio in una build di release da Android 9 in poi.
  • android:debuggable — una build di debug pubblicata per sbaglio, che da sola vale comunque un rifiuto immediato.
  • Activity MAIN/LAUNCHER — nessun punto di ingresso avviabile è, letteralmente, «app doesn't load».
  • targetSdkVersion e minSdkVersion — l'incoerenza dietro «app doesn't install» su un dispositivo di revisione.

Gli altri 14 sono le domande a cui nessun parser può rispondere al posto tuo, e tre di essi sono esattamente questa policy: ogni funzione è operativa, senza segnaposto né link rotti; hai testato su dispositivi reali e guardato Android vitals; l'app fa qualcosa di reale oltre a incapsulare un sito.

Che cosa non possiamo fare, senza giri di parole: non eseguiamo la tua app. Non possiamo dirti che il tuo backend dorme, che il tuo account demo è scaduto martedì scorso o che la tua chiave Maps è legata allo SHA-1 sbagliato. Nessuno strumento che analizza un binario può farlo. È per questo che esiste il giro da 30 minuti.

Domande frequenti

Che cosa significa «Your app contains content that isn't compliant with the Broken Functionality policy»?

Significa che il revisore di Google ha aperto la tua app ed è andata in crash, si è bloccata o non è mai diventata utilizzabile. È un verdetto sul comportamento, non una revisione del codice. La riga breve che segue — per esempio «App installs, but doesn't load» — è l'unica diagnosi che avrai: parti da lì.

La mia app funziona perfettamente. Perché Google dice che è rotta?

Perché il revisore non è né sul tuo dispositivo né sulla tua rete. Una schermata di login senza credenziali di prova, un'API con allowlist sull'IP del tuo ufficio, un URL di staging nella build di release o un backend addormentato producono tutti un'app che fallisce da lui e funziona da te. Niente di tutto ciò compare nei report di crash.

Devo caricare un nuovo .aab per risolvere un rifiuto Broken Functionality?

Non sempre. Se la causa erano dettagli di accesso mancanti o scaduti, li aggiorni in Norme e programmi → Contenuti dell'app → Dettagli di accesso e clicchi Invia per la revisione nella pagina Panoramica della pubblicazione: viene ripresentata la build esistente. Se la causa è nell'app, serve un nuovo codice di versione.

Il rapporto pre-lancio individua i problemi di Broken Functionality?

In parte. Il test Robo trova crash e ANR su dispositivi reali, ma non sa accedere tramite un login in WebView né guidare comandi disegnati in OpenGL. Se la tua app ha un login in WebView, il rapporto sembrerà pulito coprendo solo la schermata di accesso. Guarda la scheda Screenshot per vedere fin dove è arrivato davvero il crawler.

Posso fare ricorso contro un rifiuto Broken Functionality?

Sì: un ricorso per ogni provvedimento, con risposta di solito entro circa 2 giorni lavorativi. Fai ricorso solo se hai riprodotto le condizioni del revisore su un dispositivo pulito e davvero non hai trovato nulla. Altrimenti risolvi la causa, alza il codice di versione e ripresenta: è più rapido che perdere il ricorso.

Quanto ci vuole per l'approvazione dopo aver ripresentato?

Google non garantisce tempi, e variano da un giorno a un paio di settimane secondo l'account e lo storico delle violazioni. Considera la ripresentazione come l'ultima: un secondo rifiuto Broken Functionality sulla stessa app costa molto più tempo di quanto sarebbe costato il giro diagnostico da 30 minuti.

Fonti

Controlla la tua build prima di inviarla

Fai passare il tuo .ipa o .apk attraverso App Review Checker e individua questi problemi in pochi secondi.

Controlla un'app