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 Google | Co zobaczył recenzent | Najbardziej prawdopodobna przyczyna | Zrób to przed ponownym wysłaniem |
|---|---|---|---|
App doesn't install | Artefakt 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 load | Uruchomił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 crashes | Awaria 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 responsive | Dotknię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 responsive | Konkretne 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. |
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 Functionality | Limited 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 źle | Twoja aplikacja nie zrobiła tego, co obiecuje. | Twoja aplikacja zrobiła dokładnie to, co obiecuje. I to jest problem. |
| Typowy wyzwalacz | Zawieszony splash, awaria przy pierwszym uruchomieniu, martwy przycisk, nieosiągalny backend. | Strona w WebView, jeden ekran tekstu, opakowanie bez natywnej wartości. |
| Rozwiązanie | Sprawić, by istniejący przepływ działał na czystym urządzeniu. | Zbudować coś, czego karta przeglądarki nie potrafi — albo nie publikować. |
| Zły ruch | Dodawanie 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
- 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.
- 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.
- 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.
- 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.
- 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
- Google Play — Funkcjonalność, treści i wygoda użytkowania (tekst zasady Broken Functionality)
- Google Play — Wymagania dotyczące danych logowania na potrzeby weryfikacji
- Google Play — Podawanie informacji do weryfikacji aplikacji (Zawartość aplikacji → Dane logowania)
- Google Play — Wykrywanie problemów za pomocą raportu przedpremierowego
- Android developers — ANR (5-sekundowy limit obsługi zdarzeń wejścia)
- Android developers — Progi złego zachowania w Android vitals
- Google Play — Zarządzanie naruszeniami zasad i odwołaniami
- Społeczność Android Builder — „Issue found: Violation of Broken Functionality policy” (przypadek kilkusekundowej pauzy)
Sprawdź swoją kompilację przed przesłaniem
Przepuść plik .ipa lub .apk przez App Review Checker i wychwyć te problemy w kilka sekund.
Sprawdź aplikację