@bear-block/callx
v3.0.1
Published
Native call coordination for React Native using CallKit and Android Core-Telecom
Maintainers
Readme
@bear-block/callx
Native incoming and outgoing calls for React Native and Expo: iOS CallKit, Android Core-Telecom, VoIP and FCM push handling, and crash recovery in one shared native core. Calls ring even when your app is not running, answers are never lost on the lock screen, and cancelled calls never ring again.
Documentation · React Native quick start · Expo quick start · API reference · Status
Features
- Native owns the call. Pushes are received, reported to CallKit or Telecom, and every answer and hang-up is recorded natively, before the JavaScript bundle loads.
- Rings only when it should. Duplicate, expired, busy and already-cancelled invitations never ring; unanswered calls end at a ring deadline.
- Recovery built in. A durable journal, idempotent commands with explicit results, and replayable events after a crash, a reload or a reboot.
- Expo with no native code. The config plugin bootstraps the core and generates the FCM service, compatible with React Native Firebase.
- Bring your own backend and media. No hosted service and no Firebase or media dependency. Add
@bear-block/callx-livekitfor LiveKit audio and video with no native code. - New Architecture. A typed TurboModule, with a fallback for the legacy architecture.
- Phone features. Speaker, earpiece and headset switching, keypad tones (DTMF), caller-name updates, and call back from iOS Recents/Siri and Android missed-call notifications (guide).
- Private by default. MIT licensed, no telemetry.
Requirements
| | Minimum |
|---|---|
| React Native | 0.76 (React 18) |
| Expo | SDK 57, development build (not Expo Go) |
| iOS | 15.0, built with Xcode 26 or later |
| Android | API 29 (minSdkVersion = 29) |
Install with Expo
npx expo install @bear-block/callx{
"expo": {
"plugins": [
["@bear-block/callx/app.plugin", {
"microphonePermission": "Example uses the microphone for calls.",
"iosVoip": true,
"androidNotifications": true,
"androidPush": "fcm"
}]
]
}
}Then npx expo prebuild and npx expo run:ios / npx expo run:android. Every option is in the
plugin reference.
Install with React Native CLI
npm install @bear-block/callx
cd ios && pod installSet minSdkVersion = 29, enable Push Notifications and the Audio and Voice over IP
background modes on iOS, and bootstrap the core from native code:
// Android: MainApplication.onCreate
CallxModule.bootstrap(this)// iOS: application(_:didFinishLaunchingWithOptions:)
try CallxReactNativeHost.bootstrap(CallxBootstrapConfig())On Android, forward FCM messages from your messaging service to
CallxBootstrap.started?.ingress?.handlePush(...). The
React Native quick start shows every file.
Use it
import {Callx} from '@bear-block/callx';
export const callx = new Callx();
export async function start() {
const capabilities = await callx.setup();
if (!capabilities.nativeCalling) return;
// Send this to your backend so it can push invitations to this device.
const token = await callx.getPushToken(); // {type: 'voip' | 'fcm', token}
return callx.observe(({call}) => {
// call?.state: incoming, outgoing, connecting, active, held, ended
});
}
export async function answer(callId: string) {
const result = await callx.answer(callId);
if (result.status !== 'applied') console.warn(result.error?.message);
}Your backend sends an APNs VoIP push or an FCM data message with a callx invitation; the
backend guide has the exact payloads.
Try it without a backend
import {createCallxPreview} from '@bear-block/callx/preview';
const {callx, simulator} = createCallxPreview();
await callx.setup();
await simulator.incoming({callId: 'demo-1', displayName: 'Alex', handle: 'callx:alex'});
await callx.answer('demo-1'); // connecting
await simulator.mediaConnected(); // activeThe simulator is an explicit opt-in; new Callx() never falls back to it.
Scope
One live call at a time, voice or video, iOS and Android (web runs the simulator only). Callx does not host signaling, send pushes or carry media. See the roadmap and what has been verified on devices.
Support
Callx is free and independent. Sponsoring it funds the maintenance that keeps it working through every iOS and Android release. You can also help by sharing test results from your phone. Need help adding calls to your app? The maintainers take on integration work.
MIT licensed.
Optional call UI
Since 0.2.2, Callx exports CallxCallOverlay, CallxCallScreen, CallxMiniCall and
CallxPresentationController from @bear-block/callx/ui. Mount the overlay above your app UI; incoming
stays on Home until accepted, Back minimizes inside the app, and end removes the call UI.
Colors/logo and command callbacks belong to your app. The controller never changes native
call state. See the call UI guide.
