Zasada Broken Functionality: dlaczego Google odrzuca aplikację, która na Twoim telefonie działa bez zarzutu

Google wysyła Ci jedną linijkę: Twoja aplikacja narusza zasadę Broken Functionality. Żadnego stosu wywołań, żadnego zrzutu ekranu, żadnych kroków do odtworzenia. Instalujesz tę samą kompilację produkcyjną na własnym telefonie i wszystko działa. Co więc zmienić przed ponownym wysłaniem? Zwykle nic w kodzie — recenzent nigdy nie doszedł tak daleko.

Ostatnia aktualizacja: lipiec 2026

Co naprawdę mówi zasada Broken Functionality

Broken Functionality to fragment zasad Google Play „Funkcjonalność, treści i wygoda użytkowania”. Reguła mieści się w jednym zdaniu: niedozwolone są aplikacje, które ulegają awarii, wymuszają zamknięcie, zawieszają się lub działają nieprawidłowo. Google podaje dokładnie trzy przykłady — aplikacje, które się nie instalują, takie, które się instalują, ale nie wczytują, oraz takie, które się wczytują, ale nie reagują.

Przeczytaj to jeszcze raz i zauważ, czego tam NIE ma. Ani słowa o Twojej architekturze, pokryciu testami, frameworku czy jakości kodu. To zasada dotycząca zachowania. Opisuje, co wydarzyło się na jednym urządzeniu, w jednej sesji, w jednej sieci, podczas weryfikacji trwającej kilka minut. Ta różnica jest kluczowa: tego nie naprawisz lepszym kodem, tylko sprawiając, że aplikacja przetrwa pierwsze pięć minut z obcą osobą.

Zasady Google Play: funkcjonalność, treści i wygoda użytkowania

Znajdź swoją dokładną linijkę odrzucenia

Treść maila to szablon wysyłany tysiącom deweloperów. Linijka z problemem pod spodem już nie — to najbliższa zgłoszeniu błędu rzecz, jaką dostaniesz. Poszukaj swojej w pierwszej kolumnie.

Linijka, którą dał Ci GoogleCo zobaczył recenzentNajbardziej prawdopodobna przyczynaZrób to przed ponownym wysłaniem
App doesn't installArtefakt nigdy nie stał się działającą instalacją na urządzeniu weryfikacyjnym.Błąd na etapie instalacji, a nie w czasie działania: minSdkVersion wyższy niż urządzenie testowe, brakujący split ABI lub gęstości albo niezgodny podpis.Zainstaluj artefakt, który Google faktycznie ma — pobierz go z wewnętrznego kanału testowego, nie z Android Studio — na urządzeniu zgodnym z deklarowanym minSdk.
App installs, but doesn't loadUruchomiła się, a potem stanęła na ekranie, który nigdy nie stał się użyteczny.Splash czeka na coś, czego sesja recenzenta nie ma: token uwierzytelniający, pierwsze wywołanie API, pobranie zdalnej konfiguracji, token FCM.Uruchom aplikację na zimno w trybie samolotowym, bez sesji w pamięci podręcznej. Jeśli zawiśnie zamiast pokazać błąd, właśnie odtworzyłeś swoje odrzucenie.
App loads, but crashesAwaria w pierwszych minutach sesji.Ścieżka pierwszego uruchomienia, w którą lokalnie nigdy nie trafiasz. Twoje urządzenie ma dane, urządzenie recenzenta nie: pusta lista albo pusty profil kładzie ekran.Raport przedpremierowy → karta Stabilność. Stos wywołań już tam jest, z prawdziwego urządzenia, po stronie Google.
App loads, but is not responsiveDotknięcia nic nie robiły albo interfejs się zawiesił.Praca na głównym wątku przy starcie: synchroniczne wywołanie sieciowe, duże parsowanie JSON, migracja bazy danych.Przenieś to z głównego wątku. Android zgłasza ANR po 5 sekundach bez obsłużonego zdarzenia wejścia — recenzent rezygnuje dużo wcześniej niż system.
App contains icon(s) or button(s) that are not responsiveKonkretne elementy interfejsu nie reagowały na dotknięcie.Martwe elementy: kafelek „Wkrótce”, przycisk za wyłączoną flagą funkcji, pozycja menu podpięta donikąd, link zwracający 404.Na czystej instalacji bez konta dotknij każdego elementu w aplikacji. Wszystko, co nie reaguje, zostaje podpięte albo usunięte — trzeciej opcji nie ma.
Linijki problemu w postaci, w jakiej pojawiają się pod werdyktem Broken Functionality w Play Console. Pierwsza, trzecia i czwarta to opublikowane przykłady samego Google; pozostałe to powtarzające się komunikaty zgłaszane na forum deweloperów Play.

