@kaleem766/react-native-incoming-call
v0.1.0
Published
React Native incoming call UI for Android and iOS, built with Nitro Modules
Maintainers
Readme
react-native-incoming-call
Full-screen incoming call UI for React Native — works on foreground, background, and lock screen on Android. Built on Nitro Modules for maximum native performance.
Features
- Full-screen incoming call activity shown above the lock screen
- Wakes the device screen and dismisses the keyguard automatically
- Works in foreground, background, and killed-app states
- Foreground service keeps the call alive when the app is not running
- Answer / Reject buttons with event callbacks to JavaScript
- Auto-timeout with configurable duration
- Customisable caller name, avatar, background colour, and call type
- Inline
IncomingCallViewNitro View for embedding in your own React Native screen - Event-driven API — subscribe with a simple
addEventListener/ cleanup function
Platform support
| Platform | Support | |----------|---------| | Android | ✅ Full support | | iOS | 🔜 Planned (CallKit) |
Installation
# npm
npm install react-native-incoming-call react-native-nitro-modules
# yarn
yarn add react-native-incoming-call react-native-nitro-modulesreact-native-nitro-modules is a required peer dependency.
Android permissions
The library merges its own AndroidManifest.xml automatically. If you need to declare them manually, add the following to your app's AndroidManifest.xml:
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
<uses-permission android:name="android.permission.VIBRATE" />Quick start
import IncomingCall from 'react-native-incoming-call';
// Show the incoming call screen (from a push notification handler, etc.)
await IncomingCall.display({
uuid: 'call-abc-123',
callerName: 'John Doe',
avatar: 'https://example.com/avatar.jpg',
callType: 'audio', // 'audio' | 'video'
backgroundColor: '#1A1A2E',
timeout: 20000, // auto-reject after 20 s
});API reference
IncomingCall.display(options)
Starts the foreground service and launches the full-screen call activity.
IncomingCall.display({
uuid: string; // unique call ID (required)
callerName: string; // caller display name (required)
avatar?: string; // remote avatar URL
callType?: 'audio' | 'video'; // defaults to 'audio'
backgroundColor?: string; // hex colour, e.g. '#1A1A2E'
timeout?: number; // ms before auto-reject, default 30000
}): Promise<void>IncomingCall.answer(uuid)
Programmatically answer the call and emit onAnswer.
await IncomingCall.answer('call-abc-123');IncomingCall.reject(uuid)
Programmatically reject the call and emit onReject.
await IncomingCall.reject('call-abc-123');IncomingCall.end(uuid)
End an active call and stop the foreground service.
await IncomingCall.end('call-abc-123');IncomingCall.addEventListener(event, listener)
Subscribe to a call lifecycle event. Returns an unsubscribe function.
const unsubscribe = IncomingCall.addEventListener('onAnswer', (data) => {
console.log('Answered:', data.uuid, data.timestamp);
});
// later…
unsubscribe();| Event | When fired |
|-------|-----------|
| onAnswer | User taps Accept or answer() is called |
| onReject | User taps Decline or reject() is called |
| onTimeout | Timeout elapsed with no user action |
IncomingCall.removeEventListener(event, listener)
Alternative to calling the returned unsubscribe function.
IncomingCall.removeEventListener('onAnswer', myListener);Event data shape
interface IncomingCallEventData {
uuid: string; // the call ID passed to display()
timestamp: number; // Unix epoch ms
}IncomingCallView (Nitro View)
Embed an inline call UI inside your own React Native screen (foreground use-case).
import { IncomingCallView } from 'react-native-incoming-call';
<IncomingCallView
color="#1A1A2E"
callerName="John Doe"
callType="audio"
style={{ width: '100%', height: 220, borderRadius: 16 }}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| color | string | "#1A1A2E" | Background colour (hex) |
| callerName | string | — | Caller display name |
| avatar | string | — | Avatar URL |
| callType | string | "audio" | "audio" or "video" |
| timeout | number | 30000 | Auto-reject timeout (ms) |
Methods (via ref):
const ref = useRef<IncomingCallViewRef>(null);
ref.current?.answerCall();
ref.current?.rejectCall();Full example
import React, { useEffect } from 'react';
import { Button } from 'react-native';
import IncomingCall from 'react-native-incoming-call';
export default function App() {
useEffect(() => {
const unsubAnswer = IncomingCall.addEventListener('onAnswer', (d) => console.log('answered', d.uuid));
const unsubReject = IncomingCall.addEventListener('onReject', (d) => console.log('rejected', d.uuid));
const unsubTimeout = IncomingCall.addEventListener('onTimeout', (d) => console.log('timeout', d.uuid));
return () => {
unsubAnswer();
unsubReject();
unsubTimeout();
};
}, []);
const call = () =>
IncomingCall.display({
uuid: `call-${Date.now()}`,
callerName: 'Jane Smith',
callType: 'video',
backgroundColor: '#0D1B2A',
timeout: 15000,
});
return <Button title="Simulate Incoming Call" onPress={call} />;
}See the example/ directory for the full working demo app.
Architecture
react-native-incoming-call
├── src/
│ ├── index.tsx JS/TS public API + event manager
│ └── IncomingCall.nitro.ts Nitro spec (props & methods)
├── android/
│ └── src/main/java/…
│ ├── IncomingCallModule.kt RN bridge — display/answer/reject/end
│ ├── IncomingCallActivity.kt Full-screen lock-screen activity
│ ├── IncomingCallService.kt Foreground service (phoneCall type)
│ ├── IncomingCall.kt HybridIncomingCall Nitro View
│ └── IncomingCallPackage.kt Package registration
└── example/ Demo appCall flow:
JS: IncomingCall.display()
→ IncomingCallModule (Kotlin)
→ IncomingCallService (foreground, keeps alive in background/killed)
→ IncomingCallActivity (lock screen, wake, full-screen UI)
→ user taps Accept / Decline
→ broadcast → IncomingCallModule → JS event (onAnswer / onReject)Requirements
| Requirement | Version | |-------------|---------| | React Native | 0.73+ | | react-native-nitro-modules | 0.35+ | | Android minSdk | 24 (Android 7.0) | | compileSdk | 36 | | Kotlin | 2.0+ |
Contributing
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
Pull requests are welcome. For major changes, please open an issue first.
License
MIT © MuhammadKaleem
Made with create-react-native-library + Nitro Modules
