Guideline 2.5.4: background mode rifiutato da Apple
Di Mehdi Azizi
Pubblicato il , 9 min
Apple rifiuta un background mode dichiarato senza una funzione che lo usi. Togli la chiave o mostra al reviewer la funzione.
La guideline 2.5.4 limita i background mode al loro uso previsto: audio, posizione, chiamate VoIP, completamento di attività, notifiche locali. Il rifiuto arriva quando il tuo Info.plist dichiara uno di questi mode e il reviewer non trova nessuna funzione che ne abbia bisogno. Togli la chiave se niente la usa, altrimenti mostra la funzione al reviewer in trenta secondi.
Pubblico le mie app iOS con Expo. Solys, la mia sveglia con mini-giochi, dichiara il mode audio: l'ho tolto, poi rimesso per un altro motivo. Questa guida si basa sul testo di Apple, su rifiuti pubblicati da altri sviluppatori e sui miei progetti. Per il quadro generale dei motivi, leggi perché Apple rifiuta un'app.
Cosa dice la guideline 2.5.4?
La regola sta in una frase, nella sezione 2 "Performance", parte 2.5 "Software Requirements", delle App Review Guidelines: "Multitasking apps may only use background services for their intended purposes: VoIP, audio playback, location, task completion, local notifications, etc."
In pratica: un servizio in background serve solo a ciò per cui esiste. Da qui il titolo "Guideline 2.5.4 - Performance - Software Requirements".
Di default, un'app che passa in background viene sospesa. Per continuare a girare, dichiara uno o più mode nella chiave UIBackgroundModes del suo Info.plist. La documentazione di Apple sui background mode chiede di usarli con parsimonia, per via della batteria, e di preferire un'altra soluzione quando esiste. Ogni mode dichiarato è una promessa che il reviewer può verificare.
I background mode e il loro uso previsto
| Mode | Chiave | Uso previsto |
|---|---|---|
| Audio, AirPlay, PiP | audio | Audio udibile in background |
| Posizione | location | Posizione continua |
| Voice over IP | voip | Chiamate con CallKit |
| Background fetch | fetch | Contenuti di rete regolari |
| Background processing | processing | Attività pianificate |
| Notifiche remote | remote-notification | Push di nuovi contenuti |
Questa tabella riassume la pagina di Apple. Nei rifiuti pubblicati sui forum, audio, location e voip sono i più frequenti.
Cosa significa il messaggio di rifiuto 2.5.4?
Il messaggio nomina il mode in questione. Due esempi pubblicati da sviluppatori sui forum di 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." Il seguito precisa che la chiave
audioè pensata per le app che fanno sentire un contenuto in background, come un lettore musicale. Propone due vie d'uscita: aggiungere questo contenuto o togliere la chiave (thread del forum). - Posizione: in un thread di dicembre 2024, Apple non ha trovato nessuna funzione, a parte il tracciamento dei dipendenti, che richieda una posizione continua, e scrive che questo solo uso non è appropriato.
La mia lettura: il reviewer non legge il tuo codice, cerca una funzione. Deve poterla avviare, mandare l'app in background e constatare che continua.
Esiste anche il caso opposto. In un thread di maggio 2026, un'app di lettura ad alta voce, che usava davvero il mode audio, è stata rifiutata più volte: il reviewer non riusciva ad attivare l'audio. Un altro sviluppatore scrive lì che, secondo lui, un video allegato ha sbloccato il suo caso. È una testimonianza, non una regola di Apple.
Da dove viene la chiave se non l'hai aggiunta tu?
Con Expo, sono i config plugin a riempire l'Info.plist durante il prebuild. Un background mode può quindi finire nel tuo binario senza che tu l'abbia deciso.
Il plugin expo-audio, con le impostazioni di default
La documentazione di expo-audio lo dice: l'opzione enableBackgroundPlayback vale true di default e, su iOS, aggiunge il mode audio. Dichiarare il plugin nella forma breve, "expo-audio", basta quindi a dichiarare il mode.
È quello che ho trovato rileggendo TradaZen prima del primo invio: brevi suoni di interfaccia in primo piano, ma un plugin dichiarato in forma breve. La correzione sta in app.json:
{
"expo": {
"plugins": [["expo-audio", { "enableBackgroundPlayback": false }]]
}
}
Altri pacchetti aggiungono un mode a modo loro. L'opzione isIosBackgroundLocationEnabled di expo-location aggiunge location solo se la attivi. expo-background-task, invece, aggiunge processing al prebuild appena è installato.
La cartella ios/ che conserva la vecchia chiave
Seconda trappola, vissuta su Solys a luglio 2026. Avevo tolto audio da app.json, ma la chiave restava in ios/Solys/Info.plist, generato in precedenza. Un prebuild senza --clean modifica quel progetto invece di ricrearlo, e il plugin aggiunge la chiave senza mai toglierla. Una build locale l'avrebbe inclusa. Una build EAS nel cloud riparte da un prebuild nuovo quando ios/ è ignorata da git, che era il mio caso.
Prima di ogni build, controllo cosa partirà davvero:
npx expo config --type introspect --json | grep -o '"UIBackgroundModes":\[[^]]*\]'
npx expo prebuild --clean --platform ios
Il primo elenca i mode che il prebuild scriverà nell'Info.plist. Il secondo ricrea il progetto nativo per una build locale, cancellando la cartella ios/. Su Solys, il primo mostra "UIBackgroundModes":["audio"], su TradaZen niente: entrambi voluti.
Aggiungere o togliere un mode modifica l'Info.plist, quindi il binario: serve una nuova build, un aggiornamento remoto non basta. La documentazione di EAS Update mette queste modifiche tra quelle che richiedono un nuovo binario, come per ITMS-90683.
Solys: un mode audio dichiarato, con un motivo vero
Solys è una sveglia, ma il mode audio non serve a far suonare l'allarme: la suoneria passa da AlarmKit, il servizio di allarme di Apple disponibile da iOS 26 (documentazione AlarmKit). È il sistema a suonare, anche in modalità silenziosa, non l'app.
La storia della chiave, perché il ragionamento conta più della riga:
- A fine luglio 2026 la tolgo. Niente riproduceva audio in background: gli effetti sonori dei mini-giochi restano in primo piano, e l'allarme non dipende dall'app.
- Due giorni dopo la rimetto, con l'ascolto della notte. Questa opzione registra i rumori della tua notte col microfono e li analizza sull'iPhone. La registrazione deve continuare a schermo bloccato, e la documentazione di expo-audio indica che anche l'opzione di registrazione in background aggiunge il mode
audio.
La giustificazione ha cambiato natura: il mode serve a registrare, non a riprodurre. Tre paletti, visibili nell'app:
- l'ascolto è un'opzione disattivata di default, che si attiva dalle impostazioni o dal rituale della sera;
- ha una sua schermata di consenso, come richiede la regola 2.5.14 per qualsiasi registrazione, e niente lascia il telefono;
- il microfono si chiude dieci minuti prima dell'allarme, così ascolto e suoneria non si intralciano mai.
Non posso garantire che un reviewer accetterà sempre questa dichiarazione. So dire, per ogni elemento, a cosa serve e dove vederlo.
Le sveglie che tenevano l'app sveglia
Prima di AlarmKit, una sveglia di terze parti non poteva suonare come l'allarme di Apple. Alcune librerie tenevano quindi l'app attiva: la documentazione del pacchetto Flutter alarm2 descrive un player audio silenzioso che gira fino all'allarme. Ma un audio muto non fa sentire niente. Da iOS 26, AlarmKit rende inutile questa scorciatoia.
Tenere o togliere il mode: la griglia di decisione
| La tua situazione | Cosa fare |
|---|---|
| Suoni brevi in primo piano | Togliere audio |
| Musica o audiolibro | Tenerlo, mostrarlo |
| Registrazione lunga | Tenerlo + consenso |
| Sveglia o timer | AlarmKit (iOS 26) |
| Posizione ogni tanto | Cambiamenti significativi |
| Sincronizzazione non urgente | fetch o processing |
| Chiamate audio o video | voip con CallKit |
Per la posizione, la pagina di Apple cita il servizio dei cambiamenti significativi di posizione come alternativa al mode location.
Gli altri commi della 2.5: 2.5.1 e 2.5.2
2.5.1: API pubbliche e framework al loro posto
"Apps may only use public APIs and must run on the currently shipping OS." L'app usa solo API pubbliche, gira sulla versione attuale del sistema e abbandona ciò che è deprecato. Come per la 2.5.4, ogni framework serve al suo uso previsto, indicato nella descrizione: HealthKit per la salute, HomeKit per la casa connessa. Se una libreria chiama un'API privata, è la tua app a prendersi il rifiuto.
2.5.2: niente codice scaricato che cambia l'app
L'app resta autonoma nel suo pacchetto. Non può "download, install, or execute code which introduces or changes features or functionality of the app". Solo le app educative che insegnano a programmare hanno un'eccezione limitata, con un codice interamente visibile e modificabile dall'utente.
Con Expo, la questione tocca EAS Update, la cui documentazione ricorda che gli aggiornamenti devono rispettare le regole dell'App Store. Usa gli aggiornamenti remoti per correggere, mai per consegnare una funzione che il reviewer non ha visto. Una correzione legata alla revisione passa da una nuova build, come spiego nella guida alla guideline 2.1.
Come rispondere a un rifiuto 2.5.4?
La conversazione si svolge nella sezione App Review della tua app, dove rispondi al messaggio di App Review. Due casi:
- Il mode non serve a niente: toglilo, rifai una build, controlla l'introspection, poi rispondi in due frasi.
- Il mode serve a una funzione vera: rispondi col percorso esatto e un breve video, poi riprendi questo testo nelle note di revisione di ogni versione.
Il modello che userei, da adattare (togli la frase sull'allarme se la tua app non ne ha):
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,
La checklist 2.5.4 prima dell'invio
- L'introspection di Expo mostra solo i mode voluti, e sai nominare la funzione di ognuno.
- Nessun plugin è dichiarato in forma breve se aggiunge un mode di default, come expo-audio.
- La tua cartella
ios/locale non conserva nessuna vecchia chiave, oppure compili da un prebuild pulito. - La funzione si attiva in fretta, senza impostazioni nascoste, e le note di revisione dicono quale mode serve a cosa e come testarlo.
- Ogni registrazione chiede un consenso esplicito e mostra un indicatore visibile. Le regole sulle richieste di autorizzazione sono nella guida alla guideline 5.1.1.
- Per una sveglia, la suoneria passa da AlarmKit, non da un audio riprodotto dall'app.
Controllare il tuo pacchetto prima dell'invio
Il Review Kit riunisce la mia checklist pre-invio, modelli di note per il tester e skill di Claude Code che rileggono il tuo progetto. Per uno sguardo umano, prenota un'ora con me: leggiamo insieme il messaggio di Apple e il tuo Info.plist, in videochiamata. Il percorso completo è nella pagina app rifiutata da Apple.
Stai preparando la tua prima uscita? Fai la tua diagnosi gratuita: rimette in ordine i passaggi e ti manda la mia checklist anti-rifiuto Apple.
Nessuno può garantire che Apple accetterà la tua app. Un background mode ben giustificato, però, si difende in trenta secondi.
Domande frequenti
Cosa significa "Guideline 2.5.4 - Performance - Software Requirements"?
È il titolo del rifiuto quando Apple ritiene che un background mode del tuo Info.plist non serva al suo uso previsto. Il messaggio nomina il mode e propone di mostrare la funzione che lo usa o di togliere la chiave.
Serve una nuova build dopo un rifiuto 2.5.4?
Se togli o modifichi un mode, sì: la chiave è nell'Info.plist, quindi nel binario. Se il mode è giustificato, può bastare una risposta col percorso esatto e un video.
Si può tenere il mode audio per qualche suono di interfaccia?
No. Suoni brevi riprodotti in primo piano non ne hanno bisogno. Con Expo, imposta enableBackgroundPlayback su false nel plugin expo-audio.
Un'app sveglia ha bisogno del mode audio?
Non per suonare, se si appoggia ad AlarmKit, disponibile da iOS 26: è il sistema a riprodurre l'allarme. Su Solys, il mode audio serve all'ascolto della notte, che registra a schermo bloccato.
Perché Apple cita la 2.5.4 se non ho dichiarato niente?
Forse l'ha fatto un plugin al posto tuo: expo-audio aggiunge il mode audio di default, e una vecchia cartella ios/ può conservare una chiave tolta dalla tua configurazione. Controlla con npx expo config --type introspect.

