{"id":13882,"library":"react-native-callkeep","title":"React Native CallKeep","description":"React Native CallKeep is a library designed to integrate native iOS CallKit and Android ConnectionService frameworks into React Native applications, facilitating the development of VoIP calling features. It provides a unified JavaScript API for managing the incoming and outgoing call UI, handling call actions like answer and end, and ensuring compliance with platform-specific requirements for background calling and permissions. The current stable version is 4.3.16. While the project shows frequent historical updates, recent analysis from sources like Snyk suggests an 'Inactive' maintenance status with no new npm releases in the past 12 months, and low attention from maintainers. Key differentiators include its comprehensive handling of Android 11's foreground service requirements for background audio and the flexibility of early iOS setup via `AppDelegate.m` for capturing pre-JS bridge events.","status":"maintenance","version":"4.3.16","language":"javascript","source_language":"en","source_url":"https://github.com/react-native-webrtc/react-native-callkeep","tags":["javascript","typescript"],"install":[{"cmd":"npm install react-native-callkeep","lang":"bash","label":"npm"},{"cmd":"yarn add react-native-callkeep","lang":"bash","label":"yarn"},{"cmd":"pnpm add react-native-callkeep","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Peer dependency for core React Native functionalities and bridging.","package":"react-native","optional":false}],"imports":[{"note":"The library primarily exports RNCallKeep as a default export. While CommonJS `require` might work in some transpiled environments, `import` is the idiomatic and recommended approach in modern React Native projects, especially for type inference.","wrong":"const RNCallKeep = require('react-native-callkeep');","symbol":"RNCallKeep","correct":"import RNCallKeep from 'react-native-callkeep';"},{"note":"PermissionsAndroid is a named export from the `react-native` core library, often used in conjunction with CallKeep for requesting necessary phone permissions on Android.","wrong":"import PermissionsAndroid from 'react-native';","symbol":"PermissionsAndroid","correct":"import { PermissionsAndroid } from 'react-native';"},{"note":"For `displayIncomingCall` and other call management functions, a valid UUID is crucial. Using a static string or invalid format will prevent incoming call screens from being shown on iOS.","wrong":"const callUUID = 'some-static-string-id';","symbol":"UUID generation","correct":"import { v4 as uuidv4 } from 'uuid'; // or other UUID library\nconst callUUID = uuidv4();"}],"quickstart":{"code":"import RNCallKeep from 'react-native-callkeep';\nimport { PermissionsAndroid, Platform } from 'react-native';\nimport 'react-native-get-random-values'; // Polyfill for crypto for UUID generation\nimport { v4 as uuidv4 } from 'uuid'; // Recommended UUID library\n\nconst setupCallKeep = async () => {\n  const options = {\n    ios: {\n      appName: 'My VoIP App',\n      imageName: 'callkeep_icon', // Optional: image for system UI\n      maximumCallGroups: 1,\n      maximumCallsPerCallGroup: 1,\n      supportsVideo: false,\n      includesCallsInRecents: true, // Show calls in iOS Recents list\n    },\n    android: {\n      alertTitle: 'Permissions required',\n      alertDescription: 'This application needs to access your phone accounts to manage calls and show caller ID.',\n      cancelButton: 'Cancel',\n      okButton: 'Ok',\n      imageName: 'phone_account_icon', // Make sure this icon exists in your drawable folder\n      additionalPermissions: [\n        PermissionsAndroid.PERMISSIONS.READ_PHONE_STATE,\n        PermissionsAndroid.PERMISSIONS.CALL_PHONE,\n        ...(Platform.Version >= 31 ? [PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT] : []), // For Android 12+ Bluetooth\n      ],\n      foregroundService: {\n        channelId: 'com.mycompany.myapp.callservice',\n        channelName: 'VoIP Call Service',\n        notificationTitle: 'My VoIP App is running in the background for calls',\n        notificationIcon: 'ic_launcher_round', // Ensure this icon exists in your Android resources\n      },\n      selfManaged: false, // Set to true for custom incoming call UI on Android\n      // Additional Android 13+ foreground service permissions\n      // 'android.permission.FOREGROUND_SERVICE_PHONE_CALL',\n    },\n  };\n\n  try {\n    // Request necessary Android permissions before setup\n    if (Platform.OS === 'android') {\n      const granted = await PermissionsAndroid.requestMultiple(options.android.additionalPermissions);\n      const allGranted = Object.values(granted).every(status => status === PermissionsAndroid.RESULTS.GRANTED);\n      if (!allGranted) {\n        console.warn('CallKeep permissions not fully granted.');\n        // You might want to show an alert or prevent app functionality here\n        return;\n      }\n    }\n\n    const accepted = await RNCallKeep.setup(options);\n    if (accepted) {\n      console.log('RNCallKeep setup successfully.');\n      // Example: Register an event listener for answering calls\n      RNCallKeep.addEventListener('answerCall', ({ callUUID }) => {\n        console.log(`Call ${callUUID} answered.`);\n        // Implement your logic to connect the call\n      });\n      // Other event listeners like 'endCall', 'setMutedCall', etc.\n    } else {\n      console.warn('RNCallKeep setup was not accepted by the user or failed.');\n    }\n  } catch (err: any) {\n    console.error('Error setting up RNCallKeep:', err.message);\n  }\n};\n\n// Call the setup function when your app initializes, e.g., in your App.js root component's useEffect\n// useEffect(() => { setupCallKeep(); }, []);\n\n// Example of displaying an incoming call (after setup)\nconst displayExampleIncomingCall = (callerName: string) => {\n  const currentCallUUID = uuidv4();\n  RNCallKeep.displayIncomingCall(\n    currentCallUUID,\n    'remote-caller-id-123',\n    callerName,\n    'Generic',\n    true, // hasVideo\n  );\n  console.log(`Displayed incoming call from ${callerName} with UUID: ${currentCallUUID}`);\n  return currentCallUUID;\n};\n\n// To simulate an incoming call (for testing, after setup is complete):\n// const activeCallId = displayExampleIncomingCall('Jane Doe');\n// To end the call (e.g., after 30 seconds):\n// setTimeout(() => { RNCallKeep.endCall(activeCallId); }, 30000);\n","lang":"typescript","description":"This quickstart initializes React Native CallKeep, configures it for both iOS CallKit and Android ConnectionService with proper permissions and foreground service setup, and demonstrates how to display an incoming call. It includes UUID generation as a best practice."},"warnings":[{"fix":"Refer to the official `MIGRATION_v3_v4.md` guide for detailed steps. Ensure your `RNCallKeep.setup` options include the `foregroundService` configuration for Android 11+ and review all new permission requirements.","message":"Version 4.0.0 introduced significant breaking changes, particularly regarding Android's foreground service and permission handling for background audio on Android 11+.","severity":"breaking","affected_versions":">=4.0.0"},{"fix":"Always deploy and test your application on a physical iOS or Android device to verify CallKeep features.","message":"React Native CallKeep (iOS CallKit and Android ConnectionService) functionality does not work on simulators and requires a physical device for testing.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Include the `foregroundService` object within the `android` options passed to `RNCallKeep.setup()`. This object must specify `channelId`, `channelName`, `notificationTitle`, and a valid `notificationIcon`.","message":"On Android 11 (API 30) and above, a foreground service must be correctly configured and started for the application to maintain audio in the background during a VoIP call.","severity":"gotcha","affected_versions":">=4.0.0"},{"fix":"Choose a single point of initialization for `RNCallKeep.setup()` (either native `AppDelegate.m` for early event capture or JavaScript for simpler integration) and ensure consistency in configuration.","message":"If `RNCallKeep.setup()` is called natively in `AppDelegate.m` on iOS, any subsequent calls to `RNCallKeep.setup()` from JavaScript will be ignored.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always generate a valid, unique UUID for each call using a dedicated UUID library (e.g., `uuid` npm package) before calling `displayIncomingCall`.","message":"Invalid UUIDs or non-unique UUIDs for calls can lead to `displayIncomingCall` failing silently or causing unexpected behavior, especially on iOS.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure all required `additionalPermissions` are declared in `AndroidManifest.xml` and dynamically requested using `PermissionsAndroid.requestMultiple` at runtime, particularly before `RNCallKeep.setup()`.","message":"Specific Android permissions (e.g., `READ_PHONE_STATE`, `CALL_PHONE`, `BLUETOOTH_CONNECT` for Android 12+) are essential. Incorrectly requesting or missing these permissions can cause crashes or prevent call functionality.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"search_vec":"'11':112 '12':97 '4.3.16':70 'action':47 'analysi':79 'android':17,111 'answer':49 'api':36 'appdelegate.m':128 'applic':23 'attent':101 'audio':119 'background':61,118 'bridg':134 'call':29,43,46,62 'callkeep':3,6 'callkit':15 'captur':130 'complianc':54 'comprehens':108 'connectionservic':18 'current':66 'design':10 'develop':26 'differenti':105 'earli':124 'end':51 'ensur':53 'event':135 'facilit':24 'featur':30 'flexibl':122 'foreground':114 'framework':19 'frequent':75 'handl':45,109 'histor':76 'inact':86 'includ':106 'incom':40 'integr':12 'io':14,125 'javascript':35,136 'js':133 'key':104 'librari':9 'like':48,82 'low':100 'maintain':103 'mainten':87 'manag':38 'month':98 'nativ':2,5,13,22 'new':91 'npm':92 'outgo':42 'past':96 'permiss':64 'platform':57 'platform-specif':56 'pre':132 'pre-j':131 'project':73 'provid':32 'react':1,4,21 'recent':78 'releas':93 'requir':59,116 'servic':115 'setup':126 'show':74 'snyk':83 'sourc':81 'specif':58 'stabl':67 'status':88 'suggest':84 'typescript':137 'ui':44 'unifi':34 'updat':77 'version':68 'via':127 'voip':28","created_at":"2026-04-20T01:56:47.647213+00:00","updated_at":"2026-04-20T01:56:47.647213+00:00","problems":[{"fix":"Test the application on a physical iOS or Android device. Ensure a valid, unique UUID is generated and passed to `displayIncomingCall`.","cause":"The library's core features rely on native device capabilities not present in emulators/simulators, or an invalid UUID was provided.","error":"CallKit/ConnectionService not working / Incoming call screen not showing on device."},{"fix":"Verify that all required permissions are declared in `AndroidManifest.xml` and requested at runtime via `PermissionsAndroid`. For Android 11+, ensure the `foregroundService` options are correctly set in `RNCallKeep.setup()`.","cause":"Insufficient or improperly handled Android permissions, or the foreground service for background operation is not correctly configured.","error":"Android app crashes or behaves unexpectedly after permissions are denied, or when app is in background/killed state."},{"fix":"Check your `AndroidManifest.xml` for `FOREGROUND_SERVICE` declarations and ensure they align with the expected types. Review `react-native-callkeep` documentation or migration guides for the correct `foregroundServiceType` flags, which often include `phoneCall` and possibly `microphone`.","cause":"Incorrect `foregroundServiceType` flags specified in `AndroidManifest.xml` (or inferred by newer Android SDK versions) that conflict with CallKeep's use of foreground services.","error":"Error: 'camera|microphone' is incompatible with attribute foregroundServiceType (attr) flags [...]"},{"fix":"Run `npx pod-install` in your `ios` directory, `npm install` or `yarn install`, then clear Metro cache (`npm start --reset-cache`). Verify manual linking steps for older React Native versions if automatic linking fails.","cause":"The native module is not correctly linked with the React Native bridge, or a Metro cache issue.","error":"TypeError: RNCallKeep.setup is not a function (or 'undefined is not an object (evaluating 'RNCallKeep.setup')')"},{"fix":"For versions of Android where this is problematic, you might need to manually bring the app to the foreground after answering, potentially using a combination of `backToForeground()` if exposed by CallKeep, or external libraries like `react-native-incall-manager` or `react-native-background-actions` to manage app state more aggressively. Ensure `selfManaged: false` is set in your setup unless you intend to provide a fully custom UI.","cause":"This is a common behavior/issue with `ConnectionService` on some Android versions where the native call UI can override the app's foregrounding logic.","error":"On Android, after answering a call, the app goes to the background, but the CallKeep UI remains on top or the app doesn't come to the foreground."}],"ecosystem":"npm","meta_description":null,"install_score":null,"quickstart_score":null,"quickstart_tag":null,"pypi_latest":null,"cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/react-native-webrtc/react-native-callkeep","docs":null,"changelog":null,"pypi":null,"npm":"https://www.npmjs.com/package/react-native-callkeep","openapi_spec":null,"status_page":null,"smithery":null,"categories":["communication","http-networking"],"base_url":null,"auth_type":null,"provenance":{"verified_status":null,"verified_at":null,"last_verified":"2026-06-17","next_check":"2026-07-18","install_tag":null}}