Architecture

Mobile SIP Apps & the Background-Running Challenge

Running a SIP softphone on a phone (iOS or Android) sounds simple but is fundamentally hard. Mobile OSes aggressively suspend background apps to save battery, which kills SIP REGISTER refreshes and inbound INVITE delivery. Modern mobile SIP apps work around this with push notifications and OS-specific wake-up paths — not by keeping the SIP socket alive.

Why a 'normal' SIP softphone fails on mobile

The fix is not 'fight harder to stay alive'. The fix is 'don't try to stay connected; use OS push to wake up only when there's a call'.

The push-based architecture (the way it actually works)

  1. App registers with the SIP server using SIP outbound (RFC 5626) and a Path: header containing a push-token reference.
  2. SIP server stores: extension ↔ push token mapping.
  3. Inbound call arrives. Server tries normal SIP delivery first.
  4. If the app's TCP socket is dead, server sends a push notification (APNs on iOS, FCM on Android) carrying the call info.
  5. OS wakes the app. App restores SIP socket and replies to the INVITE within the push timeout (~30s).
  6. Call rings.

iOS-specific: PushKit + CallKit

iOS has a special class of high-priority pushes called VoIP pushes (PushKit). They wake the app silently, with no user-visible notification, specifically for incoming calls. Apple gates this by requiring you to use CallKit — the system call UI — for every push received, otherwise the app is permanently revoked from VoIP push.

This means iOS SIP apps must:

Apple monitors compliance — an app that receives a VoIP push and doesn't show CallKit gets its push entitlement revoked.

Android-specific: FCM + ConnectionService

Android uses FCM (Firebase Cloud Messaging) for push. High-priority pushes wake the app with ~10s of network access — usually enough to receive an INVITE and answer.

The system call UI equivalent of CallKit is ConnectionService (since Android 6) and Telecom framework. Required for showing native call UI, integrating with bluetooth headsets, and being treated as a real call (do-not-disturb, etc.).

Android pitfalls:

Server-side support

For push wake-up to work, your SIP server must:

Most modern SIP stacks support this:

Why some 'free SIP apps' don't ring reliably

Apps like Zoiper free, Linphone, and Bria (without push module) keep the SIP socket alive only while in foreground. As soon as the app backgrounds, calls stop ringing. They work fine for placing outbound, but inbound is unreliable. For dependable inbound on mobile, use:

End-to-end architecture (recommended)

[Mobile app] <==FCM/APNs==> [Push gateway] <==SIP==> [SIP server / PBX] <==SIP==> [DIDHub trunk] <== PSTN ==

Idle state:
  Mobile app NOT connected to SIP server.
  Push gateway holds the push token.

Inbound call:
  PSTN -> DIDHub -> PBX -> "extension is registered with push token X"
  PBX -> push gateway -> APNs/FCM -> phone OS -> wakes app
  App reconnects SIP, answers INVITE, audio flows.

Battery cost

A push-only architecture uses ~<1% battery per day for SIP. A keep-socket-alive architecture uses 5-15% per day and frequently fails. Push wins on every axis.

Related terms

Ready to get a number?

Pick a DID in 130+ countries from $1.99/month. Activates instantly on most numbers.