Broken Functionality to nie Limited Functionality

To dwa różne fragmenty tej samej strony zasad, a ich rozwiązania są przeciwne. Broken Functionality znaczy, że Twoja aplikacja zawodzi. Limited Functionality and Content znaczy, że Twoja aplikacja działa bez zarzutu i mimo to nie jest warta instalacji: WebView opakowujący Twoją stronę, jeden statyczny ekran, przeglądarka jednego PDF-a. Pomylenie ich wysyła Cię do budowania funkcji, gdy trzeba naprawić zawieszenie.

Broken FunctionalityLimited Functionality and Content
Reguła„Nie zezwalamy na aplikacje, które ulegają awarii, wymuszają zamknięcie, zawieszają się lub działają nieprawidłowo”.„Nie zezwalamy na aplikacje o ograniczonej funkcjonalności i treści”.
Co poszło źleTwoja aplikacja nie zrobiła tego, co obiecuje.Twoja aplikacja zrobiła dokładnie to, co obiecuje. I to jest problem.
Typowy wyzwalaczZawieszony splash, awaria przy pierwszym uruchomieniu, martwy przycisk, nieosiągalny backend.Strona w WebView, jeden ekran tekstu, opakowanie bez natywnej wartości.
RozwiązanieSprawić, by istniejący przepływ działał na czystym urządzeniu.Zbudować coś, czego karta przeglądarki nie potrafi — albo nie publikować.
Zły ruchDodawanie funkcji.Naprawianie błędów.

Nasz własny przewodnik po odrzuceniach w Google Play wrzucał obie rzeczy do jednego punktu. To było błędne i w dużej mierze dlatego powstała ta strona. Why Google Play rejects apps

Twoja aplikacja działa. Recenzent i tak nie wszedł do środka.

