Guideline 2.5.4: baggrundstilstand afvist af Apple
Af Mehdi Azizi
Udgivet , 9 min.
Apple afviser efter 2.5.4 en baggrundstilstand uden funktion, der bruger den. Fjern nøglen, eller vis revieweren lyden, positionen eller opkaldet.
Guideline 2.5.4 begrænser baggrundstilstande til det, de er beregnet til: lyd, position, VoIP-opkald, afslutning af opgaver og lokale notifikationer. Afvisningen kommer, når din Info.plist erklærer en af disse tilstande, og revieweren ikke kan finde nogen funktion, der har brug for den. Fjern nøglen, hvis intet bruger den. Ellers skal du vise revieweren funktionen på tredive sekunder.
Jeg udgiver mine egne iOS-apps med Expo. Solys, mit vækkeur med minispil, erklærer audio-tilstanden: Jeg fjernede den og satte den så ind igen af en anden grund. Denne guide bygger på Apples tekst, på afvisninger, som andre udviklere har delt, og på mine egne projekter. Overblikket over afvisningsgrundene finder du i hvorfor Apple afviser en app.
Hvad siger guideline 2.5.4?
Reglen fylder én sætning i afsnit 2 »Performance«, del 2.5 »Software Requirements« i App Review Guidelines: »Multitasking apps may only use background services for their intended purposes: VoIP, audio playback, location, task completion, local notifications, etc.«
Kort sagt: en baggrundstjeneste må kun bruges til det, den findes for. Deraf overskriften »Guideline 2.5.4 - Performance - Software Requirements«.
Som standard bliver en app sat på pause, når den går i baggrunden. For at blive ved med at køre skal den erklære en eller flere tilstande i nøglen UIBackgroundModes i sin Info.plist. Apples dokumentation om baggrundstilstande beder dig bruge dem sparsomt på grund af batteriet og vælge en anden løsning, når der findes en. Hver erklæret tilstand er et løfte, som revieweren kan tjekke.
Baggrundstilstandene og deres tiltænkte brug
| Tilstand | Nøgle | Tiltænkt brug |
|---|---|---|
| Audio, AirPlay, PiP | audio | Hørbar lyd i baggrunden |
| Position | location | Løbende position |
| Voice over IP | voip | Opkald med CallKit |
| Hentning | fetch | Jævnligt netværksindhold |
| Behandling | processing | Planlagte opgaver |
| Fjernnotifikationer | remote-notification | Push af nyt indhold |
Tabellen opsummerer Apples side. I de afvisninger, der er delt på forummerne, går audio, location og voip oftest igen.
Hvad betyder afvisningsbeskeden for 2.5.4?
Beskeden nævner den tilstand, det drejer sig om. To eksempler, som udviklere har delt på Apples forummer:
- 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.« Resten forklarer, at nøglen
audioer beregnet til apps, der afspiller hørbart indhold i baggrunden, som en musikafspiller. Den giver to udveje: tilføj sådant indhold, eller fjern nøglen (tråd på forummet). - Position: I en tråd fra december 2024 fandt Apple ingen anden funktion end sporing af medarbejdere, der krævede konstant position, og skrev, at den brug alene ikke er passende.
Min læsning: revieweren læser ikke din kode, men leder efter en funktion. Vedkommende skal kunne starte den, sende appen i baggrunden og se, at den fortsætter.
Det modsatte sker også. I en tråd fra maj 2026 blev en oplæsningsapp, der rent faktisk brugte audio-tilstanden, afvist flere gange: Revieweren kunne ikke få lyden i gang. En anden udvikler skriver der, at en vedhæftet video efter hans mening løste hans sag. Det er en beretning, ikke en regel fra Apple.
Hvor kommer nøglen fra, når du ikke selv har tilføjet den?
Med Expo er det config plugins, der udfylder Info.plist ved prebuild. En baggrundstilstand kan altså havne i din binære fil, uden at du har besluttet det.
Pluginet expo-audio med standardindstillinger
Det står i dokumentationen for expo-audio: Indstillingen enableBackgroundPlayback er true som standard og tilføjer på iOS tilstanden audio. Bare det at erklære pluginet i kort form, "expo-audio", erklærer altså tilstanden.
Det fandt jeg, da jeg gennemgik TradaZen før første indsendelse: korte UI-lyde i forgrunden, men et plugin erklæret i kort form. Rettelsen er i app.json:
{
"expo": {
"plugins": [["expo-audio", { "enableBackgroundPlayback": false }]]
}
}
Andre pakker tilføjer en tilstand på deres egen måde. Indstillingen isIosBackgroundLocationEnabled i expo-location tilføjer kun location, hvis du slår den til. expo-background-task tilføjer derimod processing ved prebuild, så snart den er installeret.
ios/-mappen, der beholder den gamle nøgle
Den anden fælde oplevede jeg på Solys i juli 2026. Jeg havde fjernet audio fra app.json, men nøglen stod stadig i ios/Solys/Info.plist, som var genereret tidligere. Et prebuild uden --clean ændrer projektet i stedet for at genskabe det, og pluginet tilføjer nøglen uden nogensinde at fjerne den. Et lokalt build ville have taget den med. Et EAS-build i skyen starter fra et frisk prebuild, når ios/ er ignoreret af git, og det var tilfældet hos mig.
Før hvert build tjekker jeg, hvad der faktisk bliver sendt:
npx expo config --type introspect --json | grep -o '"UIBackgroundModes":\[[^]]*\]'
npx expo prebuild --clean --platform ios
Den første viser de tilstande, som prebuild skriver i Info.plist. Den anden genskaber det native projekt til et lokalt build og sletter mappen ios/. På Solys viser den første "UIBackgroundModes":["audio"], på TradaZen intet: Begge dele er tilsigtet.
At tilføje eller fjerne en tilstand ændrer Info.plist og dermed den binære fil: Du skal lave et nyt build, en fjernopdatering er ikke nok. Dokumentationen for EAS Update regner disse ændringer blandt dem, der kræver en ny binær fil, ligesom ved ITMS-90683.
Solys: en erklæret audio-tilstand med en reel grund
Solys er et vækkeur, men audio-tilstanden bruges ikke til at få alarmen til at ringe: Alarmen går gennem AlarmKit, Apples alarmtjeneste, der findes fra iOS 26 (dokumentation for AlarmKit). Det er systemet, der ringer, også i lydløs tilstand, ikke appen.
Nøglens historik, fordi ræsonnementet betyder mere end linjen:
- Sidst i juli 2026 fjerner jeg den. Intet afspillede lyd i baggrunden: Lydeffekterne i minispillene bliver i forgrunden, og alarmen afhænger ikke af appen.
- To dage senere sætter jeg den ind igen, sammen med natteaflytningen. Denne funktion optager lydene fra din nat med mikrofonen og analyserer dem på iPhonen. Optagelsen skal fortsætte med låst skærm, og dokumentationen for expo-audio angiver, at indstillingen til optagelse i baggrunden også tilføjer
audio-tilstanden.
Begrundelsen har skiftet karakter: Tilstanden bruges til at optage, ikke til at afspille. Tre sikkerhedsforanstaltninger, synlige i appen:
- aflytningen er en funktion, der er slået fra som standard og slås til i indstillingerne eller i aftenritualet;
- den har sin egen samtykkeskærm, som regel 2.5.14 kræver for al optagelse, og intet forlader telefonen;
- mikrofonen lukkes ti minutter før alarmen, så aflytningen og alarmen aldrig kommer i vejen for hinanden.
Jeg kan ikke garantere, at en reviewer altid vil acceptere denne erklæring. Jeg kan sige, hvad hvert element bruges til, og hvor man ser det.
Vækkeurene, der holdt appen vågen
Før AlarmKit kunne et tredjeparts vækkeur ikke ringe ligesom Apples alarm. Nogle biblioteker holdt derfor appen vågen: Dokumentationen for Flutter-pakken alarm2 beskriver en lydløs lydafspiller, der kører indtil alarmen. Men en lydløs lyd får man ikke hørt noget af. Fra iOS 26 gør AlarmKit den omvej overflødig.
Behold eller fjern tilstanden: beslutningsskemaet
| Din situation | Hvad du gør |
|---|---|
| Korte lyde i forgrunden | Fjern audio |
| Musik eller lydbog | Behold den, vis den |
| Lang optagelse | Behold + samtykke |
| Vækkeur eller timer | AlarmKit (iOS 26) |
| Position en gang imellem | Væsentlige ændringer |
| Synkronisering uden hast | fetch eller processing |
| Lyd- eller videoopkald | voip med CallKit |
For position nævner Apples side tjenesten for væsentlige positionsændringer som alternativ til location-tilstanden.
De andre punkter i 2.5: 2.5.1 og 2.5.2
2.5.1: offentlige API'er og frameworks til deres formål
»Apps may only use public APIs and must run on the currently shipping OS.« Appen bruger kun offentlige API'er, kører på den aktuelle version af systemet og udfaser det, der er forældet. Ligesom ved 2.5.4 bruges hvert framework til sit tiltænkte formål, nævnt i beskrivelsen: HealthKit til sundhed, HomeKit til smart home. Hvis et bibliotek kalder et privat API, er det din app, der bliver afvist.
2.5.2: ingen downloadet kode, der ændrer appen
Appen skal være selvstændig i sin pakke. Den må ikke »download, install, or execute code which introduces or changes features or functionality of the app«. Kun undervisningsapps, der lærer at kode, har en begrænset undtagelse, med kode der er fuldt synlig og kan redigeres af brugeren.
Med Expo handler spørgsmålet om EAS Update, hvis dokumentation minder om, at opdateringer skal overholde App Stores regler. Brug fjernopdateringer til rettelser, aldrig til at levere en funktion, som revieweren ikke har set. En rettelse knyttet til reviewet kræver et nyt build, som jeg forklarer i guiden til guideline 2.1.
Hvordan svarer du på en 2.5.4-afvisning?
Samtalen foregår i App Review-sektionen for din app, hvor du svarer på beskeden fra App Review. To tilfælde:
- Tilstanden bruges ikke til noget: Fjern den, lav et nyt build, tjek introspektionen, og svar så med to sætninger.
- Tilstanden bruges af en reel funktion: Svar med den præcise vej og en kort video, og gentag teksten i review-noterne for hver version.
Den skabelon, jeg ville bruge, til at tilpasse (fjern sætningen om alarmen, hvis din app ikke har en):
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,
Tjeklisten for 2.5.4 før indsendelse
- Expo-introspektionen viser kun de ønskede tilstande, og du kan nævne funktionen for hver af dem.
- Intet plugin er erklæret i kort form, hvis det tilføjer en tilstand som standard, som expo-audio.
- Din lokale
ios/-mappe beholder ingen gamle nøgler, eller du bygger fra et rent prebuild. - Funktionen kan startes hurtigt uden skjulte indstillinger, og review-noterne siger, hvilken tilstand der bruges til hvad, og hvordan den testes.
- Al optagelse kræver udtrykkeligt samtykke og viser en synlig indikator. Reglerne for tilladelsesanmodninger står i guiden til guideline 5.1.1.
- For et vækkeur går alarmen gennem AlarmKit, ikke gennem en lyd afspillet fra appen.
Tjek din app før indsendelsen
Review Kit samler min tjekliste før indsendelse, skabeloner til noter til testeren og Claude Code-skills, der gennemgår dit projekt. Vil du have et menneskeligt blik, så book en time med mig: Vi læser Apples besked og din Info.plist sammen over video. Hele fremgangsmåden står på siden app afvist af Apple.
Forbereder du din første udgivelse? Tag din gratis diagnose: Den sætter trinene i rækkefølge og sender dig min tjekliste mod afvisninger fra Apple.
Ingen kan garantere, at Apple godkender din app. Men en velbegrundet baggrundstilstand kan forsvares på tredive sekunder.
Ofte stillede spørgsmål
Hvad betyder »Guideline 2.5.4 - Performance - Software Requirements«?
Det er overskriften på afvisningen, når Apple mener, at en baggrundstilstand i din Info.plist ikke bruges til sit tiltænkte formål. Beskeden nævner tilstanden og foreslår, at du viser den funktion, der bruger den, eller fjerner nøglen.
Skal jeg lave et nyt build efter en 2.5.4-afvisning?
Hvis du fjerner eller ændrer en tilstand, ja: Nøglen ligger i Info.plist og dermed i den binære fil. Hvis tilstanden er begrundet, kan et svar med den præcise vej og en video være nok.
Kan man beholde audio-tilstanden til nogle få UI-lyde?
Nej. Korte lyde, der afspilles i forgrunden, har ikke brug for den. Med Expo sætter du enableBackgroundPlayback til false i pluginet expo-audio.
Har en vækkeur-app brug for audio-tilstanden?
Ikke for at ringe, hvis den bruger AlarmKit, der findes fra iOS 26: Det er systemet, der afspiller alarmen. På Solys bruges audio-tilstanden til natteaflytningen, der optager med låst skærm.
Hvorfor henviser Apple til 2.5.4, når jeg ikke har erklæret noget?
Måske har et plugin gjort det for dig: expo-audio tilføjer audio-tilstanden som standard, og en gammel ios/-mappe kan beholde en nøgle, du har fjernet fra din konfiguration. Tjek med npx expo config --type introspect.

