Skip to content

expo-callkit-telecomCallKit & Core-Telecom for React Native + Expo

One typed API across iOS and Android. VoIP push parsed natively. LiveKit-friendly audio session.

See it in action on iOS and Android

The runnable example/ app drives the system call UI on both platforms — outgoing calls, banner-style incoming calls (while the device is in use), and full-screen incoming calls (when locked).

iOS

Outgoing call
Incoming (banner) on iOS — expo-callkit-telecom demo
Incoming (banner)
Incoming (full screen) on iOS — expo-callkit-telecom demo
Incoming (full screen)

Android

Outgoing call
Incoming (banner) on Android — expo-callkit-telecom demo
Incoming (banner)
Incoming (full screen) on Android — expo-callkit-telecom demo
Incoming (full screen)

Frequently asked questions

What is expo-callkit-telecom?

An Expo module that wraps CallKit on iOS and Jetpack Core-Telecom on Android behind one typed TypeScript API. The module owns the system call UI, the audio session, and VoIP push parsing; your app owns the media.

Does it work with bare React Native, or only Expo?

It's distributed as an Expo module with a config plugin, so the smoothest path is an Expo project (managed or prebuild). Bare React Native apps that have adopted the Expo Modules API can also use it.

How is it different from react-native-callkeep?

react-native-callkeep is built on Android's older ConnectionService API, Objective-C + Java, and leaves VoIP push parsing and RTCAudioSession coordination to the app. This module uses Jetpack androidx.core-telecom (Google's current recommendation), Swift + Kotlin, an Expo config plugin, and parses APNs VoIP and FCM data payloads natively. See vs react-native-callkeep for the full side-by-side.

Does it work with LiveKit?

Yes. The module owns the iOS audio session: it puts WebRTC's RTCAudioSession into manual-audio mode, then activates and deactivates it in lockstep with CallKit (when CallKit activates the session it enables WebRTC audio; when CallKit deactivates, it disables WebRTC audio and restores the pre-call configuration). Because of that, your app should not call LiveKit's AudioSession.startAudioSession() / stopAudioSession() (or otherwise activate AVAudioSession itself) — let the module handle it and wire LiveKit to the events the module emits.

What are the minimum platform versions?

iOS 15.1 and Android API 26 (Android 8.0). The example app is exercised end-to-end against iOS 26 and Android 15 with Expo SDK 55, React Native 0.83, and the New Architecture enabled.

Does it handle incoming calls when the app is terminated?

Yes. APNs VoIP (PushKit) on iOS and FCM data messages on Android are parsed natively before JS is running, so the call is reported to the OS in time for CallKit / Core-Telecom to show the incoming-call UI from a cold start.

Released under the MIT License.