To tutaj naprawdę mieszka większość takich odrzuceń, i prawie nikt o tym nie pisze. Twoja kompilacja jest w porządku. Twoja maszyna to nie maszyna recenzenta. Przejdź tę listę, zanim ruszysz choć jedną linijkę kodu.

  • Ekran logowania bez działających danych testowych. Recenzent otwiera aplikację, widzi formularz, nie ma czego wpisać i zamyka. Z zewnątrz jest to nie do odróżnienia od aplikacji, która „instaluje się, ale nie wczytuje”.
  • Kod jednorazowy SMS-em lub mailem. Podałeś konto demonstracyjne, ale kod idzie na telefon leżący na Twoim biurku. Google mówi wprost: jeśli aplikacja zwykle wymaga weryfikacji dwuetapowej albo hasła jednorazowego, musisz podać dane wielokrotnego użytku, które to omijają.
  • Backend z blokadą geograficzną albo listą dozwolonych adresów IP. Weryfikacja nie odbywa się z Twojego biura. Jeśli API dopuszcza tylko CIDR biura albo aplikacja blokuje kraje, w których nie sprzedajesz, recenzent ląduje na Twoim ekranie błędu. Sformułowanie Google: dane logowania muszą być ważne „niezależnie od lokalizacji użytkownika”, a blokada geograficzna wymaga danych nadrzędnych.
  • Adres bazowy środowiska testowego albo localhost w kompilacji produkcyjnej. Brzmi zbyt głupio, żeby się zdarzyć, i zdarza się bez przerwy: źle skonfigurowany wariant kompilacji, niepodmieniony .env, adres debugowy, który przetrwał scalanie. Twój laptop rozwiązuje ten host przez firmowy VPN albo wpis w /etc/hosts. Urządzenie weryfikacyjne nie.
  • Backend, który śpi. Skalowanie do zera i darmowe hostingi startują na zimno przez 5 do 30 sekund. Twoje pierwsze poranne żądanie jest wolne i przestałeś to zauważać. Każde żądanie recenzenta jest pierwszym porannym żądaniem.
  • Flaga funkcji, która została wyłączona. Opublikowałeś ze zdalną flagą wyłączoną, planując włączyć ją po zatwierdzeniu. Recenzent testuje to, co ma przed sobą, znajduje pusty ekran i odrzuca.
  • Wygasły klucz API albo klucz Maps/Firebase ograniczony do certyfikatu podpisywania debugowego. Play App Signing podpisuje wydanie innym SHA-1 niż Twój klucz debugowy. Od tego momentu każdy kafelek i każde wywołanie zawodzą — wyłącznie w produkcji, nigdy na Twojej maszynie.

Każdy z tych przypadków daje aplikację nieskazitelną na Twoim biurku i zepsutą w weryfikacji. I żaden nigdy nie pojawi się w raportach awarii, bo nic się nie zawiesiło.

Jak przekazać recenzentom Google Play konto testowe?

W Play Console przejdź do Zasady i programy → Zawartość aplikacji → Dane logowania → Rozpocznij (albo Zarządzaj), kliknij „+ Dodaj nowe instrukcje” i uzupełnij dane dostępowe. Możesz dodać do pięciu zestawów. Następnie otwórz stronę Przegląd publikowania i kliknij „Prześlij do sprawdzenia”. Jeśli zmieniłeś tylko dane logowania, nie musisz wgrywać nowego pliku .aab.

Wymagania Google wobec tych danych, ich własnymi słowami:

  • Dostępne przez cały czas, wielokrotnego użytku i ważne niezależnie od lokalizacji użytkownika.
  • Utrzymywane przez cały czas i bez błędów.
  • Podane po angielsku.
  • Jeśli logowanie nie jest numeryczne ani alfanumeryczne — kod QR albo kod kreskowy — wygeneruj statyczny adres URL i wgraj go do Play Console.
  • Jeśli użytkownik sam ustawia PIN albo hasło, by dotrzeć do treści w aplikacji, podaj jasne instrukcje.
  • Jeśli opierasz się na logowaniu przez Google, Facebooka lub podobne, podaj wszystkie informacje o koncie oraz szczegółowe instrukcje.

Awaria, przed którą nikt nie ostrzega: konto demonstracyjne działa, a potem przestaje. Kończy się 30-dniowy okres próbny. Limiter zapytań blokuje je przy trzeciej weryfikacji. Ktoś z zespołu resetuje bazę testową w piątek. „Dostępne przez cały czas” pracuje w tym zdaniu bardzo ciężko — traktuj konto weryfikacyjne jak dane produkcyjne.

Jedno konto też nie wystarczy. Recenzent musi dotrzeć do każdej funkcji, którą reklamuje Twoja wizytówka w sklepie. Jeśli zakładka premium wymaga płatnego planu, konto demonstracyjne musi mieć to uprawnienie już przyznane.

Google Play: wymagania dotyczące danych logowania na potrzeby weryfikacji

Raport przedpremierowy kłamie, jeśli masz ekran logowania

