Android FCM + ConnectionService for AI Inbound Calls (2026)
FCM high-priority + Telecom CallsManager is the Android equivalent of PushKit + CallKit for AI voice. Here is how to ship it without losing future push priority.
Android does not have a separate VoIP push channel. You use FCM with high-priority on a data message, and you have a few seconds to show an incoming-call UI through the Telecom framework — or Android deprioritizes your next push.
Background
Firebase Cloud Messaging is the universal push channel on Android. For AI voice agents in 2026, the recipe is: send a high-priority data message, receive it in a service even from Doze, and immediately register an incoming call with the Telecom framework's CallsManager (or legacy ConnectionService for older devices). If you fail to show a UI, FCM will quietly throttle your next high-priority delivery — Google's quota system penalizes apps that abuse the priority lane.
The good news: with Core-Telecom CallsManager (Jetpack, alpha 2023, stable across 2024–2026), the boilerplate is now manageable. The bad news: every OEM (Samsung, Xiaomi, OPPO, Huawei) layers extra battery-optimization on top of stock Android, and you must convince users to whitelist your app or they will miss calls.
Architecture
```mermaid flowchart LR Backend[Voice Agent Backend] -- HTTP v1 API --> FCM[(Firebase FCM)] FCM -- high-priority data --> Device[Android Device] Device -- onMessageReceived --> Service[Foreground Service] Service -- addCall --> CallsManager[Core-Telecom CallsManager] CallsManager -- CallControlScope --> WebRTC[WebRTC PeerConnection] WebRTC -- SRTP --> Gateway[Pion Go gateway 1.23] ```
CallSphere implementation
The Android client across CallSphere's six verticals (real estate, healthcare, behavioral health, legal, salon, insurance) follows the same pattern:
Hear it before you finish reading
Talk to a live CallSphere AI voice agent in your browser — 60 seconds, no signup.
- Real Estate (OneRoof) — High-priority FCM wakes the app, CallsManager surfaces the incoming UI, WebRTC peers the Pion Go gateway 1.23. NATS routes to the 6-container pod (CRM, MLS, calendar, SMS, audit, transcript). See /industries/real-estate.
- Healthcare — Same FCM + Telecom + WebRTC stack with HIPAA-safe opaque IDs. See /industries/healthcare.
- /demo browser path — Skip FCM entirely; runs in Chrome. See /demo.
37 agents · 90+ tools · 115+ DB tables · 6 verticals · HIPAA + SOC 2 · $149/$499/$1499 · 14-day /trial · 22% affiliate at /affiliate.
Build steps with code
```kotlin class VoiceMessagingService : FirebaseMessagingService() { override fun onMessageReceived(message: RemoteMessage) { val callId = message.data["call_id"] ?: return val from = message.data["from"] ?: "AI Agent"
// Start a foreground service so we have time to attach to Telecom
val intent = Intent(this, IncomingCallService::class.java).apply {
putExtra("call_id", callId); putExtra("from", from)
}
ContextCompat.startForegroundService(this, intent)
} }
class IncomingCallService : Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { startForeground(NOTIF_ID, buildPlaceholderNotification(), ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL)
val callsManager = CallsManager(this)
val attrs = CallAttributesCompat(
displayName = intent?.getStringExtra("from") ?: "AI Agent",
address = Uri.parse("voice:agent"),
direction = CallAttributesCompat.DIRECTION_INCOMING,
callType = CallAttributesCompat.CALL_TYPE_AUDIO_CALL,
)
CoroutineScope(Dispatchers.Main).launch {
callsManager.addCall(attrs,
onAnswer = { startWebRTC() },
onDisconnect = { stopSelf() })
}
return START_NOT_STICKY
} } ```
```xml
Still reading? Stop comparing — try CallSphere live.
CallSphere ships complete AI voice agents per industry — 14 tools for healthcare, 10 agents for real estate, 4 specialists for salons. See how it actually handles a call before you book a demo.
Backend: use the FCM HTTP v1 API with `"priority": "high"` and a `data` payload (no `notification` block — that one goes through display channels and gets coalesced).
Pitfalls
- Sending notification payloads instead of data payloads — display payloads cannot wake a Doze-mode app; only data payloads can.
- Skipping the phoneCall foreground service type — Android 14+ rejects the service start.
- Failing to show a call UI within seconds — Google's FCM throttles future high-priority deliveries.
- Battery optimizations from OEMs — Samsung's "Sleeping Apps" list silently kills FCM; you must guide users to whitelist.
- Forgetting MANAGE_OWN_CALLS permission — CallsManager addCall throws.
FAQ
Why not a regular notification? Notification payloads are deprioritized in Doze; only high-priority data messages wake the app.
How fast is FCM? P50 around 250 ms in 2026; p99 around 2 s on poor networks.
Does it work on devices without Google Services? Push HMS for Huawei or Mi Push for Xiaomi-only markets; the Telecom side is identical.
What if the user is in Do Not Disturb? Telecom respects DND; CallsManager surfaces the UI but mutes the ringtone.
Are call audio routes managed automatically? Yes — CallsManager sets MODE_IN_COMMUNICATION and routes to Bluetooth SCO if connected.
Sources
- https://firebase.google.com/docs/cloud-messaging/concept-options
- https://developer.android.com/develop/connectivity/telecom/voip-app/telecom
- https://github.com/react-native-webrtc/react-native-callkeep
- https://developer.android.com/develop/background-work/services/foreground-services
- https://www.twilio.com/docs/voice/sdks/android/faq
Try the Android client at /demo, browse plans at /pricing, or start a /trial.
Try CallSphere AI Voice Agents
See how AI voice agents work for your industry. Live demo available -- no signup required.