{"id":13401578,"url":"https://github.com/react-native-webrtc/react-native-incall-manager","last_synced_at":"2025-05-15T06:07:11.791Z","repository":{"id":7046981,"uuid":"56047124","full_name":"react-native-webrtc/react-native-incall-manager","owner":"react-native-webrtc","description":"Handling media-routes/sensors/events during a audio/video chat on React Native","archived":false,"fork":false,"pushed_at":"2025-04-30T16:06:53.000Z","size":328,"stargazers_count":570,"open_issues_count":94,"forks_count":197,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-04-30T16:43:33.483Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/react-native-webrtc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2016-04-12T08:56:36.000Z","updated_at":"2025-04-30T16:02:14.000Z","dependencies_parsed_at":"2023-01-16T19:15:52.744Z","dependency_job_id":"16213711-b6a8-4421-9ad3-2ec9ea7d7af5","html_url":"https://github.com/react-native-webrtc/react-native-incall-manager","commit_stats":{"total_commits":162,"total_committers":38,"mean_commits":"4.2631578947368425","dds":0.4506172839506173,"last_synced_commit":"6d927ef24c6e47c6134177a4bb14a71054f85b65"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-native-webrtc%2Freact-native-incall-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-native-webrtc%2Freact-native-incall-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-native-webrtc%2Freact-native-incall-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/react-native-webrtc%2Freact-native-incall-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/react-native-webrtc","download_url":"https://codeload.github.com/react-native-webrtc/react-native-incall-manager/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254283339,"owners_count":22045140,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:01:04.302Z","updated_at":"2025-05-15T06:07:06.781Z","avatar_url":"https://github.com/react-native-webrtc.png","language":"Java","funding_links":[],"categories":["Java"],"sub_categories":[],"readme":"# react-native-incall-manager\n\n[![npm version](https://badge.fury.io/js/react-native-incall-manager.svg)](https://badge.fury.io/js/react-native-incall-manager)\n[![npm downloads](https://img.shields.io/npm/dm/react-native-incall-manager.svg?maxAge=2592000)](https://img.shields.io/npm/dm/react-native-incall-manager.svg?maxAge=2592000)\n\n\nHandling media-routes/sensors/events during a audio/video chat on React Native\n\n## Purpose:\n\nThe purpose of this module is to handle actions/events during a phone call (audio/video) on `react-native`, ex:\n\n* Manage devices events like wired-headset plugged-in state, proximity sensors and expose functionalities to javascript.\n* Automatically route audio to proper devices based on events and platform API.\n* Toggle speaker or microphone on/off, toggle flashlight on/off\n* Play ringtone/ringback/dtmftone\n\nBasically, it is a telecommunication module which handles most of the requirements when making/receiving/talking with a call.  \n  \nThis module is designed to work with [react-native-webrtc](https://github.com/oney/react-native-webrtc)  \n  \n## TODO / Contribution Wanted:  \n  \n* Make operations run on the main thread. ( iOS/Android )  \n* Fix iOS audio shared instance singleton conflict with internal webrtc.  \n* Detect hardware button press event and react to it.  \n  ex: press bluetooth button, send an event to JS to answer/hangup.  \n  ex: press power button to mute incoming ringtone.  \n* Use config-based to decide which event should start and report. maybe control behavior as well.  \n* Flash API on Android.  \n  \n## Installation:\n\n**From npm package**: `npm install react-native-incall-manager`  \n**From git package**: `npm install git://github.com/zxcpoiu/react-native-incall-manager.git`  \n\n===================================================\n### Android:\n  \nnote: you might need `android.permission.BLUETOOTH` permisions for Bluetooth to work.\n  \nAfter install, you can use `rnpm` (`npm install rnpm -g`) to link android.  \nuse `react-native link react-native-incall-manager` to link or manually if you like.\n\nWe use android support library v4 to check/request permissions.  \nYou should add `compile \"com.android.support:support-v4:$YOUR_VERSION\"` in `$YOUR_PROJECT/android/app/build.gradle` dependencies on android.  \n\n#### Manually Linking\n\nIf `react-native link` doesn't work, ( see: https://github.com/zxcpoiu/react-native-incall-manager/issues/21#issuecomment-279575516 ) please add it manually in your main project:\n\n1. In `android/app/build.gradle`  \n    Should have a line `compile(project(':react-native-incall-manager'))` in `dependencies {}` section\n\n2. In `android/settings.gradle`  \n    Should have: \n    ```\n    include ':react-native-incall-manager'\n    project(':react-native-incall-manager').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-incall-manager/android')\n    ```\n    \n3. In `MainApplication.java`\n\n    ```java\n    import com.zxcpoiu.incallmanager.InCallManagerPackage;\n    private static List\u003cReactPackage\u003e getPackages() {\n        return Arrays.\u003cReactPackage\u003easList(\n            new MainReactPackage(),\n            new InCallManagerPackage(),\n\n        );\n    }\n    ```\n#### Optional sound files on android\n\nIf you want to use bundled ringtone/ringback/busytone sound instead of system sound,  \nput files in `android/app/src/main/res/raw`  \nand rename file correspond to sound type:  \n\n```\nincallmanager_busytone.mp3  \nincallmanager_ringback.mp3  \nincallmanager_ringtone.mp3 \n```\n\nOn android, as long as your file extension supported by android, this module will load it.\n\n===================================================\n\n### ios:\n\n`react-native link react-native-incall-manager`\n\n#### Using CocoaPods\n\nUpdate the following line with your path to node_modules/ and add it to your Podfile:\n\n`pod 'ReactNativeIncallManager', :path =\u003e '../node_modules/react-native-incall-manager'`\n\n#### Manually Linking\n\nIn case `react-native link` doesn't work,\n\n- Drag `node_modules/react-native-incall-manager/ios/RNInCallManager.xcodeproj` under `\u003cyour_xcode_project\u003e/Libraries`\n- Select `\u003cyour_xcode_project\u003e` --\u003e `Build Phases` --\u003e `Link Binary With Libraries`\n  - Drag `Libraries/RNInCallManager.xcodeproj/Products/libRNInCallManager.a` to `Link Binary With Libraries`\n- Select `\u003cyour_xcode_project\u003e` --\u003e `Build Settings`\n  - In `Header Search Paths`, add `$(SRCROOT)/../node_modules/react-native-incall-manager/ios/RNInCallManager`\n\n#### Clean project if messed up:\n\n  The installation steps are a bit complex, it might be related your xcode version, xcode cache, converting swift version, and your own path configurations. if something messed up, please follow steps below to clean this project, then do it again steps by steps.\n\n  1. Delete all project/directory in xcode related to incall-manager\n  2. Delete `react-native-incall-manager` in node_modules ( rm -rf )\n  3. Xcode -\u003e Product -\u003e clean\n  4. Close xcode\n  5. Run `npm install` again\n  6. Open xcode and try the install process again steps by steps\n\n  If someone knows a simpler way to set this project up, let me know plz.\n\n#### Optional sound files on iOS\n\nIf you want to use bundled ringtone/ringback/busytone sound instead of system sound \n\n1. Add files into your_project directory under your project's xcodeproject root. ( or drag into it as described above. )\n2. Check `copy file if needed`\n3. Make sure filename correspond to sound type:\n\n```\nincallmanager_busytone.mp3\nincallmanager_ringback.mp3 \nincallmanager_ringtone.mp3 \n```\n\nOn ios, we only support mp3 files currently.\n\n## Usage:\n\nThis module implements a basic handle logic automatically, just:\n\n```javascript\nimport InCallManager from 'react-native-incall-manager';\n\n// --- start manager when the chat start based on logics of your app \n// On Call Established:\nInCallManager.start({media: 'audio'}); // audio/video, default: audio\n\n// ... it will also register and emit events ...\n\n// --- On Call Hangup:\nInCallManager.stop();\n// ... it will also remove event listeners ...\n```\n\nIf you want to use ringback:\n\n```javascript\n// ringback is basically for OUTGOING call. and is part of start().\n\nInCallManager.start({media: 'audio', ringback: '_BUNDLE_'}); // or _DEFAULT_ or _DTMF_\n//when callee answered, you MUST stop ringback explicitly:\nInCallManager.stopRingback();\n```\n\nIf you want to use busytone:\n\n```javascript\n// busytone is basically for OUTGOING call. and is part of stop()\n// If the call failed or callee are busing,\n// you may want to stop the call and play busytone\nInCallManager.stop({busytone: '_DTMF_'}); // or _BUNDLE_ or _DEFAULT_\n```\n\nIf you want to use ringtone:\n\n```javascript\n// ringtone is basically for INCOMING call. it's independent to start() and stop()\n// if you receiving an incoming call, before user pick up,\n// you may want to play ringtone to notify user.\nInCallManager.startRingtone('_BUNDLE_'); // or _DEFAULT_ or system filename with extension\n\n// when user pickup\nInCallManager.stopRingtone();\nInCallManager.start();\n\n// or user hangup\nInCallManager.stopRingtone();\nInCallManager.stop();\n\n```\n\nAlso can interact with events if you want:\nSee API section.\n\n```javascript\nimport { DeviceEventEmitter } from 'react-native';\n\nDeviceEventEmitter.addListener('Proximity', function (data) {\n    // --- do something with events\n});\n\n```\n\n\n\n## Automatic Basic Behavior:\n\n**On start:**  \n* Store current settings, set KeepScreenOn flag = true, and register some event listeners.\n* If media type is `audio`, route voice to earpiece, otherwise route to speaker.\n* Audio will enable proximity sensor which is disabled by default if media=video\n* When proximity detects user close to screen, turn off screen to avoid accident touch and route voice to the earpiece.\n* When newly external device plugged, such as wired-headset, route audio to an external device.\n* Optional play ringback\n\n**On stop:**  \n\n* Set KeepScreenOn flag = false, remote event listeners, restore original user settings.\n* Optionally play busytone\n\n## Custom Behavior:  \n\nYou can customize behavior using API/events exposed by this module. See `API` section.\n\nNote: iOS only supports `auto` currently.\n\n## API:\n\n**Methods**\n\n|  Method      |  android |   ios   |  description |\n|  :---  |   :---:  |  :---:  |     :---    |\n| start(`{media: ?string, auto: ?boolean, ringback: ?string}`)   | :smile: | :smile: | start incall manager.\u003c/br\u003e ringback accept non-empty string or it won't play\u003c/br\u003edefault: `{media:'audio', auto: true, ringback: ''}`  |\n| stop(`{busytone: ?string}`)   | :smile: | :smile: | stop incall manager\u003c/br\u003e busytone accept non-empty string or it won't play\u003c/br\u003e default: `{busytone: ''}` |\n| turnScreenOn()   | :smile: | :rage: | force turn screen on |\n| turnScreenOff()   | :smile: | :rage: | force turn screen off |\n| setKeepScreenOn(`enable: ?boolean`)   | :smile: | :smile: | set KeepScreenOn flag = true or false\u003c/br\u003edefault: false |\n| setSpeakerphoneOn(`enable: ?boolean`)   | :smile: | :rage: | toggle speaker ON/OFF once. but not force\u003c/br\u003edefault: false |\n| setForceSpeakerphoneOn(`flag: ?boolean`)   | :smile: | :smile: | true -\u003e force speaker on\u003c/br\u003e false -\u003e force speaker off\u003c/br\u003e null -\u003e use default behavior according to media type\u003c/br\u003edefault: null |\n| setMicrophoneMute(`enable: ?boolean`)   | :smile: | :rage: | mute/unmute micophone\u003c/br\u003edefault: false\u003c/br\u003ep.s. if you use webrtc, you can just use `track.enabled = false` to mute |\n| async getAudioUriJS()   | :smile: | :smile: | get audio Uri path. this would be useful when you want to pass Uri into another module. |\n| startRingtone(`ringtone: string, ?vibrate_pattern: array, ?ios_category: string, ?seconds: number`)   | :smile: | :smile: | play ringtone. \u003c/br\u003e`ringtone`: '_DEFAULT_' or '_BUNDLE_'\u003c/br\u003e`vibrate_pattern`: same as RN, but does not support repeat\u003c/br\u003e`ios_category`: ios only, if you want to use specific audio category\u003c/br\u003e`seconds`: android only, specify how long do you want to play rather than play once nor repeat. in sec.|\n| stopRingtone()   | :smile: | :smile: | stop play ringtone if previous started via `startRingtone()` |\n| stopRingback()   | :smile: | :smile: | stop play ringback if previous started via `start()` |\n| setFlashOn(`enable: ?boolean, brightness: ?number`)  | :rage: | :smile: | set flash light on/off |\n| async getIsWiredHeadsetPluggedIn()  | :rage: | :smile: | return wired headset plugged in state |\n\n\n\n**Events**\n\n|  Event      |  android |   ios   |  description |\n|  :---  |   :---:  |  :---:  |     :---    |\n| 'Proximity'   | :smile: | :smile: | proximity sensor detected changes.\u003cbr\u003edata: `{'isNear': boolean}` |\n| 'WiredHeadset'| :smile: | :smile:  | fire when wired headset plug/unplug\u003cbr\u003edata: `{'isPlugged': boolean, 'hasMic': boolean, 'deviceName': string }` |\n| 'NoisyAudio'  | :smile: | :rage: | see [android doc](http://developer.android.com/reference/android/media/AudioManager.html#ACTION_AUDIO_BECOMING_NOISY).\u003cbr\u003edata: `null` |\n| 'MediaButton' | :smile: | :rage: | when external device controler pressed button. see [android doc](http://developer.android.com/reference/android/content/Intent.html#ACTION_MEDIA_BUTTON) \u003cbr\u003edata: `{'eventText': string, 'eventCode': number }` |\n| 'onAudioFocusChange' | :smile: | :rage: | see [android doc](http://developer.android.com/reference/android/media/AudioManager.OnAudioFocusChangeListener.html#onAudioFocusChange(int)) \u003cbr\u003edata: `{'eventText': string, 'eventCode': number }` |\n\n**NOTE: platform OS always has the final decision, so some toggle API may not work in some cases\nbe careful when customizing your own behavior**\n\n## LICENSE:\n\n**[ISC License](https://opensource.org/licenses/ISC)** ( functionality equivalent to **MIT License** )\n\n## Original Author:\n[![zxcpoiu](https://github.com/zxcpoiu.png)](https://github.com/zxcpoiu)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-native-webrtc%2Freact-native-incall-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freact-native-webrtc%2Freact-native-incall-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freact-native-webrtc%2Freact-native-incall-manager/lists"}