Come dovrebbe comportarsi una chiamata VoIP su Android quando l'app non è in primo piano, o addirittura non è in esecuzione? È una domanda che prima o poi chi sviluppa app VoIP/SIP su Android si trova ad affrontare.
Il ruolo dei Foreground Services
Android è sempre più aggressivo nel limitare i processi in background. Per molte applicazioni moderne — VoIP, navigazione, media player — un semplice Service non è più sufficiente.
Il Foreground Service è oggi l'unico contratto esplicito che abbiamo con il sistema operativo per dire: "Sto facendo qualcosa di importante per l'utente. Non uccidermi."
In cambio, Android pretende una notifica persistente, una motivazione chiara e, a partire da Android 12, una giustificazione temporale e funzionale molto più stringente.
Nel caso di una chiamata SIP
Il FGS diventa di fatto obbligatorio: è l'unico modo affidabile per mantenere viva la sessione, gestire l'audio e reagire correttamente agli eventi di chiamata.
Il caso reale: chiamata SIP mentre Flutter non esiste più
Nel mio caso specifico l'architettura è ibrida: UI in Flutter, stack SIP nativo, notifiche in stile CallKit anche quando Flutter è completamente detached. La chiamata può esistere anche quando l'app, di fatto, non esiste più.
Il sistema continua a mantenere il Foreground Service, mostra la notifica e tiene viva la chiamata SIP.
Il dilemma architetturale
Se l'utente killa l'app, è corretto chiudere la chiamata? Dal punto di vista tecnico sarebbe semplice
intercettare la chiusura forzata e terminare la chiamata.
Ma dal punto di vista UX e semantico, la domanda vera è un'altra:
"Chi sta chiudendo cosa? L'utente sta chiudendo l'app o la chiamata?"
Su una telefonata classica, chiudere l'app Telefono non chiude la chiamata. La chiamata è un'entità di sistema. Android separa in modo netto il concetto di processo da quello di funzione.
La scelta
La decisione che ho preso è stata: il kill dell'app non equivale alla fine della chiamata. La chiamata continua finché uno dei peer non riaggancia esplicitamente. Il FGS diventa il vero owner della chiamata. Vive indipendentemente dal lifecycle della UI ed è responsabile del cleanup solo quando la chiamata termina davvero.
Conclusione
I Foreground Services non sono solo un requisito tecnico. Sono una vera e propria presa di responsabilità: "Questa cosa che sto facendo merita di esistere anche se l'utente non mi guarda."
Quando lavori su chiamate, audio e realtime, quella responsabilità va maneggiata con molta attenzione.