Test Robo potrafi wpisać Twoje dane testowe wyłącznie w standardowe widżety Androida i w Compose. Nie zaloguje się przez proces uwierzytelniania oparty na WebView i nie obsłuży elementów, które aplikacja rysuje w OpenGL. Aplikacja w React Native albo Flutterze z logowaniem w WebView dostaje więc czysty, bezawaryjny raport przedpremierowy obejmujący dokładnie jeden ekran: ekran logowania. Raport na zielono, aplikacja odrzucona.

Dodaj jednorazowe konto testowe w Testowanie i publikowanie → Testy → Raport przedpremierowy → Ustawienia. Nigdy prawdziwego konta. Potem przeczytaj kartę Zrzuty ekranu przed kartą Stabilność — jeśli wszystkie 20 zrzutów to Twój ekran logowania, znalazłeś swoje odrzucenie i nigdy nie była to awaria.

Google Play: używanie raportu przedpremierowego do wykrywania problemów

Od kiedy wolno liczy się jako zawieszone?

Android zgłasza ANR, gdy aplikacja nie odpowie na zdarzenie wejścia w ciągu 5 sekund. Ten sam limit 5 sekund dotyczy odbiornika komunikatów na pierwszym planie oraz wywołania startForeground() po startForegroundService(). To są limity systemu. Cierpliwość recenzenta jest znacznie krótsza, a od nudy nie ma odwołania.

Dla kontekstu — liczby, które sam Google uznaje za nieakceptowalne: progi złego zachowania w Android vitals to 1,09 % odsetka awarii odczuwanych przez użytkownika i 0,47 % odsetka ANR odczuwanych przez użytkownika w skali wszystkich urządzeń albo 8 % na jednym modelu. Ich przekroczenie oznacza ostrzeżenie przy wizytówce w sklepie — ale możesz być głęboko poniżej i i tak zostać odrzuconym, bo weryfikacja to jedna sesja, a nie rozkład.

Tak to wygląda w praktyce. Deweloper wkleił dokładnie ciąg „App installs, but doesn't load” na forum Android Builder, twierdząc, że nic nie jest zepsute; dopytany o szczegóły wspomniał, że „czasem ekran 1 zatrzymuje się na kilka sekund”. Żadnej awarii. Żadnego ANR. Poniżej systemowego limitu 5 sekund. Odrzucone mimo to.

Co prowadzi nas do najskuteczniejszego sposobu na zapracowanie na to odrzucenie: ekran powitalny, który zasłania martwy backend. Wygląda identycznie, czy Twoje API odpowiedziało w 200 ms, czy nie odpowiedziało wcale. Daj mu limit czasu — 3 sekundy, a potem prawdziwy ekran błędu z przyciskiem Spróbuj ponownie. Aplikacja, która mówi „Nie można połączyć się z serwerem”, to działająca aplikacja mająca gorszy dzień. Aplikacja, która kręci się w nieskończoność, to „installs, but doesn't load”.

Android developers: ANR · Progi Android vitals

Odtwórz to w 30 minut

  1. Wejdź w stan recenzenta. Wyczyszczony emulator albo zapasowe urządzenie: żadnego zalogowanego konta, żadnej sesji w pamięci podręcznej, bez VPN, bez wpisu w /etc/hosts, dane mobilne zamiast biurowego wifi. Zainstaluj artefakt, który ma Google: pobierz .aab z wewnętrznego kanału testowego zamiast kompilować lokalnie. Sam ten krok znajduje większość przypadków.
  2. Otwórz raport przedpremierowy (Testowanie i publikowanie → Raport przedpremierowy). Najpierw karta Zrzuty ekranu: czy robot przeszedł Twoje logowanie? Potem Stabilność po stos wywołań i Wydajność po czas uruchamiania.
  3. Uruchom adb logcat podczas zimnego startu, z filtrem na swój proces: adb logcat --pid=$(adb shell pidof -s com.your.package). Wypatruj żądania, które nigdy nie wraca. To Twój zawieszony splash.
  4. Sprawdź Crashlytics oraz Play Console → Jakość → Android vitals → Awarie i ANR, z filtrem na wysłany kod wersji. Jeśli oba są puste, Twój problem nigdy nie był awarią — wróć do listy o środowisku recenzenta powyżej.
  5. Przejdź własną wizytówkę w sklepie. Otwórz każdy zrzut ekranu, przeczytaj każde zdanie o funkcjach i zrób dokładnie to w aplikacji, na czystym urządzeniu, po kolei.

