Guideline 2.5.4: Apple odrzuca tryb działania w tle
Autor: Mehdi Azizi
Opublikowano , 9 min
Apple odrzuca tryb działania w tle bez funkcji, która go używa. Usuń klucz albo pokaż recenzentowi dźwięk, lokalizację lub połączenie.
Guideline 2.5.4 ogranicza tryby działania w tle do ich przewidzianego zastosowania: dźwięk, lokalizacja, połączenia VoIP, dokończenie zadania, lokalne powiadomienia. Odrzucenie przychodzi, gdy twój Info.plist deklaruje jeden z tych trybów, a recenzent nie znajduje żadnej funkcji, która go potrzebuje. Usuń klucz, jeśli nic go nie używa, a w przeciwnym razie pokaż recenzentowi tę funkcję w trzydzieści sekund.
Publikuję własne aplikacje iOS z Expo. Solys, mój budzik z minigrami, deklaruje tryb audio: usunąłem go, a potem przywróciłem z innego powodu. Ten poradnik opiera się na tekście Apple, na odrzuceniach opublikowanych przez innych deweloperów i na moich projektach. Przegląd wszystkich powodów znajdziesz w artykule dlaczego Apple odrzuca aplikację.
Co mówi guideline 2.5.4?
Reguła mieści się w jednym zdaniu, w sekcji 2 „Performance”, część 2.5 „Software Requirements”, w App Review Guidelines: „Multitasking apps may only use background services for their intended purposes: VoIP, audio playback, location, task completion, local notifications, etc.”
Po ludzku: usługa działająca w tle służy tylko do tego, do czego została stworzona. Stąd tytuł „Guideline 2.5.4 - Performance - Software Requirements”.
Domyślnie aplikacja przeniesiona w tło zostaje wstrzymana. Żeby dalej działać, deklaruje jeden lub kilka trybów w kluczu UIBackgroundModes swojego Info.plist. Dokumentacja Apple o trybach działania w tle prosi, żeby używać ich oszczędnie, ze względu na baterię, i wybierać inne rozwiązanie, jeśli istnieje. Każdy zadeklarowany tryb to obietnica, którą recenzent może sprawdzić.
Tryby działania w tle i ich przewidziane zastosowanie
| Tryb | Klucz | Przewidziane zastosowanie |
|---|---|---|
| Audio, AirPlay, PiP | audio | Słyszalny dźwięk w tle |
| Lokalizacja | location | Ciągła lokalizacja |
| Voice over IP | voip | Połączenia z CallKit |
| Pobieranie | fetch | Regularne treści z sieci |
| Przetwarzanie | processing | Zaplanowane zadania |
| Zdalne powiadomienia | remote-notification | Push z nową treścią |
Ta tabela streszcza stronę Apple. W odrzuceniach publikowanych na forach najczęściej pojawiają się audio, location i voip.
Co znaczy komunikat odrzucenia 2.5.4?
Komunikat wskazuje konkretny tryb. Dwa przykłady opublikowane przez deweloperów na forach Apple:
- Audio: „Your app still declares support for audio in the UIBackgroundModes key in your Info.plist but did not include features that require persistent audio.” Dalej Apple wyjaśnia, że klucz
audiojest dla aplikacji, które odtwarzają słyszalną treść w tle, jak odtwarzacz muzyki. Proponuje dwa wyjścia: dodać taką treść albo usunąć klucz (wątek na forum). - Lokalizacja: w wątku z grudnia 2024 Apple nie znalazło żadnej funkcji poza śledzeniem pracowników, która wymagałaby stałej lokalizacji, i napisało, że samo to zastosowanie nie jest odpowiednie.
Moja interpretacja: recenzent nie czyta twojego kodu, tylko szuka funkcji. Musi móc ją uruchomić, przenieść aplikację w tło i zobaczyć, że dalej działa.
Zdarza się też odwrotna sytuacja. W wątku z maja 2026 aplikacja do czytania na głos, która naprawdę używała trybu audio, została odrzucona kilka razy: recenzent nie potrafił uruchomić dźwięku. Inny deweloper pisze tam, że jego zdaniem dołączone wideo odblokowało jego przypadek. To relacja, nie reguła Apple.
Skąd bierze się klucz, skoro go nie dodałeś?
W Expo to pluginy konfiguracyjne wypełniają Info.plist podczas prebuild. Tryb działania w tle może więc trafić do twojego pliku binarnego, choć wcale o tym nie zdecydowałeś.
Plugin expo-audio z ustawieniami domyślnymi
Dokumentacja expo-audio mówi wprost: opcja enableBackgroundPlayback ma domyślnie wartość true i na iOS dodaje tryb audio. Wystarczy więc zadeklarować plugin w krótkiej formie, "expo-audio", żeby zadeklarować tryb.
Właśnie to znalazłem, przeglądając TradaZen przed pierwszym zgłoszeniem: krótkie dźwięki interfejsu na pierwszym planie, ale plugin zadeklarowany w krótkiej formie. Poprawka mieści się w app.json:
{
"expo": {
"plugins": [["expo-audio", { "enableBackgroundPlayback": false }]]
}
}
Inne pakiety dodają tryb na swój sposób. Opcja isIosBackgroundLocationEnabled w expo-location dodaje location tylko wtedy, gdy ją włączysz. Z kolei expo-background-task dodaje processing podczas prebuild, gdy tylko jest zainstalowany.
Folder ios/, który trzyma stary klucz
Druga pułapka, przerobiona na Solys w lipcu 2026. Usunąłem audio z app.json, ale klucz został w ios/Solys/Info.plist, wygenerowanym wcześniej. Prebuild bez --clean modyfikuje ten projekt zamiast tworzyć go od nowa, a plugin dodaje klucz, nigdy go nie usuwając. Lokalny build by go zawierał. Build EAS w chmurze zaczyna od świeżego prebuild, gdy ios/ jest ignorowany przez git, i tak było u mnie.
Przed każdym buildem sprawdzam, co naprawdę zostanie wysłane:
npx expo config --type introspect --json | grep -o '"UIBackgroundModes":\[[^]]*\]'
npx expo prebuild --clean --platform ios
Pierwsza komenda wypisuje tryby, które prebuild zapisze w Info.plist. Druga tworzy od nowa projekt natywny do lokalnego buildu, usuwając folder ios/. Na Solys pierwsza pokazuje "UIBackgroundModes":["audio"], na TradaZen nic: oba wyniki są zamierzone.
Dodanie lub usunięcie trybu zmienia Info.plist, a więc plik binarny: potrzebny jest nowy build, aktualizacja zdalna nie wystarczy. Dokumentacja EAS Update zalicza takie zmiany do tych, które wymagają nowego pliku binarnego, tak jak przy ITMS-90683.
Solys: zadeklarowany tryb audio, z prawdziwym powodem
Solys to budzik, ale tryb audio nie służy do dzwonienia alarmu: dzwonek idzie przez AlarmKit, usługę alarmów Apple dostępną od iOS 26 (dokumentacja AlarmKit). Dzwoni system, nawet w trybie cichym, a nie aplikacja.
Historia klucza, bo tok rozumowania liczy się bardziej niż sama linijka:
- Pod koniec lipca 2026 go usuwam. Nic nie odtwarzało dźwięku w tle: efekty dźwiękowe minigier działają na pierwszym planie, a alarm nie zależy od aplikacji.
- Dwa dni później go przywracam, razem z nasłuchem nocy. Ta opcja nagrywa mikrofonem dźwięki z twojej nocy i analizuje je na iPhonie. Nagrywanie musi trwać przy zablokowanym ekranie, a dokumentacja expo-audio podaje, że opcja nagrywania w tle również dodaje tryb
audio.
Uzasadnienie zmieniło charakter: tryb służy do nagrywania, nie do odtwarzania. Trzy zabezpieczenia, widoczne w aplikacji:
- nasłuch to opcja domyślnie wyłączona, którą włącza się w ustawieniach albo w wieczornym rytuale;
- ma własny ekran zgody, czego wymaga reguła 2.5.14 przy każdym nagrywaniu, i nic nie opuszcza telefonu;
- mikrofon wyłącza się dziesięć minut przed alarmem, żeby nasłuch i dzwonek nigdy sobie nie przeszkadzały.
Nie mogę zagwarantować, że recenzent zawsze zaakceptuje tę deklarację. Potrafię za to powiedzieć, do czego służy każdy element i gdzie go zobaczyć.
Budziki, które nie pozwalały aplikacji zasnąć
Przed AlarmKit zewnętrzny budzik nie mógł dzwonić jak alarm Apple. Niektóre biblioteki trzymały więc aplikację w stanie aktywnym: dokumentacja pakietu Flutter alarm2 opisuje cichy odtwarzacz audio, który działa aż do alarmu. Tyle że niemy dźwięk nic nie odtwarza słyszalnie. Od iOS 26 AlarmKit sprawia, że to obejście jest niepotrzebne.
Zostawić czy usunąć tryb: tabela decyzji
| Twoja sytuacja | Co zrobić |
|---|---|
| Krótkie dźwięki na 1. planie | Usuń audio |
| Muzyka lub audiobook | Zostaw, pokaż go |
| Długie nagrywanie | Zostaw + zgoda |
| Budzik lub minutnik | AlarmKit (iOS 26) |
| Lokalizacja od czasu do czasu | Znaczące zmiany lokalizacji |
| Synchronizacja bez pośpiechu | fetch lub processing |
| Połączenia audio lub wideo | voip z CallKit |
Przy lokalizacji strona Apple podaje usługę znaczących zmian lokalizacji jako alternatywę dla trybu location.
Pozostałe punkty 2.5: 2.5.1 i 2.5.2
2.5.1: publiczne API i frameworki zgodnie z przeznaczeniem
„Apps may only use public APIs and must run on the currently shipping OS.” Aplikacja korzysta tylko z publicznych API, działa na aktualnej wersji systemu i porzuca to, co przestarzałe. Tak jak przy 2.5.4, każdy framework służy do swojego przewidzianego zastosowania, wspomnianego w opisie: HealthKit do zdrowia, HomeKit do inteligentnego domu. Jeśli jakaś biblioteka wywołuje prywatne API, odrzucenie dostaje twoja aplikacja.
2.5.2: żadnego pobieranego kodu, który zmienia aplikację
Aplikacja pozostaje samodzielna w swoim pakiecie. Nie może „download, install, or execute code which introduces or changes features or functionality of the app”. Ograniczony wyjątek mają tylko aplikacje edukacyjne uczące programowania, z kodem w pełni widocznym i edytowalnym przez użytkownika.
W Expo dotyczy to EAS Update, którego dokumentacja przypomina, że aktualizacje muszą przestrzegać zasad App Store. Używaj aktualizacji zdalnych do poprawek, nigdy do dostarczania funkcji, której recenzent nie widział. Poprawka związana z recenzją wymaga nowego buildu, jak tłumaczę w poradniku o guideline 2.1.
Jak odpowiedzieć na odrzucenie 2.5.4?
Rozmowa toczy się w sekcji App Review twojej aplikacji, gdzie odpowiadasz na wiadomość App Review. Dwa przypadki:
- Tryb do niczego nie służy: usuń go, zrób nowy build, sprawdź introspekcję i odpowiedz w dwóch zdaniach.
- Tryb obsługuje prawdziwą funkcję: odpowiedz, podając dokładną ścieżkę i krótkie wideo, a potem powtarzaj ten tekst w notatkach do recenzji przy każdej wersji.
Szablon, którego bym użył, do dopasowania (usuń zdanie o alarmie, jeśli twoja aplikacja go nie ma):
Hello,
The "audio" background mode is used only by [feature], an
optional feature that [records / plays] audio while the
device is locked. It is off by default.
How to test:
1. Open [screen] and turn on [feature].
2. Accept the microphone permission if asked.
3. Tap [button], then lock the device.
[What the reviewer will hear or see.]
Our alarm does not use this mode: it is scheduled with
AlarmKit and rings through the system.
Attached: a short screen recording of these steps.
Best regards,
Checklista 2.5.4 przed zgłoszeniem
- Introspekcja Expo pokazuje tylko zamierzone tryby, a ty potrafisz nazwać funkcję każdego z nich.
- Żaden plugin nie jest zadeklarowany w krótkiej formie, jeśli domyślnie dodaje tryb, jak expo-audio.
- Twój lokalny folder
ios/nie trzyma żadnego starego klucza albo budujesz z czystego prebuild. - Funkcja uruchamia się szybko, bez ukrytych ustawień, a notatki do recenzji mówią, który tryb do czego służy i jak go przetestować.
- Każde nagrywanie wymaga wyraźnej zgody i pokazuje widoczny wskaźnik. Zasady dotyczące próśb o uprawnienia znajdziesz w poradniku o guideline 5.1.1.
- W budziku dzwonek idzie przez AlarmKit, a nie przez dźwięk odtwarzany z aplikacji.
Sprawdź swoje zgłoszenie przed wysłaniem
Review Kit zawiera moją checklistę przed wysłaniem, szablony notatek dla testera i skille Claude Code, które przeglądają twój projekt. Jeśli chcesz, żeby spojrzał na to człowiek, zarezerwuj godzinę ze mną: razem przeczytamy wiadomość od Apple i twój Info.plist, na wideorozmowie. Cały proces opisuję na stronie aplikacja odrzucona przez Apple.
Przygotowujesz swoje pierwsze wydanie? Zrób darmową diagnozę: ułoży kroki we właściwej kolejności i wyśle ci moją checklistę przeciw odrzuceniom Apple.
Nikt nie zagwarantuje, że Apple zaakceptuje twoją aplikację. Dobrze uzasadniony tryb działania w tle obronisz za to w trzydzieści sekund.
Najczęściej zadawane pytania
Co znaczy „Guideline 2.5.4 - Performance - Software Requirements”?
To tytuł odrzucenia, gdy Apple uzna, że tryb działania w tle z twojego Info.plist nie służy przewidzianemu zastosowaniu. Komunikat wskazuje tryb i proponuje pokazać funkcję, która go używa, albo usunąć klucz.
Czy po odrzuceniu 2.5.4 potrzebny jest nowy build?
Jeśli usuwasz lub zmieniasz tryb, tak: klucz jest w Info.plist, a więc w pliku binarnym. Jeśli tryb jest uzasadniony, może wystarczyć odpowiedź z dokładną ścieżką i wideo.
Czy można zostawić tryb audio dla kilku dźwięków interfejsu?
Nie. Krótkie dźwięki odtwarzane na pierwszym planie go nie potrzebują. W Expo ustaw enableBackgroundPlayback na false w pluginie expo-audio.
Czy budzik potrzebuje trybu audio?
Nie do dzwonienia, jeśli opiera się na AlarmKit, dostępnym od iOS 26: alarm odtwarza system. W Solys tryb audio służy do nasłuchu nocy, który nagrywa przy zablokowanym ekranie.
Dlaczego Apple powołuje się na 2.5.4, skoro niczego nie zadeklarowałem?
Być może zrobił to za ciebie plugin: expo-audio domyślnie dodaje tryb audio, a stary folder ios/ może trzymać klucz usunięty z twojej konfiguracji. Sprawdź to komendą npx expo config --type introspect.

