Skip to content
AI Voice Agents
AI Voice Agents10 min0 views

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.

Try Live Demo →
  • 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

Try the Android client at /demo, browse plans at /pricing, or start a /trial.

Share

Try CallSphere AI Voice Agents

See how AI voice agents work for your industry. Live demo available -- no signup required.