Twoja wizytówka w sklepie jest scenariuszem testu

Recenzenci nie zgadują, co Twoja aplikacja ma robić. Czytają Twoją wizytówkę i zrzuty ekranu, a potem sprawdzają. Twój własny tekst marketingowy staje się przez to specyfikacją, z której jesteś oceniany. Zrzut funkcji, która wychodzi w przyszłym miesiącu, jest dziś funkcją zepsutą. Tak samo kafelek „Wkrótce”, pozycja w Ustawieniach, która nic nie otwiera, i link do pomocy wskazujący 404. Usuń zrzut albo wydaj funkcję.

Wysłać ponownie czy się odwołać?

Wyślij ponownie, jeśli znalazłeś konkretną przyczynę i ją usunąłeś: nowy kod wersji, zaktualizowana Zawartość aplikacji, Prześlij do sprawdzenia. Odwołuj się tylko wtedy, gdy masz pewność, że nic nie jest zepsute, i potrafisz to pokazać — przysługuje jedno odwołanie na każde działanie egzekucyjne, a odpowiedź przychodzi zwykle w około 2 dni robocze.

Bez owijania: większość wątków „w mojej aplikacji nic nie jest zepsute!!!” na forum Play kończy się tym, że deweloper znajduje ekran logowania albo śpiący backend. Zrób najpierw przebieg 30-minutowy. Jeśli się odwołasz i nie będziesz mieć racji, zużyjesz jedyne odwołanie i tydzień przychodu.

Tak czy inaczej powiedz, co się zmieniło. Recenzenci Google pracują na tej samej jednej linijce co Ty. Wklej to w formularz odwołania albo w pole instrukcji przy danych logowania, gdy wysyłasz ponownie:

brokenFunctionality.template

Odpowiednik tego odrzucenia u Apple

Apple nazywa to Guideline 2.1 — Performance — App Completeness i jest to ich najczęściej przywoływany powód odrzucenia. Te same przyczyny źródłowe, inna konsola: konto demonstracyjne wpisuje się w App Store Connect → Twoja aplikacja → Informacje do weryfikacji, z włączonym przełącznikiem „Wymagane logowanie” oraz polem Uwagi na wszystko, czego obca osoba nie odgadnie. Jedna różnica ma w praktyce duże znaczenie: Apple zwykle mówi, który ekran zawiódł, i dołącza zrzut. Google daje jedną linijkę. Ta asymetria jest powodem, dla którego powyższa tabela dekodująca musiała powstać.

Najczęstsze przyczyny odrzucenia w App Store

Co możemy sprawdzić za Ciebie — a czego nie

Wgraj plik .aab albo .apk, który zamierzasz wysłać, a my odczytamy jego manifest. Z 24 kontroli Androida w narzędziu 10 działa automatycznie, a cztery z nich wskazują wprost na przyczyny Broken Functionality:

  • usesCleartextTraffic — bazowy adres http://, który działa na Twojej maszynie i jest po cichu blokowany w kompilacji produkcyjnej od Androida 9 wzwyż.
  • android:debuggable — kompilacja debugowa opublikowana przez pomyłkę, co samo w sobie i tak oznacza natychmiastowe odrzucenie.
  • Aktywność MAIN/LAUNCHER — brak uruchamialnego punktu wejścia to dosłownie „app doesn't load”.
  • targetSdkVersion i minSdkVersion — niezgodność stojąca za „app doesn't install” na urządzeniu weryfikacyjnym.

Pozostałych 14 to pytania, na które żaden parser nie odpowie za Ciebie, a trzy z nich to dokładnie ta zasada: czy każda funkcja działa, bez atrap i martwych linków; czy testowałeś na prawdziwych urządzeniach i sprawdziłeś Android vitals; czy aplikacja robi coś realnego poza opakowaniem strony internetowej.

Czego wprost nie zrobimy: nie uruchamiamy Twojej aplikacji. Nie powiemy Ci, że backend śpi, że konto demonstracyjne wygasło w zeszły wtorek albo że klucz Maps jest przypisany do złego SHA-1. Żadne narzędzie analizujące plik binarny tego nie potrafi. Od tego jest przebieg 30-minutowy.

Najczęstsze pytania

Co znaczy „Your app contains content that isn't compliant with the Broken Functionality policy”?

Znaczy, że recenzent Google otworzył Twoją aplikację, a ta uległa awarii, zawiesiła się albo nigdy nie stała się użyteczna. To werdykt o zachowaniu, nie przegląd kodu. Krótka linijka pod spodem — na przykład „App installs, but doesn't load” — jest jedyną diagnozą, jaką dostaniesz, więc zacznij od niej.

Moja aplikacja działa bez zarzutu. Dlaczego Google mówi, że jest zepsuta?

Bo recenzent nie jest ani na Twoim urządzeniu, ani w Twojej sieci. Ekran logowania bez danych testowych, API ograniczone do adresu IP Twojego biura, adres środowiska testowego w kompilacji produkcyjnej albo śpiący backend — każde z tych rozwiązań daje aplikację, która u niego zawodzi, a u Ciebie działa. Nic z tego nie trafia do raportów awarii.

Czy muszę wgrać nowy .aab, żeby naprawić odrzucenie Broken Functionality?

Nie zawsze. Jeśli przyczyną były brakujące albo wygasłe dane logowania, aktualizujesz je w Zasady i programy → Zawartość aplikacji → Dane logowania i klikasz Prześlij do sprawdzenia na stronie Przegląd publikowania — ponownie wysyłana jest istniejąca kompilacja. Jeśli przyczyna tkwi w aplikacji, potrzebny jest nowy kod wersji.

Czy raport przedpremierowy wykrywa problemy Broken Functionality?

Częściowo. Test Robo znajduje awarie i ANR na prawdziwych urządzeniach, ale nie zaloguje się przez logowanie w WebView i nie obsłuży elementów rysowanych w OpenGL. Jeśli Twoja aplikacja ma logowanie w WebView, raport będzie wyglądał czysto, obejmując wyłącznie ekran logowania. Sprawdź kartę Zrzuty ekranu, żeby zobaczyć, jak daleko robot naprawdę zaszedł.

Czy mogę odwołać się od odrzucenia Broken Functionality?

Tak — jedno odwołanie na każde działanie egzekucyjne, z odpowiedzią zwykle w około 2 dni robocze. Odwołuj się tylko, jeśli odtworzyłeś warunki recenzenta na czystym urządzeniu i naprawdę nic nie znalazłeś. W przeciwnym razie usuń przyczynę, podnieś kod wersji i wyślij ponownie; to szybsze niż przegranie odwołania.

Ile trwa zatwierdzenie po ponownym wysłaniu?

Google nie gwarantuje żadnego terminu, a czas waha się od dnia do kilku tygodni w zależności od konta i historii naruszeń. Zaplanuj to ponowne wysłanie jako ostatnie: drugie odrzucenie Broken Functionality tej samej aplikacji kosztuje znacznie więcej czasu niż 30-minutowy przebieg diagnostyczny.

Źródła

Sprawdź swoją kompilację przed przesłaniem

Przepuść plik .ipa lub .apk przez App Review Checker i wychwyć te problemy w kilka sekund.

Sprawdź aplikację